Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.config_unittest.py @ 1c3231aa

History | View | Annotate | Download (22.4 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""Script for unittesting the config module"""
23

    
24

    
25
import unittest
26
import os
27
import tempfile
28
import operator
29

    
30
from ganeti import bootstrap
31
from ganeti import config
32
from ganeti import constants
33
from ganeti import errors
34
from ganeti import objects
35
from ganeti import utils
36
from ganeti import netutils
37
from ganeti import compat
38
from ganeti.cmdlib import instance
39

    
40
from ganeti.config import TemporaryReservationManager
41

    
42
import testutils
43
import mocks
44
import mock
45

    
46

    
47
def _StubGetEntResolver():
48
  return mocks.FakeGetentResolver()
49

    
50

    
51
class TestConfigRunner(unittest.TestCase):
52
  """Testing case for HooksRunner"""
53
  def setUp(self):
54
    fd, self.cfg_file = tempfile.mkstemp()
55
    os.close(fd)
56
    self._init_cluster(self.cfg_file)
57

    
58
  def tearDown(self):
59
    try:
60
      os.unlink(self.cfg_file)
61
    except OSError:
62
      pass
63

    
64
  def _get_object(self):
65
    """Returns an instance of ConfigWriter"""
66
    cfg = config.ConfigWriter(cfg_file=self.cfg_file, offline=True,
67
                              _getents=_StubGetEntResolver)
68
    return cfg
69

    
70
  def _init_cluster(self, cfg):
71
    """Initializes the cfg object"""
72
    me = netutils.Hostname()
73
    ip = constants.IP4_ADDRESS_LOCALHOST
74
    # master_ip must not conflict with the node ip address
75
    master_ip = "127.0.0.2"
76

    
77
    cluster_config = objects.Cluster(
78
      serial_no=1,
79
      rsahostkeypub="",
80
      highest_used_port=(constants.FIRST_DRBD_PORT - 1),
81
      mac_prefix="aa:00:00",
82
      volume_group_name="xenvg",
83
      drbd_usermode_helper="/bin/true",
84
      nicparams={constants.PP_DEFAULT: constants.NICC_DEFAULTS},
85
      ndparams=constants.NDC_DEFAULTS,
86
      tcpudp_port_pool=set(),
87
      enabled_hypervisors=[constants.HT_FAKE],
88
      master_node=me.name,
89
      master_ip=master_ip,
90
      master_netdev=constants.DEFAULT_BRIDGE,
91
      cluster_name="cluster.local",
92
      file_storage_dir="/tmp",
93
      uid_pool=[],
94
      )
95

    
96
    master_node_config = objects.Node(name=me.name,
97
                                      primary_ip=me.ip,
98
                                      secondary_ip=ip,
99
                                      serial_no=1,
100
                                      master_candidate=True)
101

    
102
    bootstrap.InitConfig(constants.CONFIG_VERSION,
103
                         cluster_config, master_node_config, self.cfg_file)
104

    
105
  def _create_instance(self):
106
    """Create and return an instance object"""
107
    inst = objects.Instance(name="test.example.com", disks=[], nics=[],
108
                            disk_template=constants.DT_DISKLESS,
109
                            primary_node=self._get_object().GetMasterNode())
110
    return inst
111

    
112
  def testEmpty(self):
113
    """Test instantiate config object"""
114
    self._get_object()
115

    
116
  def testInit(self):
117
    """Test initialize the config file"""
118
    cfg = self._get_object()
119
    self.failUnlessEqual(1, len(cfg.GetNodeList()))
120
    self.failUnlessEqual(0, len(cfg.GetInstanceList()))
121

    
122
  def testUpdateCluster(self):
123
    """Test updates on the cluster object"""
124
    cfg = self._get_object()
125
    # construct a fake cluster object
126
    fake_cl = objects.Cluster()
127
    # fail if we didn't read the config
128
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_cl, None)
129

    
130
    cl = cfg.GetClusterInfo()
131
    # first pass, must not fail
132
    cfg.Update(cl, None)
133
    # second pass, also must not fail (after the config has been written)
134
    cfg.Update(cl, None)
135
    # but the fake_cl update should still fail
136
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_cl, None)
137

    
138
  def testUpdateNode(self):
139
    """Test updates on one node object"""
140
    cfg = self._get_object()
141
    # construct a fake node
142
    fake_node = objects.Node()
143
    # fail if we didn't read the config
144
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_node,
145
                          None)
146

    
147
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
148
    # first pass, must not fail
149
    cfg.Update(node, None)
150
    # second pass, also must not fail (after the config has been written)
151
    cfg.Update(node, None)
152
    # but the fake_node update should still fail
153
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_node,
154
                          None)
155

    
156
  def testUpdateInstance(self):
157
    """Test updates on one instance object"""
158
    cfg = self._get_object()
159
    # construct a fake instance
160
    inst = self._create_instance()
161
    fake_instance = objects.Instance()
162
    # fail if we didn't read the config
163
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_instance,
164
                          None)
165

    
166
    cfg.AddInstance(inst, "my-job")
167
    instance = cfg.GetInstanceInfo(cfg.GetInstanceList()[0])
168
    # first pass, must not fail
169
    cfg.Update(instance, None)
170
    # second pass, also must not fail (after the config has been written)
171
    cfg.Update(instance, None)
172
    # but the fake_instance update should still fail
173
    self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_instance,
174
                          None)
175

    
176
  def testUpgradeSave(self):
177
    """Test that any modification done during upgrading is saved back"""
178
    cfg = self._get_object()
179

    
180
    # Remove an element, run upgrade, and check if the element is
181
    # back and the file upgraded
182
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
183
    # For a ConfigObject, None is the same as a missing field
184
    node.ndparams = None
185
    oldsaved = utils.ReadFile(self.cfg_file)
186
    cfg._UpgradeConfig()
187
    self.assertTrue(node.ndparams is not None)
188
    newsaved = utils.ReadFile(self.cfg_file)
189
    # We rely on the fact that at least the serial number changes
190
    self.assertNotEqual(oldsaved, newsaved)
191

    
192
    # Add something that should not be there this time
193
    key = list(constants.NDC_GLOBALS)[0]
194
    node.ndparams[key] = constants.NDC_DEFAULTS[key]
195
    cfg._WriteConfig(None)
196
    oldsaved = utils.ReadFile(self.cfg_file)
197
    cfg._UpgradeConfig()
198
    self.assertTrue(node.ndparams.get(key) is None)
199
    newsaved = utils.ReadFile(self.cfg_file)
200
    self.assertNotEqual(oldsaved, newsaved)
201

    
202
    # Do the upgrade again, this time there should be no update
203
    oldsaved = newsaved
204
    cfg._UpgradeConfig()
205
    newsaved = utils.ReadFile(self.cfg_file)
206
    self.assertEqual(oldsaved, newsaved)
207

    
208
    # Reload the configuration again: it shouldn't change the file
209
    oldsaved = newsaved
210
    self._get_object()
211
    newsaved = utils.ReadFile(self.cfg_file)
212
    self.assertEqual(oldsaved, newsaved)
213

    
214
  def testNICParameterSyntaxCheck(self):
215
    """Test the NIC's CheckParameterSyntax function"""
216
    mode = constants.NIC_MODE
217
    link = constants.NIC_LINK
218
    m_bridged = constants.NIC_MODE_BRIDGED
219
    m_routed = constants.NIC_MODE_ROUTED
220
    CheckSyntax = objects.NIC.CheckParameterSyntax
221

    
222
    CheckSyntax(constants.NICC_DEFAULTS)
223
    CheckSyntax({mode: m_bridged, link: "br1"})
224
    CheckSyntax({mode: m_routed, link: "default"})
225
    self.assertRaises(errors.ConfigurationError,
226
                      CheckSyntax, {mode: "000invalid", link: "any"})
227
    self.assertRaises(errors.ConfigurationError,
228
                      CheckSyntax, {mode: m_bridged, link: None})
229
    self.assertRaises(errors.ConfigurationError,
230
                      CheckSyntax, {mode: m_bridged, link: ""})
231

    
232
  def testGetNdParamsDefault(self):
233
    cfg = self._get_object()
234
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
235
    self.assertEqual(cfg.GetNdParams(node), constants.NDC_DEFAULTS)
236

    
237
  def testGetNdParamsModifiedNode(self):
238
    my_ndparams = {
239
        constants.ND_OOB_PROGRAM: "/bin/node-oob",
240
        constants.ND_SPINDLE_COUNT: 1,
241
        constants.ND_EXCLUSIVE_STORAGE: False,
242
        }
243

    
244
    cfg = self._get_object()
245
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
246
    node.ndparams = my_ndparams
247
    cfg.Update(node, None)
248
    self.assertEqual(cfg.GetNdParams(node), my_ndparams)
249

    
250
  def testGetNdParamsInheritance(self):
251
    node_ndparams = {
252
      constants.ND_OOB_PROGRAM: "/bin/node-oob",
253
      }
254
    group_ndparams = {
255
      constants.ND_SPINDLE_COUNT: 10,
256
      }
257
    expected_ndparams = {
258
      constants.ND_OOB_PROGRAM: "/bin/node-oob",
259
      constants.ND_SPINDLE_COUNT: 10,
260
      constants.ND_EXCLUSIVE_STORAGE:
261
        constants.NDC_DEFAULTS[constants.ND_EXCLUSIVE_STORAGE],
262
      }
263
    cfg = self._get_object()
264
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
265
    node.ndparams = node_ndparams
266
    cfg.Update(node, None)
267
    group = cfg.GetNodeGroup(node.group)
268
    group.ndparams = group_ndparams
269
    cfg.Update(group, None)
270
    self.assertEqual(cfg.GetNdParams(node), expected_ndparams)
271

    
272
  def testAddGroupFillsFieldsIfMissing(self):
273
    cfg = self._get_object()
274
    group = objects.NodeGroup(name="test", members=[])
275
    cfg.AddNodeGroup(group, "my-job")
276
    self.assert_(utils.UUID_RE.match(group.uuid))
277
    self.assertEqual(constants.ALLOC_POLICY_PREFERRED, group.alloc_policy)
278

    
279
  def testAddGroupPreservesFields(self):
280
    cfg = self._get_object()
281
    group = objects.NodeGroup(name="test", members=[],
282
                              alloc_policy=constants.ALLOC_POLICY_LAST_RESORT)
283
    cfg.AddNodeGroup(group, "my-job")
284
    self.assertEqual(constants.ALLOC_POLICY_LAST_RESORT, group.alloc_policy)
285

    
286
  def testAddGroupDoesNotPreserveFields(self):
287
    cfg = self._get_object()
288
    group = objects.NodeGroup(name="test", members=[],
289
                              serial_no=17, ctime=123, mtime=456)
290
    cfg.AddNodeGroup(group, "my-job")
291
    self.assertEqual(1, group.serial_no)
292
    self.assert_(group.ctime > 1200000000)
293
    self.assert_(group.mtime > 1200000000)
294

    
295
  def testAddGroupCanSkipUUIDCheck(self):
296
    cfg = self._get_object()
297
    uuid = cfg.GenerateUniqueID("my-job")
298
    group = objects.NodeGroup(name="test", members=[], uuid=uuid,
299
                              serial_no=17, ctime=123, mtime=456)
300

    
301
    self.assertRaises(errors.ConfigurationError,
302
                      cfg.AddNodeGroup, group, "my-job")
303

    
304
    cfg.AddNodeGroup(group, "my-job", check_uuid=False) # Does not raise.
305
    self.assertEqual(uuid, group.uuid)
306

    
307
  def testAssignGroupNodes(self):
308
    me = netutils.Hostname()
309
    cfg = self._get_object()
310

    
311
    # Create two groups
312
    grp1 = objects.NodeGroup(name="grp1", members=[],
313
                             uuid="2f2fadf7-2a70-4a23-9ab5-2568c252032c")
314
    grp1_serial = 1
315
    cfg.AddNodeGroup(grp1, "job")
316

    
317
    grp2 = objects.NodeGroup(name="grp2", members=[],
318
                             uuid="798d0de3-680f-4a0e-b29a-0f54f693b3f1")
319
    grp2_serial = 1
320
    cfg.AddNodeGroup(grp2, "job")
321
    self.assertEqual(set(map(operator.attrgetter("name"),
322
                             cfg.GetAllNodeGroupsInfo().values())),
323
                     set(["grp1", "grp2", constants.INITIAL_NODE_GROUP_NAME]))
324

    
325
    # No-op
326
    cluster_serial = cfg.GetClusterInfo().serial_no
327
    cfg.AssignGroupNodes([])
328
    cluster_serial += 1
329

    
330
    # Create two nodes
331
    node1 = objects.Node(name="node1", group=grp1.uuid, ndparams={},
332
                         uuid="node1-uuid")
333
    node1_serial = 1
334
    node2 = objects.Node(name="node2", group=grp2.uuid, ndparams={},
335
                         uuid="node2-uuid")
336
    node2_serial = 1
337
    cfg.AddNode(node1, "job")
338
    cfg.AddNode(node2, "job")
339
    cluster_serial += 2
340
    self.assertEqual(set(cfg.GetNodeList()),
341
                     set(["node1-uuid", "node2-uuid",
342
                          cfg.GetNodeInfoByName(me.name).uuid]))
343

    
344
    def _VerifySerials():
345
      self.assertEqual(cfg.GetClusterInfo().serial_no, cluster_serial)
346
      self.assertEqual(node1.serial_no, node1_serial)
347
      self.assertEqual(node2.serial_no, node2_serial)
348
      self.assertEqual(grp1.serial_no, grp1_serial)
349
      self.assertEqual(grp2.serial_no, grp2_serial)
350

    
351
    _VerifySerials()
352

    
353
    self.assertEqual(set(grp1.members), set(["node1-uuid"]))
354
    self.assertEqual(set(grp2.members), set(["node2-uuid"]))
355

    
356
    # Check invalid nodes and groups
357
    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
358
      ("unknown.node.example.com", grp2.uuid),
359
      ])
