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.OpCreateInstance))
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": ("x", "y", "z"),
198 op = self.Parse(name, data)
199 self.assert_(isinstance(op, opcodes.OpExportInstance))
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.assertEqualValues(op.destination_x509_ca, ("x", "y", "z"))
207 def testDefaults(self):
210 "destination": "node2",
213 op = self.Parse(name, data)
214 self.assert_(isinstance(op, opcodes.OpExportInstance))
215 self.assertEqual(op.instance_name, name)
216 self.assertEqual(op.mode, constants.EXPORT_MODE_LOCAL)
217 self.assertEqual(op.remove_instance, False)
219 def testErrors(self):
220 self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
221 { "remove_instance": "True", })
222 self.assertRaises(http.HttpBadRequest, self.Parse, "err1",
223 { "remove_instance": "False", })
226 class TestParseMigrateInstanceRequest(testutils.GanetiTestCase):
228 testutils.GanetiTestCase.setUp(self)
230 self.Parse = rlib2._ParseMigrateInstanceRequest
233 name = "instYooho6ek"
235 for cleanup in [False, True]:
236 for mode in constants.HT_MIGRATION_MODES:
241 op = self.Parse(name, data)
242 self.assert_(isinstance(op, opcodes.OpMigrateInstance))
243 self.assertEqual(op.instance_name, name)
244 self.assertEqual(op.mode, mode)
245 self.assertEqual(op.cleanup, cleanup)
247 def testDefaults(self):
248 name = "instnohZeex0"
250 op = self.Parse(name, {})
251 self.assert_(isinstance(op, opcodes.OpMigrateInstance))
252 self.assertEqual(op.instance_name, name)
253 self.assertEqual(op.mode, None)
254 self.assertFalse(op.cleanup)
257 class TestParseRenameInstanceRequest(testutils.GanetiTestCase):
259 testutils.GanetiTestCase.setUp(self)
261 self.Parse = rlib2._ParseRenameInstanceRequest
264 name = "instij0eeph7"
266 for new_name in ["ua0aiyoo", "fai3ongi"]:
267 for ip_check in [False, True]:
268 for name_check in [False, True]:
270 "new_name": new_name,
271 "ip_check": ip_check,
272 "name_check": name_check,
275 op = self.Parse(name, data)
276 self.assert_(isinstance(op, opcodes.OpRenameInstance))
277 self.assertEqual(op.instance_name, name)
278 self.assertEqual(op.new_name, new_name)
279 self.assertEqual(op.ip_check, ip_check)
280 self.assertEqual(op.name_check, name_check)
282 def testDefaults(self):
283 name = "instahchie3t"
285 for new_name in ["thag9mek", "quees7oh"]:
287 "new_name": new_name,
290 op = self.Parse(name, data)
291 self.assert_(isinstance(op, opcodes.OpRenameInstance))
292 self.assertEqual(op.instance_name, name)
293 self.assertEqual(op.new_name, new_name)
294 self.assert_(op.ip_check)
295 self.assert_(op.name_check)
298 class TestParseModifyInstanceRequest(testutils.GanetiTestCase):
300 testutils.GanetiTestCase.setUp(self)
302 self.Parse = rlib2._ParseModifyInstanceRequest
309 [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })],
312 for osparams in [{}, { "some": "value", "other": "Hello World", }]:
313 for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]:
314 for beparams in [{}, { constants.BE_MEMORY: 128, }]:
315 for force in [False, True]:
316 for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]:
317 for disks in test_disks:
318 for disk_template in constants.DISK_TEMPLATES:
320 "osparams": osparams,
321 "hvparams": hvparams,
322 "beparams": beparams,
326 "disk_template": disk_template,
329 op = self.Parse(name, data)
330 self.assert_(isinstance(op, opcodes.OpSetInstanceParams))
331 self.assertEqual(op.instance_name, name)
332 self.assertEqual(op.hvparams, hvparams)
333 self.assertEqual(op.beparams, beparams)
334 self.assertEqual(op.osparams, osparams)
335 self.assertEqual(op.force, force)
336 self.assertEqual(op.nics, nics)
337 self.assertEqual(op.disks, disks)
338 self.assertEqual(op.disk_template, disk_template)
339 self.assert_(op.remote_node is None)
340 self.assert_(op.os_name is None)
341 self.assertFalse(op.force_variant)
343 def testDefaults(self):
344 name = "instir8aish31"
346 op = self.Parse(name, {})
347 self.assert_(isinstance(op, opcodes.OpSetInstanceParams))
348 self.assertEqual(op.instance_name, name)
349 self.assertEqual(op.hvparams, {})
350 self.assertEqual(op.beparams, {})
351 self.assertEqual(op.osparams, {})
352 self.assertFalse(op.force)
353 self.assertEqual(op.nics, [])
354 self.assertEqual(op.disks, [])
355 self.assert_(op.disk_template is None)
356 self.assert_(op.remote_node is None)
357 self.assert_(op.os_name is None)
358 self.assertFalse(op.force_variant)
361 class TestParseInstanceReinstallRequest(testutils.GanetiTestCase):
363 testutils.GanetiTestCase.setUp(self)
365 self.Parse = rlib2._ParseInstanceReinstallRequest
367 def _Check(self, ops, name):
369 opcodes.OpShutdownInstance,
370 opcodes.OpReinstallInstance,
371 opcodes.OpStartupInstance,
374 self.assert_(compat.all(isinstance(op, exp)
375 for op, exp in zip(ops, expcls)))
376 self.assert_(compat.all(op.instance_name == name for op in ops))
379 name = "shoo0tihohma"
381 ops = self.Parse(name, {"os": "sys1", "start": True,})
382 self.assertEqual(len(ops), 3)
383 self._Check(ops, name)
384 self.assertEqual(ops[1].os_type, "sys1")
385 self.assertFalse(ops[1].osparams)
387 ops = self.Parse(name, {"os": "sys2", "start": False,})
388 self.assertEqual(len(ops), 2)
389 self._Check(ops, name)
390 self.assertEqual(ops[1].os_type, "sys2")
395 ops = self.Parse(name, {"os": "sys4035", "start": True,
396 "osparams": osparams,})
397 self.assertEqual(len(ops), 3)
398 self._Check(ops, name)
399 self.assertEqual(ops[1].os_type, "sys4035")
400 self.assertEqual(ops[1].osparams, osparams)
402 def testDefaults(self):
405 ops = self.Parse(name, {"os": "linux1"})
406 self.assertEqual(len(ops), 3)
407 self._Check(ops, name)
408 self.assertEqual(ops[1].os_type, "linux1")
409 self.assertFalse(ops[1].osparams)
412 if __name__ == '__main__':
413 testutils.GanetiTestProgram()