Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.objects_unittest.py @ 62fed51b

History | View | Annotate | Download (21.8 kB)

1
#!/usr/bin/python
2
#
3

    
4
# Copyright (C) 2006, 2007, 2008, 2010, 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 objects module"""
23

    
24

    
25
import unittest
26

    
27
from ganeti import constants
28
from ganeti import objects
29
from ganeti import errors
30

    
31
import testutils
32

    
33

    
34
class SimpleObject(objects.ConfigObject):
35
  __slots__ = ["a", "b"]
36

    
37

    
38
class TestDictState(unittest.TestCase):
39
  """Simple dict tansformation tests"""
40

    
41
  def testSimpleObjectToDict(self):
42
    o1 = SimpleObject(a="1")
43
    self.assertEquals(o1.ToDict(), {"a": "1"})
44
    self.assertEquals(o1.__getstate__(), {"a": "1"})
45
    self.assertEquals(o1.__getstate__(), o1.ToDict())
46
    o1.a = 2
47
    o1.b = 5
48
    self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
49
    o2 = SimpleObject.FromDict(o1.ToDict())
50
    self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
51

    
52

    
53
class TestClusterObject(unittest.TestCase):
54
  """Tests done on a L{objects.Cluster}"""
55

    
56
  def setUp(self):
57
    hvparams = {
58
      constants.HT_FAKE: {
59
        "foo": "bar",
60
        "bar": "foo",
61
        "foobar": "barfoo",
62
        },
63
      }
64
    os_hvp = {
65
      "lenny-image": {
66
        constants.HT_FAKE: {
67
          "foo": "baz",
68
          "foobar": "foobar",
69
          "blah": "blibb",
70
          "blubb": "blah",
71
          },
72
        constants.HT_XEN_PVM: {
73
          "root_path": "/dev/sda5",
74
          "foo": "foobar",
75
          },
76
        },
77
      "ubuntu-hardy": {
78
        },
79
      }
80
    ndparams = {
81
        constants.ND_OOB_PROGRAM: "/bin/cluster-oob",
82
        constants.ND_SPINDLE_COUNT: 1,
83
        constants.ND_EXCLUSIVE_STORAGE: False,
84
        }
85

    
86
    self.fake_cl = objects.Cluster(hvparams=hvparams, os_hvp=os_hvp,
87
                                   ndparams=ndparams)
88
    self.fake_cl.UpgradeConfig()
89

    
90
  def testGetHVDefaults(self):
91
    cl = self.fake_cl
92
    self.failUnlessEqual(cl.GetHVDefaults(constants.HT_FAKE),
93
                         cl.hvparams[constants.HT_FAKE])
94
    self.failUnlessEqual(cl.GetHVDefaults(None), {})
95
    self.failUnlessEqual(cl.GetHVDefaults(constants.HT_XEN_PVM,
96
                                          os_name="lenny-image"),
97
                         cl.os_hvp["lenny-image"][constants.HT_XEN_PVM])
98

    
99

    
100
  def testFillHvFullMerge(self):
101
    inst_hvparams = {
102
      "blah": "blubb",
103
      }
104

    
105
    fake_dict = {
106
      "foo": "baz",
107
      "bar": "foo",
108
      "foobar": "foobar",
109
      "blah": "blubb",
110
      "blubb": "blah",
111
      }
112
    fake_inst = objects.Instance(name="foobar",
113
                                 os="lenny-image",
114
                                 hypervisor=constants.HT_FAKE,
115
                                 hvparams=inst_hvparams)
116
    self.assertEqual(fake_dict, self.fake_cl.FillHV(fake_inst))
117

    
118
  def testFillHvGlobalParams(self):
119
    fake_inst = objects.Instance(name="foobar",
120
                                 os="ubuntu-hardy",
121
                                 hypervisor=constants.HT_FAKE,
122
                                 hvparams={})
123
    self.assertEqual(self.fake_cl.hvparams[constants.HT_FAKE],
124
                     self.fake_cl.FillHV(fake_inst))
125

    
126
  def testFillHvInstParams(self):
127
    inst_hvparams = {
128
      "blah": "blubb",
129
      }
130
    fake_inst = objects.Instance(name="foobar",
131
                                 os="ubuntu-hardy",
132
                                 hypervisor=constants.HT_XEN_PVM,
133
                                 hvparams=inst_hvparams)