360
    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
361
      (node1.name, "unknown-uuid"),
362
      ])
363

    
364
    self.assertEqual(node1.group, grp1.uuid)
365
    self.assertEqual(node2.group, grp2.uuid)
366
    self.assertEqual(set(grp1.members), set(["node1-uuid"]))
367
    self.assertEqual(set(grp2.members), set(["node2-uuid"]))
368

    
369
    # Another no-op
370
    cfg.AssignGroupNodes([])
371
    cluster_serial += 1
372
    _VerifySerials()
373

    
374
    # Assign to the same group (should be a no-op)
375
    self.assertEqual(node2.group, grp2.uuid)
376
    cfg.AssignGroupNodes([
377
      (node2.uuid, grp2.uuid),
378
      ])
379
    cluster_serial += 1
380
    self.assertEqual(node2.group, grp2.uuid)
381
    _VerifySerials()
382
    self.assertEqual(set(grp1.members), set(["node1-uuid"]))
383
    self.assertEqual(set(grp2.members), set(["node2-uuid"]))
384

    
385
    # Assign node 2 to group 1
386
    self.assertEqual(node2.group, grp2.uuid)
387
    cfg.AssignGroupNodes([
388
      (node2.uuid, grp1.uuid),
389
      ])
390
    cluster_serial += 1
