4 # Copyright (C) 2006, 2007, 2008, 2010, 2012 Google Inc.
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.
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.
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
22 """Script for unittesting the objects module"""
27 from ganeti import constants
28 from ganeti import objects
29 from ganeti import errors
34 class SimpleObject(objects.ConfigObject):
35 __slots__ = ["a", "b"]
38 class TestDictState(unittest.TestCase):
39 """Simple dict tansformation tests"""
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())
48 self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
49 o2 = SimpleObject.FromDict(o1.ToDict())
50 self.assertEquals(o1.ToDict(), {"a": 2, "b": 5})
53 class TestClusterObject(unittest.TestCase):
54 """Tests done on a L{objects.Cluster}"""
72 constants.HT_XEN_PVM: {
73 "root_path": "/dev/sda5",
81 constants.ND_OOB_PROGRAM: "/bin/cluster-oob",
82 constants.ND_SPINDLE_COUNT: 1,
83 constants.ND_EXCLUSIVE_STORAGE: False,
86 self.fake_cl = objects.Cluster(hvparams=hvparams, os_hvp=os_hvp,
88 self.fake_cl.UpgradeConfig()
90 def testGetHVDefaults(self):
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])
100 def testFillHvFullMerge(self):
112 fake_inst = objects.Instance(name="foobar",
114 hypervisor=constants.HT_FAKE,
115 hvparams=inst_hvparams)
116 self.assertEqual(fake_dict, self.fake_cl.FillHV(fake_inst))
118 def testFillHvGlobalParams(self):
119 fake_inst = objects.Instance(name="foobar",
121 hypervisor=constants.HT_FAKE,
123 self.assertEqual(self.fake_cl.hvparams[constants.HT_FAKE],
124 self.fake_cl.FillHV(fake_inst))
126 def testFillHvInstParams(self):
130 fake_inst = objects.Instance(name="foobar",
132 hypervisor=constants.HT_XEN_PVM,
133 hvparams=inst_hvparams)
134 self.assertEqual(inst_hvparams, self.fake_cl.FillHV(fake_inst))
136 def testFillHvEmptyParams(self):
137 fake_inst = objects.Instance(name="foobar",
139 hypervisor=constants.HT_XEN_PVM,
141 self.assertEqual({}, self.fake_cl.FillHV(fake_inst))
143 def testFillHvPartialParams(self):
145 fake_inst = objects.Instance(name="foobar",
147 hypervisor=constants.HT_XEN_PVM,
149 self.assertEqual(self.fake_cl.os_hvp[os][constants.HT_XEN_PVM],
150 self.fake_cl.FillHV(fake_inst))
152 def testFillNdParamsCluster(self):
153 fake_node = objects.Node(name="test",
156 fake_group = objects.NodeGroup(name="testgroup",
158 self.assertEqual(self.fake_cl.ndparams,
159 self.fake_cl.FillND(fake_node, fake_group))
161 def testFillNdParamsNodeGroup(self):
162 fake_node = objects.Node(name="test",
166 constants.ND_OOB_PROGRAM: "/bin/group-oob",
167 constants.ND_SPINDLE_COUNT: 10,
168 constants.ND_EXCLUSIVE_STORAGE: True,
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))
175 def testFillNdParamsNode(self):
177 constants.ND_OOB_PROGRAM: "/bin/node-oob",
178 constants.ND_SPINDLE_COUNT: 2,
179 constants.ND_EXCLUSIVE_STORAGE: True,
181 fake_node = objects.Node(name="test",
182 ndparams=node_ndparams,
184 fake_group = objects.NodeGroup(name="testgroup",
186 self.assertEqual(node_ndparams,
187 self.fake_cl.FillND(fake_node, fake_group))
189 def testFillNdParamsAll(self):
191 constants.ND_OOB_PROGRAM: "/bin/node-oob",
192 constants.ND_SPINDLE_COUNT: 5,
193 constants.ND_EXCLUSIVE_STORAGE: True,
195 fake_node = objects.Node(name="test",
196 ndparams=node_ndparams,
199 constants.ND_OOB_PROGRAM: "/bin/group-oob",
200 constants.ND_SPINDLE_COUNT: 4,
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))
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)
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)
215 self.fake_cl.enabled_hypervisors = sorted(constants.HYPER_TYPES)
216 self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_CHROOT)
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)
226 class TestOS(unittest.TestCase):
229 "debootstrap+default",
230 "debootstrap++default",
233 def testSplitNameVariant(self):
234 for name in self.ALL_DATA:
235 self.assertEqual(len(objects.OS.SplitNameVariant(name)), 2)
237 def testVariant(self):
238 self.assertEqual(objects.OS.GetVariant("debootstrap"), "")
239 self.assertEqual(objects.OS.GetVariant("debootstrap+default"), "default")
242 class TestInstance(unittest.TestCase):
243 def _GenericCheck(self, inst):
244 for i in [inst.all_nodes, inst.secondary_nodes]:
245 self.assertTrue(isinstance(inst.all_nodes, (list, tuple)),
246 msg="Data type doesn't guarantee order")
248 self.assertTrue(inst.primary_node not in inst.secondary_nodes)
249 self.assertEqual(inst.all_nodes[0], inst.primary_node,
250 msg="Primary node not first node in list")
252 def testNodesNoDisks(self):
253 inst = objects.Instance(name="fakeinst.example.com",
254 primary_node="pnode.example.com",
258 self._GenericCheck(inst)
259 self.assertEqual(len(inst.secondary_nodes), 0)
260 self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
261 self.assertEqual(inst.MapLVsByNode(), {
262 inst.primary_node: [],
265 def testNodesPlainDisks(self):
266 inst = objects.Instance(name="fakeinstplain.example.com",
267 primary_node="node3.example.com",
269 objects.Disk(dev_type=constants.LD_LV, size=128,
270 logical_id=("myxenvg", "disk25494")),
271 objects.Disk(dev_type=constants.LD_LV, size=512,
272 logical_id=("myxenvg", "disk29071")),
275 self._GenericCheck(inst)
276 self.assertEqual(len(inst.secondary_nodes), 0)
277 self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
278 self.assertEqual(inst.MapLVsByNode(), {
279 inst.primary_node: ["myxenvg/disk25494", "myxenvg/disk29071"],
282 def testNodesDrbdDisks(self):
283 inst = objects.Instance(name="fakeinstdrbd.example.com",
284 primary_node="node10.example.com",
286 objects.Disk(dev_type=constants.LD_DRBD8, size=786432,
287 logical_id=("node10.example.com", "node15.example.com",
288 12300, 0, 0, "secret"),
290 objects.Disk(dev_type=constants.LD_LV, size=786432,
291 logical_id=("myxenvg", "disk0")),
292 objects.Disk(dev_type=constants.LD_LV, size=128,
293 logical_id=("myxenvg", "meta0"))
298 self._GenericCheck(inst)
299 self.assertEqual(set(inst.secondary_nodes), set(["node15.example.com"]))
300 self.assertEqual(set(inst.all_nodes),
301 set([inst.primary_node, "node15.example.com"]))
302 self.assertEqual(inst.MapLVsByNode(), {
303 inst.primary_node: ["myxenvg/disk0", "myxenvg/meta0"],
304 "node15.example.com": ["myxenvg/disk0", "myxenvg/meta0"],
307 self.assertEqual(inst.FindDisk(0), inst.disks[0])
308 self.assertRaises(errors.OpPrereqError, inst.FindDisk, "hello")
309 self.assertRaises(errors.OpPrereqError, inst.FindDisk, 100)
310 self.assertRaises(errors.OpPrereqError, inst.FindDisk, 1)
313 class TestNode(unittest.TestCase):
315 self.assertEqual(objects.Node().ToDict(), {})
316 self.assertTrue(isinstance(objects.Node.FromDict({}), objects.Node))
318 def testHvState(self):
319 node = objects.Node(name="node18157.example.com", hv_state={
320 constants.HT_XEN_HVM: objects.NodeHvState(cpu_total=64),
321 constants.HT_KVM: objects.NodeHvState(cpu_node=1),
324 node2 = objects.Node.FromDict(node.ToDict())
326 # Make sure nothing can reference it anymore
329 self.assertEqual(node2.name, "node18157.example.com")
330 self.assertEqual(frozenset(node2.hv_state), frozenset([
331 constants.HT_XEN_HVM,
334 self.assertEqual(node2.hv_state[constants.HT_KVM].cpu_node, 1)
335 self.assertEqual(node2.hv_state[constants.HT_XEN_HVM].cpu_total, 64)
337 def testDiskState(self):
338 node = objects.Node(name="node32087.example.com", disk_state={
340 "lv32352": objects.NodeDiskState(total=128),
341 "lv2082": objects.NodeDiskState(total=512),
345 node2 = objects.Node.FromDict(node.ToDict())
347 # Make sure nothing can reference it anymore
350 self.assertEqual(node2.name, "node32087.example.com")
351 self.assertEqual(frozenset(node2.disk_state), frozenset([
354 self.assertEqual(frozenset(node2.disk_state[constants.LD_LV]), frozenset([
358 self.assertEqual(node2.disk_state[constants.LD_LV]["lv2082"].total, 512)
359 self.assertEqual(node2.disk_state[constants.LD_LV]["lv32352"].total, 128)
361 def testFilterEsNdp(self):
362 node1 = objects.Node(name="node11673.example.com", ndparams={
363 constants.ND_EXCLUSIVE_STORAGE: True,
365 node2 = objects.Node(name="node11674.example.com", ndparams={
366 constants.ND_SPINDLE_COUNT: 3,
367 constants.ND_EXCLUSIVE_STORAGE: False,
369 self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
370 node1.UpgradeConfig()
371 self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node1.ndparams)
372 self.assertTrue(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
373 self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
374 node2.UpgradeConfig()
375 self.assertFalse(constants.ND_EXCLUSIVE_STORAGE in node2.ndparams)
376 self.assertTrue(constants.ND_SPINDLE_COUNT in node2.ndparams)
379 class TestInstancePolicy(unittest.TestCase):
381 # Policies are big, and we want to see the difference in case of an error
384 def _AssertIPolicyIsFull(self, policy):
385 self.assertEqual(frozenset(policy.keys()), constants.IPOLICY_ALL_KEYS)
386 for key in constants.IPOLICY_ISPECS:
388 self.assertEqual(frozenset(spec.keys()), constants.ISPECS_PARAMETERS)
390 def testDefaultIPolicy(self):
391 objects.InstancePolicy.CheckParameterSyntax(constants.IPOLICY_DEFAULTS,
393 self._AssertIPolicyIsFull(constants.IPOLICY_DEFAULTS)
395 def testFillIPolicyEmpty(self):
396 policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, {})
397 objects.InstancePolicy.CheckParameterSyntax(policy, True)
398 self.assertEqual(policy, constants.IPOLICY_DEFAULTS)
400 def _AssertISpecsMerged(self, default_spec, diff_spec, merged_spec):
401 for (param, value) in merged_spec.items():
402 if param in diff_spec:
403 self.assertEqual(value, diff_spec[param])
405 self.assertEqual(value, default_spec[param])
407 def _AssertIPolicyMerged(self, default_pol, diff_pol, merged_pol):
408 for (key, value) in merged_pol.items():
410 if key in constants.IPOLICY_ISPECS:
411 self._AssertISpecsMerged(default_pol[key], diff_pol[key], value)
413 self.assertEqual(value, diff_pol[key])
415 self.assertEqual(value, default_pol[key])
417 def testFillIPolicy(self):
419 {constants.IPOLICY_VCPU_RATIO: 3.14},
420 {constants.IPOLICY_SPINDLE_RATIO: 2.72},
421 {constants.IPOLICY_DTS: []},
422 {constants.IPOLICY_DTS: [constants.DT_FILE]},
424 for diff_pol in partial_policies:
425 policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
426 objects.InstancePolicy.CheckParameterSyntax(policy, True)
427 self._AssertIPolicyIsFull(policy)
428 self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy)
430 def testFillIPolicySpecs(self):
432 {constants.ISPECS_MIN: {constants.ISPEC_MEM_SIZE: 32},
433 constants.ISPECS_MAX: {constants.ISPEC_CPU_COUNT: 1024}},
434 {constants.ISPECS_STD: {constants.ISPEC_DISK_SIZE: 2048},
435 constants.ISPECS_MAX: {
436 constants.ISPEC_DISK_COUNT: constants.MAX_DISKS - 1,
437 constants.ISPEC_NIC_COUNT: constants.MAX_NICS - 1,
439 {constants.ISPECS_STD: {constants.ISPEC_SPINDLE_USE: 3}},
441 for diff_pol in partial_policies:
442 policy = objects.FillIPolicy(constants.IPOLICY_DEFAULTS, diff_pol)
443 objects.InstancePolicy.CheckParameterSyntax(policy, True)
444 self._AssertIPolicyIsFull(policy)
445 self._AssertIPolicyMerged(constants.IPOLICY_DEFAULTS, diff_pol, policy)
448 if __name__ == "__main__":
449 testutils.GanetiTestProgram()