134
    self.assertEqual(inst_hvparams, self.fake_cl.FillHV(fake_inst))
135

    
136
  def testFillHvEmptyParams(self):
137
    fake_inst = objects.Instance(name="foobar",
138
                                 os="ubuntu-hardy",
139
                                 hypervisor=constants.HT_XEN_PVM,
140
                                 hvparams={})
141
    self.assertEqual({}, self.fake_cl.FillHV(fake_inst))
142

    
143
  def testFillHvPartialParams(self):
144
    os = "lenny-image"
145
    fake_inst = objects.Instance(name="foobar",
146
                                 os=os,
147
                                 hypervisor=constants.HT_XEN_PVM,
148
                                 hvparams={})
149
    self.assertEqual(self.fake_cl.os_hvp[os][constants.HT_XEN_PVM],
150
                     self.fake_cl.FillHV(fake_inst))
151

    
152
  def testFillNdParamsCluster(self):
153
    fake_node = objects.Node(name="test",
154
                             ndparams={},
155
                             group="testgroup")
156
    fake_group = objects.NodeGroup(name="testgroup",
157
                                   ndparams={})
158
    self.assertEqual(self.fake_cl.ndparams,
159
                     self.fake_cl.FillND(fake_node, fake_group))
160

    
161
  def testFillNdParamsNodeGroup(self):
162
    fake_node = objects.Node(name="test",
163
                             ndparams={},
164
                             group="testgroup")
165
    group_ndparams = {
166
        constants.ND_OOB_PROGRAM: "/bin/group-oob",
167
        constants.ND_SPINDLE_COUNT: 10,
168
        constants.ND_EXCLUSIVE_STORAGE: True,
169
        }
170
    fake_group = objects.NodeGroup(name="testgroup",
171
                                   ndparams=group_ndparams)
172
    self.assertEqual(group_ndparams,
173
                     self.fake_cl.FillND(fake_node, fake_group))
174

    
175
  def testFillNdParamsNode(self):
176
    node_ndparams = {
177
        constants.ND_OOB_PROGRAM: "/bin/node-oob",
178
        constants.ND_SPINDLE_COUNT: 2,
179
        constants.ND_EXCLUSIVE_STORAGE: True,
180
        }
181
    fake_node = objects.Node(name="test",
182
                             ndparams=node_ndparams,
183
                             group="testgroup")
184
    fake_group = objects.NodeGroup(name="testgroup",
185
                                   ndparams={})
186
    self.assertEqual(node_ndparams,
187
                     self.fake_cl.FillND(fake_node, fake_group))
188

    
189
  def testFillNdParamsAll(self):
190
    node_ndparams = {
191
        constants.ND_OOB_PROGRAM: "/bin/node-oob",
192
        constants.ND_SPINDLE_COUNT: 5,
193
        constants.ND_EXCLUSIVE_STORAGE: True,
194
        }
195
    fake_node = objects.Node(name="test",
196
                             ndparams=node_ndparams,
197
                             group="testgroup")
198
    group_ndparams = {
199
        constants.ND_OOB_PROGRAM: "/bin/group-oob",
200
        constants.ND_SPINDLE_COUNT: 4,
201
        }
202
    fake_group = objects.NodeGroup(name="testgroup",
203
                                   ndparams=group_ndparams)
204
    self.assertEqual(node_ndparams,
205
                     self.fake_cl.FillND(fake_node, fake_group))
206

    
207
  def testPrimaryHypervisor(self):
208
    assert self.fake_cl.enabled_hypervisors is None
209
    self.fake_cl.enabled_hypervisors = [constants.HT_XEN_HVM]
210
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_HVM)
211

    
212
    self.fake_cl.enabled_hypervisors = [constants.HT_XEN_PVM, constants.HT_KVM]
213
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_PVM)
214

    
215
    self.fake_cl.enabled_hypervisors = sorted(constants.HYPER_TYPES)
216
    self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_CHROOT)
217

    
218
  def testUpgradeConfig(self):
219
    # FIXME: This test is incomplete
220
    cluster = objects.Cluster()
221
    cluster.UpgradeConfig()
222
    cluster = objects.Cluster(ipolicy={"unknown_key": None})
223
    self.assertRaises(errors.ConfigurationError, cluster.UpgradeConfig)
224

    
225

    
226
class TestClusterObjectTcpUdpPortPool(unittest.TestCase):
227
  def testNewCluster(self):
