Fix a bug in command line option parsing code
[ganeti-local] / lib / rapi / rlib2.py
index ab54c25..ab89270 100644 (file)
@@ -28,11 +28,11 @@ According to RFC2616 the main difference between PUT and POST is that
 POST can create new resources but PUT can only create the resource the
 URI was pointing to on the PUT request.
 
-In the context of this module POST on ``/2/instances`` to chance an existing
+In the context of this module POST on ``/2/instances`` to change an existing
 entity is legitimate, while PUT would not be. PUT creates a new entity (e.g. a
 new instance) with a name specified in the request.
 
-Quoting from RFC2616, section 9.6:
+Quoting from RFC2616, section 9.6::
 
   The fundamental difference between the POST and PUT requests is reflected in
   the different meaning of the Request-URI. The URI in a POST request
@@ -51,7 +51,7 @@ PUT should be prefered over POST.
 
 """
 
-# pylint: disable-msg=C0103
+# pylint: disable=C0103
 
 # C0103: Invalid name, since the R_* names are not conforming
 
@@ -415,6 +415,8 @@ class R_2_nodes_name_role(baserlib.R_Generic):
     node_name = self.items[0]
     role = self.request_body
 
+    auto_promote = bool(self._checkIntVariable("auto-promote"))
+
     if role == _NR_REGULAR:
       candidate = False
       offline = False
@@ -439,6 +441,7 @@ class R_2_nodes_name_role(baserlib.R_Generic):
                                  master_candidate=candidate,
                                  offline=offline,
                                  drained=drained,
+                                 auto_promote=auto_promote,
                                  force=bool(self.useForce()))
 
     return baserlib.SubmitJob([op])
@@ -497,6 +500,25 @@ class R_2_nodes_name_migrate(baserlib.R_Generic):
     return baserlib.SubmitJob([op])
 
 
+class R_2_nodes_name_modify(baserlib.R_Generic):
+  """/2/nodes/[node_name]/modify resource.
+
+  """
+  def POST(self):
+    """Changes parameters of a node.
+
+    @return: a job id
+
+    """
+    baserlib.CheckType(self.request_body, dict, "Body contents")
+
+    op = baserlib.FillOpcode(opcodes.OpNodeSetParams, self.request_body, {
+      "node_name": self.items[0],
+      })
+
+    return baserlib.SubmitJob([op])
+
+
 class R_2_nodes_name_storage(baserlib.R_Generic):
   """/2/nodes/[node_name]/storage resource.
 
@@ -664,7 +686,6 @@ def _ParseModifyGroupRequest(name, data):
     })
 
 
-
 class R_2_groups_name_modify(baserlib.R_Generic):
   """/2/groups/[group_name]/modify resource.
 
@@ -923,8 +944,6 @@ class R_2_instances_name_shutdown(baserlib.R_Generic):
     @return: a job id
 
     """
-    baserlib.CheckType(self.request_body, dict, "Body contents")
-
     no_remember = bool(self._checkIntVariable("no_remember"))
     op = _ParseShutdownInstanceRequest(self.items[0], self.request_body,
                                        bool(self.dryRun()), no_remember)
@@ -1002,16 +1021,19 @@ def _ParseInstanceReplaceDisksRequest(name, data):
 
   # Parse disks
   try:
-    raw_disks = data["disks"]
+    raw_disks = data.pop("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))
+    if raw_disks:
+      if ht.TListOf(ht.TInt)(raw_disks): # pylint: disable=E1102
+        data["disks"] = raw_disks
+      else:
+        # 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)
 
@@ -1024,7 +1046,20 @@ class R_2_instances_name_replace_disks(baserlib.R_Generic):
     """Replaces disks on an instance.
 
     """
-    op = _ParseInstanceReplaceDisksRequest(self.items[0], self.request_body)
+    if self.request_body:
+      body = self.request_body
+    elif self.queryargs:
+      # Legacy interface, do not modify/extend
+      body = {
+        "remote_node": self._checkStringVariable("remote_node", default=None),
+        "mode": self._checkStringVariable("mode", default=None),
+        "disks": self._checkStringVariable("disks", default=None),
+        "iallocator": self._checkStringVariable("iallocator", default=None),
+        }
+    else:
+      body = {}
+
+    op = _ParseInstanceReplaceDisksRequest(self.items[0], body)
 
     return baserlib.SubmitJob([op])
 
@@ -1369,7 +1404,7 @@ class _R_Tags(baserlib.R_Generic):
     Example: ["tag1", "tag2", "tag3"]
 
     """
-    # pylint: disable-msg=W0212
+    # pylint: disable=W0212
     return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
 
   def PUT(self):
@@ -1379,7 +1414,7 @@ class _R_Tags(baserlib.R_Generic):
     you'll have back a job id.
 
     """
-    # pylint: disable-msg=W0212
+    # pylint: disable=W0212
     if "tag" not in self.queryargs:
       raise http.HttpBadRequest("Please specify tag(s) to add using the"
                                 " the 'tag' parameter")
@@ -1395,7 +1430,7 @@ class _R_Tags(baserlib.R_Generic):
     /tags?tag=[tag]&tag=[tag]
 
     """
-    # pylint: disable-msg=W0212
+    # pylint: disable=W0212
     if "tag" not in self.queryargs:
       # no we not gonna delete all tags
       raise http.HttpBadRequest("Cannot delete all tags - please specify"