From 3882937a7015bd4e66b912d4d9af1f46e3dbb27b Mon Sep 17 00:00:00 2001 From: Michael Hanselmann Date: Tue, 17 Aug 2010 18:50:11 +0200 Subject: [PATCH] RAPI: Allow modifying instance Signed-off-by: Michael Hanselmann Reviewed-by: Iustin Pop --- doc/rapi.rst | 39 ++++++++++++++++++++++ lib/rapi/connector.py | 2 ++ lib/rapi/rlib2.py | 50 ++++++++++++++++++++++++++++ test/ganeti.rapi.rlib2_unittest.py | 63 ++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) diff --git a/doc/rapi.rst b/doc/rapi.rst index 38e7e59..fcf955a 100644 --- a/doc/rapi.rst +++ b/doc/rapi.rst @@ -671,6 +671,45 @@ Body parameters: Whether to ensure instance's name is resolvable. +``/2/instances/[instance_name]/modify`` +++++++++++++++++++++++++++++++++++++++++ + +Modifies an instance. + +Supports the following commands: ``PUT``. + +``PUT`` +~~~~~~~ + +Returns a job ID. + +Body parameters: + +``osparams`` (dict) + Dictionary with OS parameters. +``hvparams`` (dict) + Hypervisor parameters, hypervisor-dependent. +``beparams`` (dict) + Backend parameters. +``force`` (bool) + Whether to force the operation. +``nics`` (list) + List of NIC changes. Each item is of the form ``(op, settings)``. + ``op`` can be ``add`` to add a new NIC with the specified settings, + ``remove`` to remove the last NIC or a number to modify the settings + of the NIC with that index. +``disks`` (list) + List of disk changes. See ``nics``. +``disk_template`` (string) + Disk template for instance. +``remote_node`` (string) + Secondary node (used when changing disk template). +``os_name`` (string) + Change instance's OS name. Does not reinstall the instance. +``force_variant`` (bool) + Whether to force an unknown variant. + + ``/2/instances/[instance_name]/tags`` +++++++++++++++++++++++++++++++++++++ diff --git a/lib/rapi/connector.py b/lib/rapi/connector.py index b865e74..648aa0b 100644 --- a/lib/rapi/connector.py +++ b/lib/rapi/connector.py @@ -217,6 +217,8 @@ def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern): rlib2.R_2_instances_name_migrate, re.compile(r'^/2/instances/(%s)/rename$' % instance_name_pattern): rlib2.R_2_instances_name_rename, + re.compile(r'^/2/instances/(%s)/modify$' % instance_name_pattern): + rlib2.R_2_instances_name_modify, "/2/jobs": rlib2.R_2_jobs, re.compile(r"^/2/jobs/(%s)$" % job_id_pattern): diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py index cacf7d8..b7e9b9b 100644 --- a/lib/rapi/rlib2.py +++ b/lib/rapi/rlib2.py @@ -1055,6 +1055,56 @@ class R_2_instances_name_rename(baserlib.R_Generic): return baserlib.SubmitJob([op]) +def _ParseModifyInstanceRequest(name, data): + """Parses a request for modifying an instance. + + @rtype: L{opcodes.OpSetInstanceParams} + @return: Instance modify opcode + + """ + osparams = baserlib.CheckParameter(data, "osparams", default={}) + force = baserlib.CheckParameter(data, "force", default=False) + nics = baserlib.CheckParameter(data, "nics", default=[]) + disks = baserlib.CheckParameter(data, "disks", default=[]) + disk_template = baserlib.CheckParameter(data, "disk_template", default=None) + remote_node = baserlib.CheckParameter(data, "remote_node", default=None) + os_name = baserlib.CheckParameter(data, "os_name", default=None) + force_variant = baserlib.CheckParameter(data, "force_variant", default=False) + + # HV/BE parameters + hvparams = baserlib.CheckParameter(data, "hvparams", default={}) + utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES, + allowed_values=[constants.VALUE_DEFAULT]) + + beparams = baserlib.CheckParameter(data, "beparams", default={}) + utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES, + allowed_values=[constants.VALUE_DEFAULT]) + + return opcodes.OpSetInstanceParams(instance_name=name, hvparams=hvparams, + beparams=beparams, osparams=osparams, + force=force, nics=nics, disks=disks, + disk_template=disk_template, + remote_node=remote_node, os_name=os_name, + force_variant=force_variant) + + +class R_2_instances_name_modify(baserlib.R_Generic): + """/2/instances/[instance_name]/modify resource. + + """ + def PUT(self): + """Changes some parameters of an instance. + + @return: a job id + + """ + baserlib.CheckType(self.request_body, dict, "Body contents") + + op = _ParseModifyInstanceRequest(self.items[0], self.request_body) + + return baserlib.SubmitJob([op]) + + class _R_Tags(baserlib.R_Generic): """ Quasiclass for tagging resources diff --git a/test/ganeti.rapi.rlib2_unittest.py b/test/ganeti.rapi.rlib2_unittest.py index 632001d..e9effb8 100755 --- a/test/ganeti.rapi.rlib2_unittest.py +++ b/test/ganeti.rapi.rlib2_unittest.py @@ -295,5 +295,68 @@ class TestParseRenameInstanceRequest(testutils.GanetiTestCase): self.assert_(op.name_check) +class TestParseModifyInstanceRequest(testutils.GanetiTestCase): + def setUp(self): + testutils.GanetiTestCase.setUp(self) + + self.Parse = rlib2._ParseModifyInstanceRequest + + def test(self): + name = "instush8gah" + + test_disks = [ + [], + [(1, { constants.IDISK_MODE: constants.DISK_RDWR, })], + ] + + for osparams in [{}, { "some": "value", "other": "Hello World", }]: + for hvparams in [{}, { constants.HV_KERNEL_PATH: "/some/kernel", }]: + for beparams in [{}, { constants.BE_MEMORY: 128, }]: + for force in [False, True]: + for nics in [[], [(0, { constants.INIC_IP: "192.0.2.1", })]]: + for disks in test_disks: + for disk_template in constants.DISK_TEMPLATES: + data = { + "osparams": osparams, + "hvparams": hvparams, + "beparams": beparams, + "nics": nics, + "disks": disks, + "force": force, + "disk_template": disk_template, + } + + op = self.Parse(name, data) + self.assert_(isinstance(op, opcodes.OpSetInstanceParams)) + self.assertEqual(op.instance_name, name) + self.assertEqual(op.hvparams, hvparams) + self.assertEqual(op.beparams, beparams) + self.assertEqual(op.osparams, osparams) + self.assertEqual(op.force, force) + self.assertEqual(op.nics, nics) + self.assertEqual(op.disks, disks) + self.assertEqual(op.disk_template, disk_template) + self.assert_(op.remote_node is None) + self.assert_(op.os_name is None) + self.assertFalse(op.force_variant) + + def testDefaults(self): + name = "instir8aish31" + + op = self.Parse(name, {}) + self.assert_(isinstance(op, opcodes.OpSetInstanceParams)) + self.assertEqual(op.instance_name, name) + self.assertEqual(op.hvparams, {}) + self.assertEqual(op.beparams, {}) + self.assertEqual(op.osparams, {}) + self.assertFalse(op.force) + self.assertEqual(op.nics, []) + self.assertEqual(op.disks, []) + self.assert_(op.disk_template is None) + self.assert_(op.remote_node is None) + self.assert_(op.os_name is None) + self.assertFalse(op.force_variant) + + if __name__ == '__main__': testutils.GanetiTestProgram() -- 1.7.10.4