228
    self.assertTrue(objects.Cluster().tcpudp_port_pool is None)
229

    
230
  def testSerializingEmpty(self):
231
    self.assertEqual(objects.Cluster().ToDict(), {
232
      "tcpudp_port_pool": [],
233
      })
234

    
235
  def testSerializing(self):
236
    cluster = objects.Cluster.FromDict({})
237
    self.assertEqual(cluster.tcpudp_port_pool, set())
238

    
239
    cluster.tcpudp_port_pool.add(3546)
240
    cluster.tcpudp_port_pool.add(62511)
241

    
242
    data = cluster.ToDict()
243
    self.assertEqual(data.keys(), ["tcpudp_port_pool"])
244
    self.assertEqual(sorted(data["tcpudp_port_pool"]), sorted([3546, 62511]))
245

    
246
  def testDeserializingEmpty(self):
247
    cluster = objects.Cluster.FromDict({})
248
    self.assertEqual(cluster.tcpudp_port_pool, set())
249

    
250
  def testDeserialize(self):
251
    cluster = objects.Cluster.FromDict({
252
      "tcpudp_port_pool": [26214, 10039, 267],
253
      })
254
    self.assertEqual(cluster.tcpudp_port_pool, set([26214, 10039, 267]))
255

    
256

    
257
class TestOS(unittest.TestCase):
258
  ALL_DATA = [
259
    "debootstrap",
260
    "debootstrap+default",
261
    "debootstrap++default",
262
    ]
263

    
264
  def testSplitNameVariant(self):
265
    for name in self.ALL_DATA:
266
      self.assertEqual(len(objects.OS.SplitNameVariant(name)), 2)
267

    
268
  def testVariant(self):
269
    self.assertEqual(objects.OS.GetVariant("debootstrap"), "")
270
    self.assertEqual(objects.OS.GetVariant("debootstrap+default"), "default")
271

    
272

    
273
class TestInstance(unittest.TestCase):
274
  def _GenericCheck(self, inst):
275
    for i in [inst.all_nodes, inst.secondary_nodes]:
276
      self.assertTrue(isinstance(inst.all_nodes, (list, tuple)),
277
                      msg="Data type doesn't guarantee order")
278

    
279
    self.assertTrue(inst.primary_node not in inst.secondary_nodes)
280
    self.assertEqual(inst.all_nodes[0], inst.primary_node,
281
                     msg="Primary node not first node in list")
282

    
283
  def testNodesNoDisks(self):
284
    inst = objects.Instance(name="fakeinst.example.com",
285
      primary_node="pnode.example.com",
286
      disks=[
287
        ])
288

    
289
    self._GenericCheck(inst)
290
    self.assertEqual(len(inst.secondary_nodes), 0)
291
    self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
292
    self.assertEqual(inst.MapLVsByNode(), {
293
      inst.primary_node: [],
294
      })
295

    
296
  def testNodesPlainDisks(self):
297
    inst = objects.Instance(name="fakeinstplain.example.com",
298
      primary_node="node3.example.com",
299
      disks=[
300
        objects.Disk(dev_type=constants.LD_LV, size=128,
301
                     logical_id=("myxenvg", "disk25494")),
302
        objects.Disk(dev_type=constants.LD_LV, size=512,
303
                     logical_id=("myxenvg", "disk29071")),
304
        ])
305

    
306
    self._GenericCheck(inst)
307
    self.assertEqual(len(inst.secondary_nodes), 0)
308
    self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
309
    self.assertEqual(inst.MapLVsByNode(), {
310
      inst.primary_node: ["myxenvg/disk25494", "myxenvg/disk29071"],
311
      })
312

    
313
  def testNodesDrbdDisks(self):
314
    inst = objects.Instance(name="fakeinstdrbd.example.com",
315
      primary_node="node10.example.com",
316
      disks=[
317
        objects.Disk(dev_type=constants.LD_DRBD8, size=786432,
318
          logical_id=("node10.example.com", "node15.example.com",
319
                      12300, 0, 0, "secret"),
320
          children=[
321
            objects.Disk(dev_type=constants.LD_LV, size=786432,
322
                         logical_id=("myxenvg", "disk0")),
323
            objects.Disk(dev_type=constants.LD_LV, size=128,
324
                         logical_id=("myxenvg", "meta0"))
325
          ],
326
          iv_name="disk/0")
327
        ])
