Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (22.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 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
    node1_serial = 1
333
    node2 = objects.Node(name="node2", group=grp2.uuid, ndparams={})
334
    node2_serial = 1
335
    cfg.AddNode(node1, "job")
336
    cfg.AddNode(node2, "job")
337
    cluster_serial += 2
338
    self.assertEqual(set(cfg.GetNodeList()), set(["node1", "node2", me.name]))
339

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

    
347
    _VerifySerials()
348

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
592
    result = cfg_writer._UnlockedGetHvparamsString(hvname)
593

    
594
    self.assertTrue("a=A" in result)
595
    lines = [line for line in result.split('\n') if line != '']
596
    self.assertEqual(len(hvparams.keys()), len(lines))
597

    
598
  def testExtendByAllHvparamsStrings(self):
599
    all_hvparams = {constants.HT_XEN_PVM: "foo"}
600
    ssconf_values = {}
601
    cfg_writer = self._get_object()
602

    
603
    cfg_writer._ExtendByAllHvparamsStrings(ssconf_values, all_hvparams)
604

    
605
    expected_key = constants.SS_HVPARAMS_PREF + constants.HT_XEN_PVM
606
    self.assertTrue(expected_key in ssconf_values)
607

    
608

    
609
def _IsErrorInList(err_str, err_list):
610
  return any(map(lambda e: err_str in e, err_list))
611

    
612

    
613
class TestTRM(unittest.TestCase):
614
  EC_ID = 1
615

    
616
  def testEmpty(self):
617
    t = TemporaryReservationManager()
618
    t.Reserve(self.EC_ID, "a")
619
    self.assertFalse(t.Reserved(self.EC_ID))
620
    self.assertTrue(t.Reserved("a"))
621
    self.assertEqual(len(t.GetReserved()), 1)
622

    
623
  def testDuplicate(self):
624
    t = TemporaryReservationManager()
625
    t.Reserve(self.EC_ID, "a")
626
    self.assertRaises(errors.ReservationError, t.Reserve, 2, "a")
627
    t.DropECReservations(self.EC_ID)
628
    self.assertFalse(t.Reserved("a"))
629

    
630

    
631
class TestCheckInstanceDiskIvNames(unittest.TestCase):
632
  @staticmethod
633
  def _MakeDisks(names):
634
    return [objects.Disk(iv_name=name) for name in names]
635

    
636
  def testNoError(self):
637
    disks = self._MakeDisks(["disk/0", "disk/1"])
638
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
639
    instance._UpdateIvNames(0, disks)
640
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
641

    
642
  def testWrongNames(self):
643
    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
644
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
645
      (0, "disk/0", "disk/1"),
646
      (1, "disk/1", "disk/3"),
647
      ])
648

    
649
    # Fix names
650
    instance._UpdateIvNames(0, disks)
651
    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
652

    
653

    
654
if __name__ == "__main__":
655
  testutils.GanetiTestProgram()