From a52978c71b8f86c6854dd946ec66325e772e804f Mon Sep 17 00:00:00 2001 From: Michael Hanselmann <hansmi@google.com> Date: Thu, 15 Sep 2011 17:41:59 +0200 Subject: [PATCH] RAPI: Add resource to recreate instance's disks This was still missing from RAPI. Signed-off-by: Michael Hanselmann <hansmi@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- doc/rapi.rst | 17 +++++++++++++++++ lib/opcodes.py | 2 +- lib/rapi/client.py | 25 +++++++++++++++++++++++++ lib/rapi/connector.py | 2 ++ lib/rapi/rlib2.py | 15 +++++++++++++++ test/docs_unittest.py | 1 - test/ganeti.rapi.client_unittest.py | 8 ++++++++ test/ganeti.rapi.rlib2_unittest.py | 20 ++++++++++++++++++++ 8 files changed, 88 insertions(+), 2 deletions(-) diff --git a/doc/rapi.rst b/doc/rapi.rst index efb4a4b5e..20602b052 100644 --- a/doc/rapi.rst +++ b/doc/rapi.rst @@ -811,6 +811,23 @@ It supports the following commands: ``PUT``. Takes no parameters. +``/2/instances/[instance_name]/recreate-disks`` ++++++++++++++++++++++++++++++++++++++++++++++++++ + +Recreate disks of an instance. Supports the following commands: +``POST``. + +``POST`` +~~~~~~~~ + +Returns a job ID. + +Body parameters: + +.. opcode_params:: OP_INSTANCE_RECREATE_DISKS + :exclude: instance_name + + ``/2/instances/[instance_name]/disk/[disk_index]/grow`` +++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/lib/opcodes.py b/lib/opcodes.py index 36104f7c7..6b2f1870b 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -1268,7 +1268,7 @@ class OpInstanceDeactivateDisks(OpCode): class OpInstanceRecreateDisks(OpCode): - """Deactivate an instance's disks.""" + """Recreate an instance's disks.""" OP_DSC_FIELD = "instance_name" OP_PARAMS = [ _PInstanceName, diff --git a/lib/rapi/client.py b/lib/rapi/client.py index dac670b1b..8ad0d95a1 100644 --- a/lib/rapi/client.py +++ b/lib/rapi/client.py @@ -753,6 +753,31 @@ class GanetiRapiClient(object): # pylint: disable=R0904 ("/%s/instances/%s/deactivate-disks" % (GANETI_RAPI_VERSION, instance)), None, None) + def RecreateInstanceDisks(self, instance, disks=None, nodes=None): + """Recreate an instance's disks. + + @type instance: string + @param instance: Instance name + @type disks: list of int + @param disks: List of disk indexes + @type nodes: list of string + @param nodes: New instance nodes, if relocation is desired + @rtype: string + @return: job id + + """ + body = {} + + if disks is not None: + body["disks"] = disks + + if nodes is not None: + body["nodes"] = nodes + + return self._SendRequest(HTTP_POST, + ("/%s/instances/%s/recreate-disks" % + (GANETI_RAPI_VERSION, instance)), None, body) + def GrowInstanceDisk(self, instance, disk, amount, wait_for_sync=None): """Grows a disk of an instance. diff --git a/lib/rapi/connector.py b/lib/rapi/connector.py index d8524efad..8d0d3951a 100644 --- a/lib/rapi/connector.py +++ b/lib/rapi/connector.py @@ -143,6 +143,8 @@ def GetHandlers(node_name_pattern, instance_name_pattern, rlib2.R_2_instances_name_activate_disks, re.compile(r"^/2/instances/(%s)/deactivate-disks$" % instance_name_pattern): rlib2.R_2_instances_name_deactivate_disks, + re.compile(r"^/2/instances/(%s)/recreate-disks$" % instance_name_pattern): + rlib2.R_2_instances_name_recreate_disks, re.compile(r"^/2/instances/(%s)/prepare-export$" % instance_name_pattern): rlib2.R_2_instances_name_prepare_export, re.compile(r"^/2/instances/(%s)/export$" % instance_name_pattern): diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py index 76d640b12..0d4f29ab3 100644 --- a/lib/rapi/rlib2.py +++ b/lib/rapi/rlib2.py @@ -995,6 +995,21 @@ class R_2_instances_name_deactivate_disks(baserlib.OpcodeResource): }) +class R_2_instances_name_recreate_disks(baserlib.OpcodeResource): + """/2/instances/[instance_name]/recreate-disks resource. + + """ + POST_OPCODE = opcodes.OpInstanceRecreateDisks + + def GetPostOpInput(self): + """Recreate disks for an instance. + + """ + return ({}, { + "instance_name": self.items[0], + }) + + class R_2_instances_name_prepare_export(baserlib.OpcodeResource): """/2/instances/[instance_name]/prepare-export resource. diff --git a/test/docs_unittest.py b/test/docs_unittest.py index 1815805d2..a695280a7 100755 --- a/test/docs_unittest.py +++ b/test/docs_unittest.py @@ -53,7 +53,6 @@ RAPI_OPCODE_EXCLUDE = frozenset([ opcodes.OpClusterVerifyDisks, opcodes.OpInstanceChangeGroup, opcodes.OpInstanceMove, - opcodes.OpInstanceRecreateDisks, opcodes.OpNodePowercycle, opcodes.OpNodeQueryvols, opcodes.OpOobCommand, diff --git a/test/ganeti.rapi.client_unittest.py b/test/ganeti.rapi.client_unittest.py index 2d17df877..81d6ea6da 100755 --- a/test/ganeti.rapi.client_unittest.py +++ b/test/ganeti.rapi.client_unittest.py @@ -1166,6 +1166,14 @@ class GanetiRapiClientTests(testutils.GanetiTestCase): self.assertHandler(rlib2.R_2_instances_name_deactivate_disks) self.assertFalse(self.rapi.GetLastHandler().queryargs) + def testRecreateInstanceDisks(self): + self.rapi.AddResponse("13553") + job_id = self.client.RecreateInstanceDisks("inst23153") + self.assertEqual(job_id, 13553) + self.assertItems(["inst23153"]) + self.assertHandler(rlib2.R_2_instances_name_recreate_disks) + self.assertFalse(self.rapi.GetLastHandler().queryargs) + def testGetInstanceConsole(self): self.rapi.AddResponse("26876") job_id = self.client.GetInstanceConsole("inst21491") diff --git a/test/ganeti.rapi.rlib2_unittest.py b/test/ganeti.rapi.rlib2_unittest.py index 58127e4f8..74176adc1 100755 --- a/test/ganeti.rapi.rlib2_unittest.py +++ b/test/ganeti.rapi.rlib2_unittest.py @@ -446,6 +446,26 @@ class TestInstanceDeactivateDisks(unittest.TestCase): self.assertRaises(IndexError, cl.GetNextSubmittedJob) +class TestInstanceRecreateDisks(unittest.TestCase): + def test(self): + clfactory = _FakeClientFactory(_FakeClient) + handler = _CreateHandler(rlib2.R_2_instances_name_recreate_disks, + ["inst22357"], {}, {}, clfactory) + job_id = handler.POST() + + cl = clfactory.GetNextClient() + self.assertRaises(IndexError, clfactory.GetNextClient) + + (exp_job_id, (op, )) = cl.GetNextSubmittedJob() + self.assertEqual(job_id, exp_job_id) + self.assertTrue(isinstance(op, opcodes.OpInstanceRecreateDisks)) + self.assertEqual(op.instance_name, "inst22357") + self.assertFalse(hasattr(op, "dry_run")) + self.assertFalse(hasattr(op, "force")) + + self.assertRaises(IndexError, cl.GetNextSubmittedJob) + + class TestInstanceFailover(unittest.TestCase): def test(self): clfactory = _FakeClientFactory(_FakeClient) -- GitLab