4 # Copyright (C) 2010 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 RAPI rlib2 module
30 from ganeti import constants
31 from ganeti import opcodes
32 from ganeti import compat
33 from ganeti import http
35 from ganeti.rapi import rlib2
40 class TestParseInstanceCreateRequestVersion1(testutils.GanetiTestCase):
42 testutils.GanetiTestCase.setUp(self)
44 self.Parse = rlib2._ParseInstanceCreateRequestVersion1
52 [{"size": 5, }, {"size": 100, }],
55 [{"size": 123, "mode": constants.DISK_RDWR, }],
57 # With unknown setting
58 [{"size": 123, "unknown": 999 }],
70 { "ip": "192.0.2.6", "mode": constants.NIC_MODE_ROUTED,
71 "mac": "01:23:45:67:68:9A",
73 { "mode": constants.NIC_MODE_BRIDGED, "link": "n0", "bridge": "br1", },
77 [{ "unknown": 999, }, { "foobar": "Hello World", }],
83 { constants.BE_VCPUS: 2, },
84 { constants.BE_MEMORY: 123, },
85 { constants.BE_VCPUS: 2,
86 constants.BE_MEMORY: 1024,
87 constants.BE_AUTO_BALANCE: True, }
92 { constants.HV_BOOT_ORDER: "anc", },
93 { constants.HV_KERNEL_PATH: "/boot/fookernel",
94 constants.HV_ROOT_PATH: "/dev/hda1", },
97 for mode in [constants.INSTANCE_CREATE, constants.INSTANCE_IMPORT]:
98 for nics in nic_variants:
99 for disk_template in constants.DISK_TEMPLATES:
100 for disks in disk_variants:
101 for beparams in beparam_variants:
102 for hvparams in hvparam_variants:
104 "name": "inst1.example.com",
105 "hypervisor": constants.HT_FAKE,
109 "disk_template": disk_template,
113 if beparams is not None:
114 data["beparams"] = beparams
116 if hvparams is not None:
117 data["hvparams"] = hvparams
119 for dry_run in [False, True]:
120 op = self.Parse(data, dry_run)
121 self.assert_(isinstance(op, opcodes.OpInstanceCreate))
122 self.assertEqual(op.mode, mode)
123 self.assertEqual(op.disk_template, disk_template)
124 self.assertEqual(op.dry_run, dry_run)
125 self.assertEqual(len(op.disks), len(disks))
126 self.assertEqual(len(op.nics), len(nics))
128 for opdisk, disk in zip(op.disks, disks):
129 for key in constants.IDISK_PARAMS:
130 self.assertEqual(opdisk.get(key), disk.get(key))
131 self.assertFalse("unknown" in opdisk)
133 for opnic, nic in zip(op.nics, nics):
134 for key in constants.INIC_PARAMS:
135 self.assertEqual(opnic.get(key), nic.get(key))
136 self.assertFalse("unknown" in opnic)
137 self.assertFalse("foobar" in opnic)
140 self.assertEqualValues(op.beparams, {})
142 self.assertEqualValues(op.beparams, beparams)
145 self.assertEqualValues(op.hvparams, {})
147 self.assertEqualValues(op.hvparams, hvparams)
149 def testErrors(self):
150 # Test all required fields
152 "name": "inst1.example.com",
155 "mode": constants.INSTANCE_CREATE,
156 "disk_template": constants.DT_PLAIN,
160 for name in reqfields.keys():
161 self.assertRaises(http.HttpBadRequest, self.Parse,
162 dict(i for i in reqfields.iteritems() if i[0] != name),
165 # Invalid disks and nics
166 for field in ["disks", "nics"]:
167 invalid_values = [None, 1, "", {}, [1, 2, 3], ["hda1", "hda2"]]
170 invalid_values.append([
173 { "mode": constants.DISK_RDWR, },
176 for invvalue in invalid_values:
177 data = reqfields.copy()
178 data[field] = invvalue
179 self.assertRaises(http.HttpBadRequest, self.Parse, data, False)
182 class TestParseExportInstanceRequest(testutils.GanetiTestCase):
184 testutils.GanetiTestCase.setUp(self)
186 self.Parse = rlib2._ParseExportInstanceRequest
191 "mode": constants.EXPORT_MODE_REMOTE,
192 "destination": [(1, 2, 3), (99, 99, 99)],
194 "remove_instance": True,
195 "x509_key_name": ["name", "hash"],
196 "destination_x509_ca": "---cert---"
198 op = self.Parse(name, data)
199 self.assert_(isinstance(op, opcodes.OpBackupExport))
200 self.assertEqual(op.instance_name, name)
201 self.assertEqual(op.mode, constants.EXPORT_MODE_REMOTE)
202 self.assertEqual(op.shutdown, True)
203 self.assertEqual(op.remove_instance, True)
204 self.assertEqualValues(op.x509_key_name, ("name", "hash"))
205 self.assertEqual(op.destination_x509_ca, "---cert---")
207 def testDefaults(self):
210 "destination": "node2",
213 op = self.Parse(name, data)
214 self.assert_(isinstance(op, opcodes.OpBackupExport))
215 self.assertEqual(op.instance_name, name)
216 self.assertEqual(op.target_node, "node2")
217 self.assertFalse(hasattr(op, "mode"))
218 self.assertFalse(hasattr(op, "remove_instance"))
219 self.assertFalse(hasattr(op, "destination"))
221 def testErrors(self):
222 self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
223 { "remove_instance": "True", })
224 self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
225 { "remove_instance": "False", })
228 class TestParseMigrateInstanceRequest(testutils.GanetiTestCase):
230 testutils.GanetiTestCase.setUp(self)
232 self.Parse = rlib2._ParseMigrateInstanceRequest
235 name = "instYooho6ek"
237 for cleanup in [False, True]:
238 for mode in constants.HT_MIGRATION_MODES:
243 op = self.Parse(name, data)
244 self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
245 self.assertEqual(op.instance_name, name)
246 self.assertEqual(op.mode, mode)
247 self.assertEqual(op.cleanup, cleanup)
249 def testDefaults(self):
250 name = "instnohZeex0"
252 op = self.Parse(name, {})
253 self.assert_(isinstance(op, opcodes.OpInstanceMigrate))
254 self.assertEqual(op.instance_name, name)
255 self.assertFalse(hasattr(op, "mode"))
256 self.assertFalse(hasattr(op, "cleanup"))
259 class TestParseRenameInstanceRequest(testutils.GanetiTestCase):
261 testutils.GanetiTestCase.setUp(self)
263 self.Parse = rlib2._ParseRenameInstanceRequest
266 name = "instij0eeph7"
268 for new_name in ["ua0aiyoo", "fai3ongi"]:
269 for ip_check in [False, True]:
270 for name_check in [False, True]:
272 "new_name": new_name,
273 "ip_check": ip_check,
274 "name_check": name_check,
277 op = self.Parse(name, data)
278 self.assert_(isinstance(op, opcodes.OpInstanceRename))
279 self.assertEqual(op.instance_name, name)
280 self.assertEqual(op.new_name, new_name)
281 self.assertEqual(op.ip_check, ip_check)
282 self.assertEqual(op.name_check, name_check)
284 def testDefaults(self):
285 name = "instahchie3t"
287 for new_name in ["thag9mek", "quees7oh"]:
289 "new_name": new_name,
292 op = self.Parse(name, data)
293 self.assert_(isinstance(op, opcodes.OpInstanceRename))
294 self.assertEqual(op.instance_name, name)
295 self.assertEqual(op.new_name, new_name)
296 self.assertFalse(hasattr(op, "ip_check"))
297 self.assertFalse(hasattr(op, "name_check"))
300 class TestParseModifyInstanceRequest(testutils.GanetiTestCase):
302 testutils.GanetiTestCase.setUp(self)
304 self.Parse = rlib2._ParseModifyInstanceRequest
311 [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })],
314 for osparams in [{}, { "some": "value", "other": "Hello World", }]:
315 for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]:
316 for beparams in [{}, { constants.BE_MEMORY: 128, }]:
317 for force in [False, True]:
318 for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]:
319 for disks in test_disks:
320 for disk_template in constants.DISK_TEMPLATES:
322 "osparams": osparams,
323 "hvparams": hvparams,
324 "beparams": beparams,
328 "disk_template": disk_template,
331 op = self.Parse(name, data)
332 self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
333 self.assertEqual(op.instance_name, name)
334 self.assertEqual(op.hvparams, hvparams)
335 self.assertEqual(op.beparams, beparams)
336 self.assertEqual(op.osparams, osparams)
337 self.assertEqual(op.force, force)
338 self.assertEqual(op.nics, nics)
339 self.assertEqual(op.disks, disks)
340 self.assertEqual(op.disk_template, disk_template)
341 self.assertFalse(hasattr(op, "remote_node"))
342 self.assertFalse(hasattr(op, "os_name"))
343 self.assertFalse(hasattr(op, "force_variant"))
345 def testDefaults(self):
346 name = "instir8aish31"
348 op = self.Parse(name, {})
349 self.assert_(isinstance(op, opcodes.OpInstanceSetParams))
350 self.assertEqual(op.instance_name, name)
351 for i in ["hvparams", "beparams", "osparams", "force", "nics", "disks",
352 "disk_template", "remote_node", "os_name", "force_variant"]:
353 self.assertFalse(hasattr(op, i))
356 class TestParseInstanceReinstallRequest(testutils.GanetiTestCase):
358 testutils.GanetiTestCase.setUp(self)
360 self.Parse = rlib2._ParseInstanceReinstallRequest
362 def _Check(self, ops, name):
364 opcodes.OpInstanceShutdown,
365 opcodes.OpInstanceReinstall,
366 opcodes.OpInstanceStartup,
369 self.assert_(compat.all(isinstance(op, exp)
370 for op, exp in zip(ops, expcls)))
371 self.assert_(compat.all(op.instance_name == name for op in ops))
374 name = "shoo0tihohma"
376 ops = self.Parse(name, {"os": "sys1", "start": True,})
377 self.assertEqual(len(ops), 3)
378 self._Check(ops, name)
379 self.assertEqual(ops[1].os_type, "sys1")
380 self.assertFalse(ops[1].osparams)
382 ops = self.Parse(name, {"os": "sys2", "start": False,})
383 self.assertEqual(len(ops), 2)
384 self._Check(ops, name)
385 self.assertEqual(ops[1].os_type, "sys2")
390 ops = self.Parse(name, {"os": "sys4035", "start": True,
391 "osparams": osparams,})
392 self.assertEqual(len(ops), 3)
393 self._Check(ops, name)
394 self.assertEqual(ops[1].os_type, "sys4035")
395 self.assertEqual(ops[1].osparams, osparams)
397 def testDefaults(self):
400 ops = self.Parse(name, {"os": "linux1"})
401 self.assertEqual(len(ops), 3)
402 self._Check(ops, name)
403 self.assertEqual(ops[1].os_type, "linux1")
404 self.assertFalse(ops[1].osparams)
407 class TestParseRenameGroupRequest(testutils.GanetiTestCase):
409 testutils.GanetiTestCase.setUp(self)
411 self.Parse = rlib2._ParseRenameGroupRequest
414 name = "instij0eeph7"
416 "new_name": "ua0aiyoo",
419 op = self.Parse(name, data, False)
421 self.assert_(isinstance(op, opcodes.OpGroupRename))
422 self.assertEqual(op.old_name, name)
423 self.assertEqual(op.new_name, "ua0aiyoo")
424 self.assertFalse(op.dry_run)
426 def testDryRun(self):
427 name = "instij0eeph7"
429 "new_name": "ua0aiyoo",
432 op = self.Parse(name, data, True)
434 self.assert_(isinstance(op, opcodes.OpGroupRename))
435 self.assertEqual(op.old_name, name)
436 self.assertEqual(op.new_name, "ua0aiyoo")
437 self.assert_(op.dry_run)
440 class TestParseInstanceReplaceDisksRequest(unittest.TestCase):
442 self.Parse = rlib2._ParseInstanceReplaceDisksRequest
447 for disks in [range(1, 4), "1,2,3", "1, 2, 3"]:
449 "mode": constants.REPLACE_DISK_SEC,
451 "iallocator": "myalloc",
454 op = self.Parse(name, data)
455 self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
456 self.assertEqual(op.mode, constants.REPLACE_DISK_SEC)
457 self.assertEqual(op.disks, [1, 2, 3])
458 self.assertEqual(op.iallocator, "myalloc")
460 def testDefaults(self):
463 "mode": constants.REPLACE_DISK_AUTO,
466 op = self.Parse(name, data)
467 self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
468 self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO)
469 self.assertFalse(hasattr(op, "iallocator"))
470 self.assertFalse(hasattr(op, "disks"))
473 self.assertRaises(http.HttpBadRequest, self.Parse, "inst",
474 { "mode": constants.REPLACE_DISK_AUTO,
475 "disks": "hello world",
479 if __name__ == '__main__':
480 testutils.GanetiTestProgram()