Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.config_unittest.py @ 0f511c8a

History | View | Annotate | Download (21.2 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
      ispeclist.extend([
465
        (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MIN],
466
         "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MIN)),
467
        (ipolicy[constants.ISPECS_MINMAX][constants.ISPECS_MAX],
468
         "%s/%s" % (constants.ISPECS_MINMAX, constants.ISPECS_MAX)),
469
        ])
470
    if constants.ISPECS_STD in ipolicy:
471
      ispeclist.append((ipolicy[constants.ISPECS_STD], constants.ISPECS_STD))
472

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

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

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

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

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

    
558
  def testVerifyConfig(self):
559
    cfg = self._get_object()
560

    
561
    errs = cfg.VerifyConfig()
562
    self.assertFalse(errs)
563

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

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

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

    
584

    
585
def _IsErrorInList(err_str, err_list):
586
  return any(map(lambda e: err_str in e, err_list))
587

    
588

    
589
class TestTRM(unittest.TestCase):
590
  EC_ID = 1
591

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

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

    
606

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

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

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

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

    
629

    
630
if __name__ == "__main__":
631
  testutils.GanetiTestProgram()