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