Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.config_unittest.py @ 92070017

History | View | Annotate | Download (21.3 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

    
45

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

    
49

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
339
    def _VerifySerials():
340
      self.assertEqual(cfg.GetClusterInfo().serial_no, cluster_serial)
341
      self.assertEqual(node1.serial_no, node1_serial)
342
      self.assertEqual(node2.serial_no, node2_serial)
343
      self.assertEqual(grp1.serial_no, grp1_serial)
344
      self.assertEqual(grp2.serial_no, grp2_serial)
345

    
346
    _VerifySerials()
347

    
348
    self.assertEqual(set(grp1.members), set(["node1"]))
349
    self.assertEqual(set(grp2.members), set(["node2"]))
350

    
351
    # Check invalid nodes and groups
352
    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
353
      ("unknown.node.example.com", grp2.uuid),
354
      ])
355
    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
356
      (node1.name, "unknown-uuid"),
357
      ])
358

    
359
    self.assertEqual(node1.group, grp1.uuid)
360
    self.assertEqual(node2.group, grp2.uuid)
361
    self.assertEqual(set(grp1.members), set(["node1"]))
362
    self.assertEqual(set(grp2.members), set(["node2"]))
363

    
364
    # Another no-op
365
    cfg.AssignGroupNodes([])
366
    cluster_serial += 1
367
    _VerifySerials()
368

    
369
    # Assign to the same group (should be a no-op)
370
    self.assertEqual(node2.group, grp2.uuid)
371
    cfg.AssignGroupNodes([
372
      (node2.name, grp2.uuid),
373
      ])
374
    cluster_serial += 1
375
    self.assertEqual(node2.group, grp2.uuid)
376
    _VerifySerials()
377
    self.assertEqual(set(grp1.members), set(["node1"]))
378
    self.assertEqual(set(grp2.members), set(["node2"]))
379

    
380
    # Assign node 2 to group 1
381
    self.assertEqual(node2.group, grp2.uuid)
382
    cfg.AssignGroupNodes([
383
      (node2.name, grp1.uuid),
384
      ])
385
    cluster_serial += 1
386
    node2_serial += 1
387
    grp1_serial += 1
388
    grp2_serial += 1
389
    self.assertEqual(node2.group, grp1.uuid)
390
    _VerifySerials()
391
    self.assertEqual(set(grp1.members), set(["node1", "node2"]))
392
    self.assertFalse(grp2.members)
393

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

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

    
427
  def _TestVerifyConfigIPolicy(self, ipolicy, ipowner, cfg, isgroup):
428
    INVALID_KEY = "this_key_cannot_exist"
429

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

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

    
458
    ispeclist = []
459
    if constants.ISPECS_MINMAX in ipolicy:
460
      for k in range(len(ipolicy[constants.ISPECS_MINMAX])):
461
        ispeclist.extend([
462
            (ipolicy[constants.ISPECS_MINMAX][k][constants.ISPECS_MIN],
463
             "%s[%s]/%s" % (constants.ISPECS_MINMAX, k, constants.ISPECS_MIN)),
464
            (ipolicy[constants.ISPECS_MINMAX][k][constants.ISPECS_MAX],
465
             "%s[%s]/%s" % (constants.ISPECS_MINMAX, k, constants.ISPECS_MAX)),
466
            ])
467
    if constants.ISPECS_STD in ipolicy:
468
      ispeclist.append((ipolicy[constants.ISPECS_STD], constants.ISPECS_STD))
469

    
470
    for (ispec, ispecpath) in ispeclist:
471
      ispec[INVALID_KEY] = None
472
      errs = cfg.VerifyConfig()
473
      self.assertTrue(len(errs) >= 1)
474
      self.assertTrue(_IsErrorInList(("%s has invalid ipolicy/%s" %
475
                                      (ipowner, ispecpath)), errs))
476
      del ispec[INVALID_KEY]
477
      errs = cfg.VerifyConfig()
478
      self.assertFalse(errs)
479

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

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

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

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

    
556
  def testVerifyConfig(self):
557
    cfg = self._get_object()
558

    
559
    errs = cfg.VerifyConfig()
560
    self.assertFalse(errs)
561

    
562
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
563
    key = list(constants.NDC_GLOBALS)[0]
564
    node.ndparams[key] = constants.NDC_DEFAULTS[key]
565
    errs = cfg.VerifyConfig()
566
    self.assertTrue(len(errs) >= 1)
567
    self.assertTrue(_IsErrorInList("has some global parameters set", errs))
568

    
569
    del node.ndparams[key]
570
    errs = cfg.VerifyConfig()
571
    self.assertFalse(errs)
572

    
573
    cluster = cfg.GetClusterInfo()
574
    nodegroup = cfg.GetNodeGroup(cfg.GetNodeGroupList()[0])
575
    self._TestVerifyConfigIPolicy(cluster.ipolicy, "cluster", cfg, False)
576
    self._TestVerifyConfigClusterIPolicy(cluster.ipolicy, cfg)
577
    self._TestVerifyConfigIPolicy(nodegroup.ipolicy, nodegroup.name, cfg, True)
578
    self._TestVerifyConfigGroupIPolicy(nodegroup, cfg)
579
    nodegroup.ipolicy = cluster.SimpleFillIPolicy(nodegroup.ipolicy)
580
    self._TestVerifyConfigIPolicy(nodegroup.ipolicy, nodegroup.name, cfg, True)
581

    
582

    
583
def _IsErrorInList(err_str, err_list):
584
  return any(map(lambda e: err_str in e, err_list))
585

    
586

    
587
class TestTRM(unittest.TestCase):
588
  EC_ID = 1
589

    
590
  def testEmpty(self):
591
    t = TemporaryReservationManager()
592
    t.Reserve(self.EC_ID, "a")
593
    self.assertFalse(t.Reserved(self.EC_ID))
594
    self.assertTrue(t.Reserved("a"))
595
    self.assertEqual(len(t.GetReserved()), 1)
596

    
597
  def testDuplicate(self):
598
    t = TemporaryReservationManager()
599
    t.Reserve(self.EC_ID, "a")
600
    self.assertRaises(errors.ReservationError, t.Reserve, 2, "a")
601
    t.DropECReservations(self.EC_ID)
602
    self.assertFalse(t.Reserved("a"))
603

    
604

    
605
class TestCheckInstanceDiskIvNames(unittest.TestCase):
606
  @staticmethod
607
  def _MakeDisks(names):
608
    return [objects.Disk(iv_name=name) for name in names]
609

    
610
  def testNoError(self):
611
    disks = self._MakeDisks(["disk/0", "disk/1"])
612
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
613
    instance._UpdateIvNames(0, disks)
614
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
615

    
616
  def testWrongNames(self):
617
    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
618
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
619
      (0, "disk/0", "disk/1"),
620
      (1, "disk/1", "disk/3"),
621
      ])
622

    
623
    # Fix names
624
    instance._UpdateIvNames(0, disks)
625
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
626

    
627

    
628
if __name__ == "__main__":
629
  testutils.GanetiTestProgram()