Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (22.5 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",
108
                            uuid="test-uuid",
109
                            disks=[], nics=[],
110
                            disk_template=constants.DT_DISKLESS,
111
                            primary_node=self._get_object().GetMasterNode())
112
    return inst
113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
353
    _VerifySerials()
354

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
563
  def testVerifyConfig(self):
564
    cfg = self._get_object()
565

    
566
    errs = cfg.VerifyConfig()
567
    self.assertFalse(errs)
568

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

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

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

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

    
598
    result = cfg_writer._UnlockedGetHvparamsString(hvname)
599

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

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

    
609
    cfg_writer._ExtendByAllHvparamsStrings(ssconf_values, all_hvparams)
610

    
611
    expected_key = constants.SS_HVPARAMS_PREF + constants.HT_XEN_PVM
612
    self.assertTrue(expected_key in ssconf_values)
613

    
614

    
615
def _IsErrorInList(err_str, err_list):
616
  return any(map(lambda e: err_str in e, err_list))
617

    
618

    
619
class TestTRM(unittest.TestCase):
620
  EC_ID = 1
621

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

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

    
636

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

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

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

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

    
659

    
660
if __name__ == "__main__":
661
  testutils.GanetiTestProgram()