diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py index 2072944b2457dc9cc08f76522de2561836e8d1f6..62b454ea1417ab784c3a6eea31dee8220fbcc71c 100644 --- a/lib/rapi/rlib2.py +++ b/lib/rapi/rlib2.py @@ -47,6 +47,7 @@ from ganeti import constants from ganeti import cli from ganeti import utils from ganeti import rapi +from ganeti import ht from ganeti.rapi import baserlib @@ -1076,6 +1077,33 @@ class R_2_instances_name_reinstall(baserlib.R_Generic): return baserlib.SubmitJob(ops) +def _ParseInstanceReplaceDisksRequest(name, data): + """Parses a request for an instance export. + + @rtype: L{opcodes.OpInstanceReplaceDisks} + @return: Instance export opcode + + """ + override = { + "instance_name": name, + } + + # Parse disks + try: + raw_disks = data["disks"] + except KeyError: + pass + else: + if not ht.TListOf(ht.TInt)(raw_disks): # pylint: disable-msg=E1102 + # Backwards compatibility for strings of the format "1, 2, 3" + try: + data["disks"] = [int(part) for part in raw_disks.split(",")] + except (TypeError, ValueError), err: + raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err)) + + return baserlib.FillOpcode(opcodes.OpInstanceReplaceDisks, data, override) + + class R_2_instances_name_replace_disks(baserlib.R_Generic): """/2/instances/[instance_name]/replace-disks resource. @@ -1084,25 +1112,7 @@ class R_2_instances_name_replace_disks(baserlib.R_Generic): """Replaces disks on an instance. """ - instance_name = self.items[0] - remote_node = self._checkStringVariable("remote_node", default=None) - mode = self._checkStringVariable("mode", default=None) - raw_disks = self._checkStringVariable("disks", default=None) - iallocator = self._checkStringVariable("iallocator", default=None) - - if raw_disks: - try: - disks = [int(part) for part in raw_disks.split(",")] - except ValueError, err: - raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err)) - else: - disks = [] - - op = opcodes.OpInstanceReplaceDisks(instance_name=instance_name, - remote_node=remote_node, - mode=mode, - disks=disks, - iallocator=iallocator) + op = _ParseInstanceReplaceDisksRequest(self.items[0], self.request_body) return baserlib.SubmitJob([op]) diff --git a/test/ganeti.rapi.rlib2_unittest.py b/test/ganeti.rapi.rlib2_unittest.py index 35438d3ebb9697762f0ca48b060ea338860b9399..3e83d2f65775bc0146eb247a1b7e748313a0fe11 100755 --- a/test/ganeti.rapi.rlib2_unittest.py +++ b/test/ganeti.rapi.rlib2_unittest.py @@ -437,5 +437,44 @@ class TestParseRenameGroupRequest(testutils.GanetiTestCase): self.assert_(op.dry_run) +class TestParseInstanceReplaceDisksRequest(unittest.TestCase): + def setUp(self): + self.Parse = rlib2._ParseInstanceReplaceDisksRequest + + def test(self): + name = "inst22568" + + for disks in [range(1, 4), "1,2,3", "1, 2, 3"]: + data = { + "mode": constants.REPLACE_DISK_SEC, + "disks": disks, + "iallocator": "myalloc", + } + + op = self.Parse(name, data) + self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks)) + self.assertEqual(op.mode, constants.REPLACE_DISK_SEC) + self.assertEqual(op.disks, [1, 2, 3]) + self.assertEqual(op.iallocator, "myalloc") + + def testDefaults(self): + name = "inst11413" + data = { + "mode": constants.REPLACE_DISK_AUTO, + } + + op = self.Parse(name, data) + self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks)) + self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO) + self.assertFalse(hasattr(op, "iallocator")) + self.assertFalse(hasattr(op, "disks")) + + def testWrong(self): + self.assertRaises(http.HttpBadRequest, self.Parse, "inst", + { "mode": constants.REPLACE_DISK_AUTO, + "disks": "hello world", + }) + + if __name__ == '__main__': testutils.GanetiTestProgram()