391
    node2_serial += 1
392
    grp1_serial += 1
393
    grp2_serial += 1
394
    self.assertEqual(node2.group, grp1.uuid)
395
    _VerifySerials()
396
    self.assertEqual(set(grp1.members), set(["node1-uuid", "node2-uuid"]))
397
    self.assertFalse(grp2.members)
398

    
399
    # And assign both nodes to group 2
400
    self.assertEqual(node1.group, grp1.uuid)
401
    self.assertEqual(node2.group, grp1.uuid)
402
    self.assertNotEqual(grp1.uuid, grp2.uuid)
403
    cfg.AssignGroupNodes([
404
      (node1.uuid, grp2.uuid),
405
      (node2.uuid, grp2.uuid),
406
      ])
407
    cluster_serial += 1
408
    node1_serial += 1
409
    node2_serial += 1
410
    grp1_serial += 1
411
    grp2_serial += 1
412
    self.assertEqual(node1.group, grp2.uuid)
413
    self.assertEqual(node2.group, grp2.uuid)
414
    _VerifySerials()
415
    self.assertFalse(grp1.members)
416
    self.assertEqual(set(grp2.members), set(["node1-uuid", "node2-uuid"]))
417

    
418
    # Destructive tests
419
    orig_group = node2.group
420
    try:
