Add DRBD barriers disk parameters
[ganeti-local] / test / ganeti.objects_unittest.py
1 #!/usr/bin/python
2 #
3
4 # Copyright (C) 2006, 2007, 2008, 2010 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         }
83
84     self.fake_cl = objects.Cluster(hvparams=hvparams, os_hvp=os_hvp,
85                                    ndparams=ndparams)
86     self.fake_cl.UpgradeConfig()
87
88   def testGetHVDefaults(self):
89     cl = self.fake_cl
90     self.failUnlessEqual(cl.GetHVDefaults(constants.HT_FAKE),
91                          cl.hvparams[constants.HT_FAKE])
92     self.failUnlessEqual(cl.GetHVDefaults(None), {})
93     self.failUnlessEqual(cl.GetHVDefaults(constants.HT_XEN_PVM,
94                                           os_name="lenny-image"),
95                          cl.os_hvp["lenny-image"][constants.HT_XEN_PVM])
96
97
98   def testFillHvFullMerge(self):
99     inst_hvparams = {
100       "blah": "blubb",
101       }
102
103     fake_dict = {
104       "foo": "baz",
105       "bar": "foo",
106       "foobar": "foobar",
107       "blah": "blubb",
108       "blubb": "blah",
109       }
110     fake_inst = objects.Instance(name="foobar",
111                                  os="lenny-image",
112                                  hypervisor=constants.HT_FAKE,
113                                  hvparams=inst_hvparams)
114     self.assertEqual(fake_dict, self.fake_cl.FillHV(fake_inst))
115
116   def testFillHvGlobalParams(self):
117     fake_inst = objects.Instance(name="foobar",
118                                  os="ubuntu-hardy",
119                                  hypervisor=constants.HT_FAKE,
120                                  hvparams={})
121     self.assertEqual(self.fake_cl.hvparams[constants.HT_FAKE],
122                      self.fake_cl.FillHV(fake_inst))
123
124   def testFillHvInstParams(self):
125     inst_hvparams = {
126       "blah": "blubb",
127       }
128     fake_inst = objects.Instance(name="foobar",
129                                  os="ubuntu-hardy",
130                                  hypervisor=constants.HT_XEN_PVM,
131                                  hvparams=inst_hvparams)
132     self.assertEqual(inst_hvparams, self.fake_cl.FillHV(fake_inst))
133
134   def testFillHvEmptyParams(self):
135     fake_inst = objects.Instance(name="foobar",
136                                  os="ubuntu-hardy",
137                                  hypervisor=constants.HT_XEN_PVM,
138                                  hvparams={})
139     self.assertEqual({}, self.fake_cl.FillHV(fake_inst))
140
141   def testFillHvPartialParams(self):
142     os = "lenny-image"
143     fake_inst = objects.Instance(name="foobar",
144                                  os=os,
145                                  hypervisor=constants.HT_XEN_PVM,
146                                  hvparams={})
147     self.assertEqual(self.fake_cl.os_hvp[os][constants.HT_XEN_PVM],
148                      self.fake_cl.FillHV(fake_inst))
149
150   def testFillNdParamsCluster(self):
151     fake_node = objects.Node(name="test",
152                              ndparams={},
153                              group="testgroup")
154     fake_group = objects.NodeGroup(name="testgroup",
155                                    ndparams={})
156     self.assertEqual(self.fake_cl.ndparams,
157                      self.fake_cl.FillND(fake_node, fake_group))
158
159   def testFillNdParamsNodeGroup(self):
160     fake_node = objects.Node(name="test",
161                              ndparams={},
162                              group="testgroup")
163     group_ndparams = {
164         constants.ND_OOB_PROGRAM: "/bin/group-oob"
165         }
166     fake_group = objects.NodeGroup(name="testgroup",
167                                    ndparams=group_ndparams)
168     self.assertEqual(group_ndparams,
169                      self.fake_cl.FillND(fake_node, fake_group))
170
171   def testFillNdParamsNode(self):
172     node_ndparams = {
173         constants.ND_OOB_PROGRAM: "/bin/node-oob"
174         }
175     fake_node = objects.Node(name="test",
176                              ndparams=node_ndparams,
177                              group="testgroup")
178     fake_group = objects.NodeGroup(name="testgroup",
179                                    ndparams={})
180     self.assertEqual(node_ndparams,
181                      self.fake_cl.FillND(fake_node, fake_group))
182
183   def testFillNdParamsAll(self):
184     node_ndparams = {
185         constants.ND_OOB_PROGRAM: "/bin/node-oob"
186         }
187     fake_node = objects.Node(name="test",
188                              ndparams=node_ndparams,
189                              group="testgroup")
190     group_ndparams = {
191         constants.ND_OOB_PROGRAM: "/bin/group-oob"
192         }
193     fake_group = objects.NodeGroup(name="testgroup",
194                                    ndparams=group_ndparams)
195     self.assertEqual(node_ndparams,
196                      self.fake_cl.FillND(fake_node, fake_group))
197
198   def testPrimaryHypervisor(self):
199     assert self.fake_cl.enabled_hypervisors is None
200     self.fake_cl.enabled_hypervisors = [constants.HT_XEN_HVM]
201     self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_HVM)
202
203     self.fake_cl.enabled_hypervisors = [constants.HT_XEN_PVM, constants.HT_KVM]
204     self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_XEN_PVM)
205
206     self.fake_cl.enabled_hypervisors = sorted(constants.HYPER_TYPES)
207     self.assertEqual(self.fake_cl.primary_hypervisor, constants.HT_CHROOT)
208
209
210 class TestOS(unittest.TestCase):
211   ALL_DATA = [
212     "debootstrap",
213     "debootstrap+default",
214     "debootstrap++default",
215     ]
216
217   def testSplitNameVariant(self):
218     for name in self.ALL_DATA:
219       self.assertEqual(len(objects.OS.SplitNameVariant(name)), 2)
220
221   def testVariant(self):
222     self.assertEqual(objects.OS.GetVariant("debootstrap"), "")
223     self.assertEqual(objects.OS.GetVariant("debootstrap+default"), "default")
224
225
226 class TestInstance(unittest.TestCase):
227   def _GenericCheck(self, inst):
228     for i in [inst.all_nodes, inst.secondary_nodes]:
229       self.assertTrue(isinstance(inst.all_nodes, (list, tuple)),
230                       msg="Data type doesn't guarantee order")
231
232     self.assertTrue(inst.primary_node not in inst.secondary_nodes)
233     self.assertEqual(inst.all_nodes[0], inst.primary_node,
234                      msg="Primary node not first node in list")
235
236   def testNodesNoDisks(self):
237     inst = objects.Instance(name="fakeinst.example.com",
238       primary_node="pnode.example.com",
239       disks=[
240         ])
241
242     self._GenericCheck(inst)
243     self.assertEqual(len(inst.secondary_nodes), 0)
244     self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
245     self.assertEqual(inst.MapLVsByNode(), {
246       inst.primary_node: [],
247       })
248
249   def testNodesPlainDisks(self):
250     inst = objects.Instance(name="fakeinstplain.example.com",
251       primary_node="node3.example.com",
252       disks=[
253         objects.Disk(dev_type=constants.LD_LV, size=128,
254                      logical_id=("myxenvg", "disk25494")),
255         objects.Disk(dev_type=constants.LD_LV, size=512,
256                      logical_id=("myxenvg", "disk29071")),
257         ])
258
259     self._GenericCheck(inst)
260     self.assertEqual(len(inst.secondary_nodes), 0)
261     self.assertEqual(set(inst.all_nodes), set([inst.primary_node]))
262     self.assertEqual(inst.MapLVsByNode(), {
263       inst.primary_node: ["myxenvg/disk25494", "myxenvg/disk29071"],
264       })
265
266   def testNodesDrbdDisks(self):
267     inst = objects.Instance(name="fakeinstdrbd.example.com",
268       primary_node="node10.example.com",
269       disks=[
270         objects.Disk(dev_type=constants.LD_DRBD8, size=786432,
271           logical_id=("node10.example.com", "node15.example.com",
272                       12300, 0, 0, "secret"),
273           children=[
274             objects.Disk(dev_type=constants.LD_LV, size=786432,
275                          logical_id=("myxenvg", "disk0")),
276             objects.Disk(dev_type=constants.LD_LV, size=128,
277                          logical_id=("myxenvg", "meta0"))
278           ],
279           iv_name="disk/0")
280         ])
281
282     self._GenericCheck(inst)
283     self.assertEqual(set(inst.secondary_nodes), set(["node15.example.com"]))
284     self.assertEqual(set(inst.all_nodes),
285                      set([inst.primary_node, "node15.example.com"]))
286     self.assertEqual(inst.MapLVsByNode(), {
287       inst.primary_node: ["myxenvg/disk0", "myxenvg/meta0"],
288       "node15.example.com": ["myxenvg/disk0", "myxenvg/meta0"],
289       })
290
291     self.assertEqual(inst.FindDisk(0), inst.disks[0])
292     self.assertRaises(errors.OpPrereqError, inst.FindDisk, "hello")
293     self.assertRaises(errors.OpPrereqError, inst.FindDisk, 100)
294     self.assertRaises(errors.OpPrereqError, inst.FindDisk, 1)
295
296
297 class TestNode(unittest.TestCase):
298   def testEmpty(self):
299     self.assertEqual(objects.Node().ToDict(), {})
300     self.assertTrue(isinstance(objects.Node.FromDict({}), objects.Node))
301
302   def testHvState(self):
303     node = objects.Node(name="node18157.example.com", hv_state={
304       constants.HT_XEN_HVM: objects.NodeHvState(cpu_total=64),
305       constants.HT_KVM: objects.NodeHvState(cpu_node=1),
306       })
307
308     node2 = objects.Node.FromDict(node.ToDict())
309
310     # Make sure nothing can reference it anymore
311     del node
312
313     self.assertEqual(node2.name, "node18157.example.com")
314     self.assertEqual(frozenset(node2.hv_state), frozenset([
315       constants.HT_XEN_HVM,
316       constants.HT_KVM,
317       ]))
318     self.assertEqual(node2.hv_state[constants.HT_KVM].cpu_node, 1)
319     self.assertEqual(node2.hv_state[constants.HT_XEN_HVM].cpu_total, 64)
320
321   def testDiskState(self):
322     node = objects.Node(name="node32087.example.com", disk_state={
323       constants.LD_LV: {
324         "lv32352": objects.NodeDiskState(total=128),
325         "lv2082": objects.NodeDiskState(total=512),
326         },
327       })
328
329     node2 = objects.Node.FromDict(node.ToDict())
330
331     # Make sure nothing can reference it anymore
332     del node
333
334     self.assertEqual(node2.name, "node32087.example.com")
335     self.assertEqual(frozenset(node2.disk_state), frozenset([
336       constants.LD_LV,
337       ]))
338     self.assertEqual(frozenset(node2.disk_state[constants.LD_LV]), frozenset([
339       "lv32352",
340       "lv2082",
341       ]))
342     self.assertEqual(node2.disk_state[constants.LD_LV]["lv2082"].total, 512)
343     self.assertEqual(node2.disk_state[constants.LD_LV]["lv32352"].total, 128)
344
345
346 if __name__ == '__main__':
347   testutils.GanetiTestProgram()