Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.config_unittest.py @ 7352d33b

History | View | Annotate | Download (21.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 time
28
import tempfile
29
import os.path
30
import socket
31
import operator
32
import itertools
33

    
34
from ganeti import bootstrap
35
from ganeti import config
36
from ganeti import constants
37
from ganeti import errors
38
from ganeti import objects
39
from ganeti import utils
40
from ganeti import netutils
41
from ganeti import compat
42
from ganeti import cmdlib
43

    
44
from ganeti.config import TemporaryReservationManager
45

    
46
import testutils
47
import mocks
48

    
49

    
50
def _StubGetEntResolver():
51
  return mocks.FakeGetentResolver()
52

    
53

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

    
61
  def tearDown(self):
62
    try:
63
      os.unlink(self.cfg_file)
64
    except OSError:
65
      pass
66

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

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

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

    
99
    master_node_config = objects.Node(name=me.name,
100
                                      primary_ip=me.ip,
101
                                      secondary_ip=ip,
102
                                      serial_no=1,
103
                                      master_candidate=True)
104

    
105
    bootstrap.InitConfig(constants.CONFIG_VERSION,
106
                         cluster_config, master_node_config, self.cfg_file)
107

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

    
115
  def testEmpty(self):
116
    """Test instantiate config object"""
117
    self._get_object()
118

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

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

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

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

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

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

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

    
179
  def testUpgradeSave(self):
180
    """Test that any modification done during upgrading is saved back"""
181
    cfg = self._get_object()
182

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

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

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

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

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

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

    
235
  def testGetNdParamsDefault(self):
236
    cfg = self._get_object()
237
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
238
    self.assertEqual(cfg.GetNdParams(node), constants.NDC_DEFAULTS)
239

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

    
247
    cfg = self._get_object()
248
    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
249
    node.ndparams = my_ndparams
250
    cfg.Update(node, None)
251
    self.assertEqual(cfg.GetNdParams(node), my_ndparams)
252

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

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

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

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

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

    
304
    self.assertRaises(errors.ConfigurationError,
305
                      cfg.AddNodeGroup, group, "my-job")
306

    
307
    cfg.AddNodeGroup(group, "my-job", check_uuid=False) # Does not raise.
308
    self.assertEqual(uuid, group.uuid)
309

    
310
  def testAssignGroupNodes(self):
311
    me = netutils.Hostname()
312
    cfg = self._get_object()
313

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

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

    
328
    # No-op
329
    cluster_serial = cfg.GetClusterInfo().serial_no
330
    cfg.AssignGroupNodes([])
331
    cluster_serial += 1
332

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

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

    
350
    _VerifySerials()
351

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
586

    
587
def _IsErrorInList(err_str, err_list):
588
  return any(map(lambda e: err_str in e, err_list))
589

    
590

    
591
class TestTRM(unittest.TestCase):
592
  EC_ID = 1
593

    
594
  def testEmpty(self):
595
    t = TemporaryReservationManager()
596
    t.Reserve(self.EC_ID, "a")
597
    self.assertFalse(t.Reserved(self.EC_ID))
598
    self.assertTrue(t.Reserved("a"))
599
    self.assertEqual(len(t.GetReserved()), 1)
600

    
601
  def testDuplicate(self):
602
    t = TemporaryReservationManager()
603
    t.Reserve(self.EC_ID, "a")
604
    self.assertRaises(errors.ReservationError, t.Reserve, 2, "a")
605
    t.DropECReservations(self.EC_ID)
606
    self.assertFalse(t.Reserved("a"))
607

    
608

    
609
class TestCheckInstanceDiskIvNames(unittest.TestCase):
610
  @staticmethod
611
  def _MakeDisks(names):
612
    return [objects.Disk(iv_name=name) for name in names]
613

    
614
  def testNoError(self):
615
    disks = self._MakeDisks(["disk/0", "disk/1"])
616
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
617
    cmdlib._UpdateIvNames(0, disks)
618
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
619

    
620
  def testWrongNames(self):
621
    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
622
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
623
      (0, "disk/0", "disk/1"),
624
      (1, "disk/1", "disk/3"),
625
      ])
626

    
627
    # Fix names
628
    cmdlib._UpdateIvNames(0, disks)
629
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
630

    
631

    
632
if __name__ == "__main__":
633
  testutils.GanetiTestProgram()