421
      other_uuid = "68b3d087-6ea5-491c-b81f-0a47d90228c5"
422
      assert compat.all(node.group != other_uuid
423
                        for node in cfg.GetAllNodesInfo().values())
424
      node2.group = "68b3d087-6ea5-491c-b81f-0a47d90228c5"
425
      self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
426
        (node2.uuid, grp2.uuid),
427
        ])
428
      _VerifySerials()
429
    finally:
430
      node2.group = orig_group
431

    
432
  def _TestVerifyConfigIPolicy(self, ipolicy, ipowner, cfg, isgroup):
433
    INVALID_KEY = "this_key_cannot_exist"
434

    
435
    ipolicy[INVALID_KEY] = None
436
    # A call to cluster.SimpleFillIPolicy causes different kinds of error
437
    # depending on the owner (cluster or group)
438
    if isgroup:
439
      errs = cfg.VerifyConfig()
440
      self.assertTrue(len(errs) >= 1)
441
      errstr = "%s has invalid instance policy" % ipowner
442
      self.assertTrue(_IsErrorInList(errstr, errs))
443
    else:
444
      self.assertRaises(AssertionError, cfg.VerifyConfig)
445
    del ipolicy[INVALID_KEY]
446
    errs = cfg.VerifyConfig()
447
    self.assertFalse(errs)