328

    
329
    self._GenericCheck(inst)
330
    self.assertEqual(set(inst.secondary_nodes), set(["node15.example.com"]))
331
    self.assertEqual(set(inst.all_nodes),
332
                     set([inst.primary_node, "node15.example.com"]))
333
    self.assertEqual(inst.MapLVsByNode(), {
334
      inst.primary_node: ["myxenvg/disk0", "myxenvg/meta0"],
335
      "node15.example.com": ["myxenvg/disk0", "myxenvg/meta0"],
336
      })
337

    
338
    self.assertEqual(inst.FindDisk(0), inst.disks[0])
339
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, "hello")
340
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, 100)
341
    self.assertRaises(errors.OpPrereqError, inst.FindDisk, 1)
342

    
343

    
344
class TestNode(unittest.TestCase):
345
  def testEmpty(self):
346
    self.assertEqual(objects.Node().ToDict(), {})
347
    self.assertTrue(isinstance(objects.Node.FromDict({}), objects.Node))
348

    
349
  def testHvState(self):
350
    node = objects.Node(name="node18157.example.com", hv_state={
351
      constants.HT_XEN_HVM: objects.NodeHvState(cpu_total=64),
352
      constants.HT_KVM: objects.NodeHvState(cpu_node=1),
353
      })
354

    
355
    node2 = objects.Node.FromDict(node.ToDict())
356

    
357
    # Make sure nothing can reference it anymore
358
    del node
359

    
360
    self.assertEqual(node2.name, "node18157.example.com")
361
    self.assertEqual(frozenset(node2.hv_state), frozenset([
362
      constants.HT_XEN_HVM,
363
      constants.HT_KVM,
364
      ]))
365
    self.assertEqual(node2.hv_state[constants.HT_KVM].cpu_node, 1)
366
    self.assertEqual(node2.hv_state[constants.HT_XEN_HVM].cpu_total, 64)
367

    
368
  def testDiskState(self):
369
    node = objects.Node(name="node32087.example.com", disk_state={
370
      constants.LD_LV: {
371
        "lv32352": objects.NodeDiskState(total=128),
372
        "lv2082": objects.NodeDiskState(total=512),
373
        },
374
      })
375

    
376
    node2 = objects.Node.FromDict(node.ToDict())
377

    
378
    # Make sure nothing can reference it anymore
379
    del node
380

    
381
    self.assertEqual(node2.name, "node32087.example.com")
382
    self.assertEqual(frozenset(node2.disk_state), frozenset([
383
      constants.LD_LV,
384
      ]))
385
    self.assertEqual(frozenset(node2.disk_state[constants.LD_LV]), frozenset([
386
      "lv32352",
387
      "lv2082",
388
      ]))
389
    self.assertEqual(node2.disk_state[constants.LD_LV]["lv2082"].total, 512)
390
    self.assertEqual(node2.disk_state[constants.LD_LV]["lv32352"].total, 128)
391

    
392
  def testFilterEsNdp(self):
393
    node1 = objects.Node(name="node11673.example.com", ndparams={
394
      constants.ND_EXCLUSIVE_STORAGE: True,
395
      })
396
    node2 = objects.Node(name="node11674.example.com", ndparams={
397
      constants.ND_SPINDLE_COUNT: 3,
398
      constants.ND_EXCLUSIVE_STORAGE: False,
399
      })
400
    self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
401
    node1.UpgradeConfig()
402
    self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
403
    self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
404
    self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
405
    node2.UpgradeConfig()
406
    self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
407
    self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
408

    
409

    
410
class TestInstancePolicy(unittest.TestCase):
411
  def setUp(self):
412
    # Policies are big, and we want to see the difference in case of an error
413
    self.maxDiff = None
414

    
415
  def _AssertIPolicyIsFull(self, policy):
416
    self.assertEqual(frozenset(policy.keys()), constants.IPOLICY_ALL_KEYS)
417
    minmax = policy[constants.ISPECS_MINMAX]
418
    self.assertEqual(frozenset(minmax.keys()), constants.ISPECS_MINMAX_KEYS)
419
    for key in constants.ISPECS_MINMAX_KEYS:
420
      self.assertEqual(frozenset(minmax[key].keys()),
421
                       constants.ISPECS_PARAMETERS)
