rlib2: Convert /2/instances/[inst]/replace-disks to OpcodeResource
authorMichael Hanselmann <hansmi@google.com>
Thu, 8 Sep 2011 15:39:31 +0000 (17:39 +0200)
committerMichael Hanselmann <hansmi@google.com>
Fri, 9 Sep 2011 15:04:39 +0000 (17:04 +0200)
Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: RenĂ© Nussbaumer <rn@google.com>

lib/rapi/rlib2.py
test/ganeti.rapi.rlib2_unittest.py

index 48c697f..4f3bfb1 100644 (file)
@@ -922,44 +922,35 @@ class R_2_instances_name_reinstall(baserlib.ResourceBase):
     return self.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.ResourceBase):
+class R_2_instances_name_replace_disks(baserlib.OpcodeResource):
   """/2/instances/[instance_name]/replace-disks resource.
 
   """
-  def POST(self):
+  POST_OPCODE = opcodes.OpInstanceReplaceDisks
+
+  def GetPostOpInput(self):
     """Replaces disks on an instance.
 
     """
-    op = _ParseInstanceReplaceDisksRequest(self.items[0], self.request_body)
+    data = self.request_body.copy()
+    static = {
+      "instance_name": self.items[0],
+      }
 
-    return self.SubmitJob([op])
+    # 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" % err)
+
+    return (data, static)
 
 
 class R_2_instances_name_activate_disks(baserlib.ResourceBase):
index 74b5780..fd61d16 100755 (executable)
@@ -864,11 +864,10 @@ class TestGroupRename(unittest.TestCase):
     self.assertRaises(IndexError, cl.GetNextSubmittedJob)
 
 
-class TestParseInstanceReplaceDisksRequest(unittest.TestCase):
-  def setUp(self):
-    self.Parse = rlib2._ParseInstanceReplaceDisksRequest
-
+class TestInstanceReplaceDisks(unittest.TestCase):
   def test(self):
+    clfactory = _FakeClientFactory(_FakeClient)
+
     name = "inst22568"
 
     for disks in [range(1, 4), "1,2,3", "1, 2, 3"]:
@@ -878,29 +877,59 @@ class TestParseInstanceReplaceDisksRequest(unittest.TestCase):
         "iallocator": "myalloc",
         }
 
-      op = self.Parse(name, data)
-      self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
+      handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
+                               [name], {}, data, 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.OpInstanceReplaceDisks))
+      self.assertEqual(op.instance_name, name)
       self.assertEqual(op.mode, constants.REPLACE_DISK_SEC)
       self.assertEqual(op.disks, [1, 2, 3])
       self.assertEqual(op.iallocator, "myalloc")
+      self.assertRaises(IndexError, cl.GetNextSubmittedJob)
 
   def testDefaults(self):
+    clfactory = _FakeClientFactory(_FakeClient)
+
     name = "inst11413"
     data = {
       "mode": constants.REPLACE_DISK_AUTO,
       }
 
-    op = self.Parse(name, data)
-    self.assert_(isinstance(op, opcodes.OpInstanceReplaceDisks))
+    handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
+                             [name], {}, data, 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.OpInstanceReplaceDisks))
+    self.assertEqual(op.instance_name, name)
     self.assertEqual(op.mode, constants.REPLACE_DISK_AUTO)
     self.assertFalse(hasattr(op, "iallocator"))
     self.assertFalse(hasattr(op, "disks"))
+    self.assertRaises(IndexError, cl.GetNextSubmittedJob)
 
   def testWrong(self):
-    self.assertRaises(http.HttpBadRequest, self.Parse, "inst",
-                      { "mode": constants.REPLACE_DISK_AUTO,
-                        "disks": "hello world",
-                      })
+    clfactory = _FakeClientFactory(_FakeClient)
+
+    data = {
+      "mode": constants.REPLACE_DISK_AUTO,
+      "disks": "hello world",
+      }
+
+    handler = _CreateHandler(rlib2.R_2_instances_name_replace_disks,
+                             ["foo"], {}, data, clfactory)
+    self.assertRaises(http.HttpBadRequest, handler.POST)
 
 
 class TestGroupModify(unittest.TestCase):