448

    
449
    key = list(constants.IPOLICY_PARAMETERS)[0]
450
    hasoldv = (key in ipolicy)
451
    if hasoldv:
452
      oldv = ipolicy[key]
453
    ipolicy[key] = "blah"
454
    errs = cfg.VerifyConfig()
455
    self.assertTrue(len(errs) >= 1)
456
    self.assertTrue(_IsErrorInList("%s has invalid instance policy" % ipowner,
457
                                   errs))
458
    if hasoldv:
459
      ipolicy[key] = oldv
460
    else:
461
      del ipolicy[key]
462

    
463
    ispeclist = []
464
    if constants.ISPECS_MINMAX in ipolicy:
465
      for k in range(len(ipolicy[constants.ISPECS_MINMAX])):
466
        ispeclist.extend([
467
            (ipolicy[constants.ISPECS_MINMAX][k][constants.ISPECS_MIN],
468
             "%s[%s]/%s" % (constants.ISPECS_MINMAX, k, constants.ISPECS_MIN)),
469
            (ipolicy[constants.ISPECS_MINMAX][k][constants.ISPECS_MAX],
470
             "%s[%s]/%s" % (constants.ISPECS_MINMAX, k, constants.ISPECS_MAX)),
471
            ])
472
    if constants.ISPECS_STD in ipolicy:
473
      ispeclist.append((ipolicy[constants.ISPECS_STD], constants.ISPECS_STD))
474

    
475
    for (ispec, ispecpath) in ispeclist:
476
      ispec[INVALID_KEY] = None
477
      errs = cfg.VerifyConfig()
478
      self.assertTrue(len(errs) >= 1)
479
      self.assertTrue(_IsErrorInList(("%s has invalid ipolicy/%s" %
480
                                      (ipowner, ispecpath)), errs))