422
    self.assertEqual(frozenset(policy[constants.ISPECS_STD].keys()),
423
                     constants.ISPECS_PARAMETERS)
424

    
425
  def testDefaultIPolicy(self):
426
    objects.InstancePolicy.CheckParameterSyntax(constants.IPOLICY_DEFAULTS,
427
                                                True)
428
    self._AssertIPolicyIsFull(constants.IPOLICY_DEFAULTS)
429

    
430
  def testCheckISpecSyntax(self):
431
    incomplete_ipolicies = [
432
      {
433
         constants.ISPECS_MINMAX: {},
434
         constants.ISPECS_STD: NotImplemented,
435
         },
436
      {
437
        constants.ISPECS_MINMAX: {
438
          constants.ISPECS_MIN: NotImplemented,
439
          },
440
        constants.ISPECS_STD: NotImplemented,
441
        },
442
      {
443
        constants.ISPECS_MINMAX: {
444
          constants.ISPECS_MAX: NotImplemented,
445
          },
446
        constants.ISPECS_STD: NotImplemented,
447
        },
448
      {
449
        constants.ISPECS_MINMAX: {
450
          constants.ISPECS_MIN: NotImplemented,
451
          constants.ISPECS_MAX: NotImplemented,
452
          },
453
        },
454
      ]
455
    for ipol in incomplete_ipolicies:
456
      self.assertRaises(errors.ConfigurationError,
457
                        objects.InstancePolicy.CheckISpecSyntax,
458
                        ipol, True)
459

    
460
  def testCheckISpecParamSyntax(self):
461
    par = "my_parameter"
462
    for check_std in [True, False]:
463
      # Only one policy limit
464
      for key in constants.ISPECS_MINMAX_KEYS:
465
        minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
466
        minmax[key][par] = 11
467
        objects.InstancePolicy._CheckISpecParamSyntax(minmax, {}, par,
468
                                                      check_std)
469
      if check_std:
470
        minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
471
        stdspec = {par: 11}
472
        objects.InstancePolicy._CheckISpecParamSyntax(minmax, stdspec, par,
473
                                                      check_std)
474

    
475
      # Min and max only
476
      good_values = [(11, 11), (11, 40), (0, 0)]
477
      for (mn, mx) in good_values:
478
        minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
479
        minmax[constants.ISPECS_MIN][par] = mn
480
        minmax[constants.ISPECS_MAX][par] = mx
481
        objects.InstancePolicy._CheckISpecParamSyntax(minmax, {}, par,
482
                                                     check_std)
483
      minmax = dict((k, {}) for k in constants.ISPECS_MINMAX_KEYS)
484
      minmax[constants.ISPECS_MIN][par] = 11
485
      minmax[constants.ISPECS_MAX][par] = 5
486
      self.assertRaises(errors.ConfigurationError,
487
                        objects.InstancePolicy._CheckISpecParamSyntax,
488
                        minmax, {}, par, check_std)
489
    # Min, std, max
490
    good_values = [
491
      (11, 11, 11),
492
      (11, 11, 40),
493
      (11, 40, 40),
494
      ]
495
    for (mn, st, mx) in good_values:
496
      minmax = {
497
        constants.ISPECS_MIN: {par: mn},
498
        constants.ISPECS_MAX: {par: mx},
499
        }
500
      stdspec = {par: st}
501
      objects.InstancePolicy._CheckISpecParamSyntax(minmax, stdspec, par, True)
502
    bad_values = [
503
      (11, 11,  5),
504
      (40, 11, 11),
505
      (11, 80, 40),
506
      (11,  5, 40),
507
      (11,  5,  5),
508
      (40, 40, 11),
509
      ]
510
    for (mn, st, mx) in bad_values:
511
      minmax = {
512
        constants.ISPECS_MIN: {par: mn},
513
        constants.ISPECS_MAX: {par: mx},
514
        }
515
      stdspec = {par: st}
516
      self.assertRaises(errors.ConfigurationError,
517
                        objects.InstancePolicy._CheckISpecParamSyntax,
518
                        minmax, stdspec, par, True)
519

    
520
  def testCheckDiskTemplates(self):
521
    invalid = "this_is_not_a_good_template"
522
    for dt in constants.DISK_TEMPLATES:
523
      objects.InstancePolicy.CheckDiskTemplates([dt])
524
    objects.InstancePolicy.CheckDiskTemplates(list(constants.DISK_TEMPLATES))