481
      del ispec[INVALID_KEY]
482
      errs = cfg.VerifyConfig()
483
      self.assertFalse(errs)
484

    
485
      for par in constants.ISPECS_PARAMETERS:
486
        hasoldv = par in ispec
487
        if hasoldv:
488
          oldv = ispec[par]
489
        ispec[par] = "blah"
490
        errs = cfg.VerifyConfig()
491
        self.assertTrue(len(errs) >= 1)
492
        self.assertTrue(_IsErrorInList(("%s has invalid ipolicy/%s" %
493
                                        (ipowner, ispecpath)), errs))
494
        if hasoldv:
495
          ispec[par] = oldv
496
        else:
497
          del ispec[par]
498
        errs = cfg.VerifyConfig()
499
        self.assertFalse(errs)
500

    
501
    if constants.ISPECS_MINMAX in ipolicy:
502
      # Test partial minmax specs
503
      for minmax in ipolicy[constants.ISPECS_MINMAX]:
504
        for key in constants.ISPECS_MINMAX_KEYS:
505
          self.assertTrue(key in minmax)
506
          ispec = minmax[key]
507
          del minmax[key]
508
          errs = cfg.VerifyConfig()
509
          self.assertTrue(len(errs) >= 1)
510
          self.assertTrue(_IsErrorInList("Missing instance specification",
511
                                         errs))
512
          minmax[key] = ispec
513
          for par in constants.ISPECS_PARAMETERS:
514
            oldv = ispec[par]
515
            del ispec[par]
516
            errs = cfg.VerifyConfig()
517
            self.assertTrue(len(errs) >= 1)
518
            self.assertTrue(_IsErrorInList("Missing instance specs parameters",
519
                                           errs))
520
            ispec[par] = oldv
521
      errs = cfg.VerifyConfig()
522
      self.assertFalse(errs)
523

    
524
  def _TestVerifyConfigGroupIPolicy(self, groupinfo, cfg):
525
    old_ipolicy = groupinfo.ipolicy
526
    ipolicy = cfg.GetClusterInfo().SimpleFillIPolicy({})
527
    groupinfo.ipolicy = ipolicy
528
    # Test partial policies
529
    for key in constants.IPOLICY_ALL_KEYS:
530
      self.assertTrue(key in ipolicy)
531
      oldv = ipolicy[key]
532
      del ipolicy[key]
533
      errs = cfg.VerifyConfig()
534
      self.assertFalse(errs)
535
      ipolicy[key] = oldv
536
    groupinfo.ipolicy = old_ipolicy
537

    
538
  def _TestVerifyConfigClusterIPolicy(self, ipolicy, cfg):
539
    # Test partial policies
540
    for key in constants.IPOLICY_ALL_KEYS:
541
      self.assertTrue(key in ipolicy)
542
      oldv = ipolicy[key]
543
      del ipolicy[key]
544
      self.assertRaises(AssertionError, cfg.VerifyConfig)
545
      ipolicy[key] = oldv
546
    errs = cfg.VerifyConfig()
547
    self.assertFalse(errs)
548
    # Partial standard specs
549
    ispec = ipolicy[constants.ISPECS_STD]
550
    for par in constants.ISPECS_PARAMETERS:
551
      oldv = ispec[par]
552
      del ispec[par]
553
      errs = cfg.VerifyConfig()
554
      self.assertTrue(len(errs) >= 1)
555
      self.assertTrue(_IsErrorInList("Missing instance specs parameters",
556
                                     errs))
557
      ispec[par] = oldv
558
    errs = cfg.VerifyConfig()
559
    self.assertFalse(errs)
560

    
561
  def testVerifyConfig(self):
562
    cfg = self._get_object()
563

    
564
    errs = cfg.VerifyConfig()
565
    self.assertFalse(errs)
566

    
567
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
568
    key = list(constants.NDC_GLOBALS)[0]
569
    node.ndparams[key] = constants.NDC_DEFAULTS[key]
570
    errs = cfg.VerifyConfig()