525
    bad_examples = [
526
      [invalid],
527
      [constants.DT_DRBD8, invalid],
528
      list(constants.DISK_TEMPLATES) + [invalid],
529
      [],
530
      None,
531
      ]
532
    for dtl in bad_examples:
533
      self.assertRaises(errors.ConfigurationError,
534
                        objects.InstancePolicy.CheckDiskTemplates,
535
                        dtl)
536

    
537
  def testCheckParameterSyntax(self):
538
    invalid = "this_key_shouldnt_be_here"
539
    for check_std in [True, False]:
540
      objects.InstancePolicy.CheckParameterSyntax({}, check_std)
541
      policy = {invalid: None}
542
      self.assertRaises(errors.ConfigurationError,
543
                        objects.InstancePolicy.CheckParameterSyntax,
544
                        policy, check_std)
545
      for par in constants.IPOLICY_PARAMETERS:
546
        for val in ("blah", None, {}, [42]):
547
          policy = {par: val}
548
          self.assertRaises(errors.ConfigurationError,
549
                            objects.InstancePolicy.CheckParameterSyntax,
550
                            policy, check_std)
551

    
552
  def testFillIPolicyEmpty(self):
553
    policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, {})
554
    objects.InstancePolicy.CheckParameterSyntax(policy, True)
555
    self.assertEqual(policy, constants.IPOLICY_DEFAULTS)
556

    
557
  def _AssertISpecsMerged(self, default_spec, diff_spec, merged_spec):
558
    for (param, value) in merged_spec.items():
559
      if param in diff_spec:
560
        self.assertEqual(value, diff_spec[param])
561
      else:
562
        self.assertEqual(value, default_spec[param])
563

    
564
  def _AssertIPolicyMerged(self, default_pol, diff_pol, merged_pol):
565
    for (key, value) in merged_pol.items():
566
      if key in diff_pol:
567
        if key == constants.ISPECS_MINMAX:
568
          self.assertEqual(frozenset(value), constants.ISPECS_MINMAX_KEYS)
569
          for k in constants.ISPECS_MINMAX_KEYS:
570
            self._AssertISpecsMerged(default_pol[key][k], diff_pol[key][k],
571
                                     value[k])
572
        elif key == constants.ISPECS_STD:
573
          self._AssertISpecsMerged(default_pol[key], diff_pol[key], value)
574
        else:
575
          self.assertEqual(value, diff_pol[key])
576
      else:
577
        self.assertEqual(value, default_pol[key])
578

    
579
  def testFillIPolicy(self):
580
    partial_policies = [
581
      {constants.IPOLICY_VCPU_RATIO: 3.14},
582
      {constants.IPOLICY_SPINDLE_RATIO: 2.72},
583
      {constants.IPOLICY_DTS: [constants.DT_FILE]},
584
      ]
585
    for diff_pol in partial_policies:
586
      policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
587
      objects.InstancePolicy.CheckParameterSyntax(policy, True)
588
      self._AssertIPolicyIsFull(policy)
589
      self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy)
590

    
591
  def testFillIPolicySpecs(self):
592
    partial_ipolicies = [
593
      {
594
        constants.ISPECS_MINMAX: {
595
          constants.ISPECS_MIN: {constants.ISPEC_MEM_SIZE: 32},
596
          constants.ISPECS_MAX: {constants.ISPEC_CPU_COUNT: 1024}
597
          },
598
        },
599
      {
600
        constants.ISPECS_MINMAX: {
601
          constants.ISPECS_MAX: {
602
            constants.ISPEC_DISK_COUNT: constants.MAX_DISKS - 1,
603
            constants.ISPEC_NIC_COUNT: constants.MAX_NICS - 1,
604
            },
605
          constants.ISPECS_MIN: {},
606
          },
607
          constants.ISPECS_STD: {constants.ISPEC_DISK_SIZE: 2048},
608
        },
609
      {
610
        constants.ISPECS_STD: {constants.ISPEC_SPINDLE_USE: 3},
611
        },
612
      ]
613
    for diff_pol in partial_ipolicies:
614
      policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
615
      objects.InstancePolicy.CheckParameterSyntax(policy, True)
616
      self._AssertIPolicyIsFull(policy)
617
      self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy)
618

    
619

    
620
if __name__ == "__main__":
621
  testutils.GanetiTestProgram()