571
    self.assertTrue(len(errs) >= 1)
572
    self.assertTrue(_IsErrorInList("has some global parameters set", errs))
573

    
574
    del node.ndparams[key]
575
    errs = cfg.VerifyConfig()
576
    self.assertFalse(errs)
577

    
578
    cluster = cfg.GetClusterInfo()
579
    nodegroup = cfg.GetNodeGroup(cfg.GetNodeGroupList()[0])
580
    self._TestVerifyConfigIPolicy(cluster.ipolicy, "cluster", cfg, False)
581
    self._TestVerifyConfigClusterIPolicy(cluster.ipolicy, cfg)
582
    self._TestVerifyConfigIPolicy(nodegroup.ipolicy, nodegroup.name, cfg, True)
583
    self._TestVerifyConfigGroupIPolicy(nodegroup, cfg)
584
    nodegroup.ipolicy = cluster.SimpleFillIPolicy(nodegroup.ipolicy)
585
    self._TestVerifyConfigIPolicy(nodegroup.ipolicy, nodegroup.name, cfg, True)
586

    
587
  # Tests for Ssconf helper functions
588
  def testUnlockedGetHvparamsString(self):
589
    hvparams = {"a": "A", "b": "B", "c": "C"}
590
    hvname = "myhv"
591
    cfg_writer = self._get_object()
592
    cfg_writer._config_data = mock.Mock()
593
    cfg_writer._config_data.cluster = mock.Mock()
594
    cfg_writer._config_data.cluster.hvparams = {hvname: hvparams}
595

    
596
    result = cfg_writer._UnlockedGetHvparamsString(hvname)
597

    
598
    self.assertTrue("a=A" in result)
599
    lines = [line for line in result.split('\n') if line != '']
600
    self.assertEqual(len(hvparams.keys()), len(lines))
601

    
602
  def testExtendByAllHvparamsStrings(self):
603
    all_hvparams = {constants.HT_XEN_PVM: "foo"}
604
    ssconf_values = {}
605
    cfg_writer = self._get_object()
606

    
607
    cfg_writer._ExtendByAllHvparamsStrings(ssconf_values, all_hvparams)
608

    
609
    expected_key = constants.SS_HVPARAMS_PREF + constants.HT_XEN_PVM
610
    self.assertTrue(expected_key in ssconf_values)
611

    
612

    
613
def _IsErrorInList(err_str, err_list):
614
  return any(map(lambda e: err_str in e, err_list))
615

    
616

    
617
class TestTRM(unittest.TestCase):
618
  EC_ID = 1
619

    
620
  def testEmpty(self):
621
    t = TemporaryReservationManager()
622
    t.Reserve(self.EC_ID, "a")
623
    self.assertFalse(t.Reserved(self.EC_ID))
624
    self.assertTrue(t.Reserved("a"))
625
    self.assertEqual(len(t.GetReserved()), 1)
626

    
627
  def testDuplicate(self):
628
    t = TemporaryReservationManager()
629
    t.Reserve(self.EC_ID, "a")
630
    self.assertRaises(errors.ReservationError, t.Reserve, 2, "a")
631
    t.DropECReservations(self.EC_ID)
632
    self.assertFalse(t.Reserved("a"))
633

    
634

    
635
class TestCheckInstanceDiskIvNames(unittest.TestCase):
636
  @staticmethod
637
  def _MakeDisks(names):
638
    return [objects.Disk(iv_name=name) for name in names]
639

    
640
  def testNoError(self):
641
    disks = self._MakeDisks(["disk/0", "disk/1"])
642
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
643
    instance._UpdateIvNames(0, disks)
644
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
645

    
646
  def testWrongNames(self):
647
    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
648
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
649
      (0, "disk/0", "disk/1"),
650
      (1, "disk/1", "disk/3"),
651
      ])
652

    
653
    # Fix names
654
    instance._UpdateIvNames(0, disks)
655
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
656

    
657

    
658
if __name__ == "__main__":
659
  testutils.GanetiTestProgram()