Add new spindle_count node parameter
[ganeti-local] / lib / rapi / rlib2.py
index 80c695b..46e0029 100644 (file)
@@ -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
 
@@ -94,6 +94,7 @@ G_FIELDS = [
   "name",
   "node_cnt",
   "node_list",
+  "ipolicy",
   ] + _COMMON_FIELDS
 
 J_FIELDS_BULK = [
@@ -161,6 +162,12 @@ class R_root(baserlib.ResourceBase):
     return None
 
 
+class R_2(R_root):
+  """/2 resource.
+
+  """
+
+
 class R_version(baserlib.ResourceBase):
   """/version resource.
 
@@ -176,10 +183,12 @@ class R_version(baserlib.ResourceBase):
     return constants.RAPI_VERSION
 
 
-class R_2_info(baserlib.ResourceBase):
+class R_2_info(baserlib.OpcodeResource):
   """/2/info resource.
 
   """
+  GET_OPCODE = opcodes.OpClusterQuery
+
   def GET(self):
     """Returns cluster information.
 
@@ -200,10 +209,12 @@ class R_2_features(baserlib.ResourceBase):
     return list(ALL_FEATURES)
 
 
-class R_2_os(baserlib.ResourceBase):
+class R_2_os(baserlib.OpcodeResource):
   """/2/os resource.
 
   """
+  GET_OPCODE = opcodes.OpOsDiagnose
+
   def GET(self):
     """Return a list of all OSes.
 
@@ -345,10 +356,12 @@ class R_2_jobs_id_wait(baserlib.ResourceBase):
       }
 
 
-class R_2_nodes(baserlib.ResourceBase):
+class R_2_nodes(baserlib.OpcodeResource):
   """/2/nodes resource.
 
   """
+  GET_OPCODE = opcodes.OpNodeQuery
+
   def GET(self):
     """Returns a list of all nodes.
 
@@ -365,10 +378,12 @@ class R_2_nodes(baserlib.ResourceBase):
                                    uri_fields=("id", "uri"))
 
 
-class R_2_nodes_name(baserlib.ResourceBase):
+class R_2_nodes_name(baserlib.OpcodeResource):
   """/2/nodes/[node_name] resource.
 
   """
+  GET_OPCODE = opcodes.OpNodeQuery
+
   def GET(self):
     """Send information about a node.
 
@@ -383,6 +398,22 @@ class R_2_nodes_name(baserlib.ResourceBase):
     return baserlib.MapFields(N_FIELDS, result[0])
 
 
+class R_2_nodes_name_powercycle(baserlib.OpcodeResource):
+  """/2/nodes/[node_name]/powercycle resource.
+
+  """
+  POST_OPCODE = opcodes.OpNodePowercycle
+
+  def GetPostOpInput(self):
+    """Tries to powercycle a node.
+
+    """
+    return (self.request_body, {
+      "node_name": self.items[0],
+      "force": self.useForce(),
+      })
+
+
 class R_2_nodes_name_role(baserlib.OpcodeResource):
   """/2/nodes/[node_name]/role resource.
 
@@ -438,6 +469,7 @@ class R_2_nodes_name_role(baserlib.OpcodeResource):
       "offline": offline,
       "drained": drained,
       "force": self.useForce(),
+      "auto_promote": bool(self._checkIntVariable("auto-promote", default=0)),
       })
 
 
@@ -492,6 +524,23 @@ class R_2_nodes_name_migrate(baserlib.OpcodeResource):
       })
 
 
+class R_2_nodes_name_modify(baserlib.OpcodeResource):
+  """/2/nodes/[node_name]/modify resource.
+
+  """
+  POST_OPCODE = opcodes.OpNodeSetParams
+
+  def GetPostOpInput(self):
+    """Changes parameters of a node.
+
+    """
+    assert len(self.items) == 1
+
+    return (self.request_body, {
+      "node_name": self.items[0],
+      })
+
+
 class R_2_nodes_name_storage(baserlib.OpcodeResource):
   """/2/nodes/[node_name]/storage resource.
 
@@ -576,6 +625,7 @@ class R_2_groups(baserlib.OpcodeResource):
   """/2/groups resource.
 
   """
+  GET_OPCODE = opcodes.OpGroupQuery
   POST_OPCODE = opcodes.OpGroupAdd
   POST_RENAME = {
     "name": "group_name",
@@ -691,6 +741,7 @@ class R_2_instances(baserlib.OpcodeResource):
   """/2/instances resource.
 
   """
+  GET_OPCODE = opcodes.OpInstanceQuery
   POST_OPCODE = opcodes.OpInstanceCreate
   POST_RENAME = {
     "os": "os_type",
@@ -744,6 +795,7 @@ class R_2_instances_name(baserlib.OpcodeResource):
   """/2/instances/[instance_name] resource.
 
   """
+  GET_OPCODE = opcodes.OpInstanceQuery
   DELETE_OPCODE = opcodes.OpInstanceRemove
 
   def GET(self):
@@ -879,12 +931,14 @@ def _ParseInstanceReinstallRequest(name, data):
   return ops
 
 
-class R_2_instances_name_reinstall(baserlib.ResourceBase):
+class R_2_instances_name_reinstall(baserlib.OpcodeResource):
   """/2/instances/[instance_name]/reinstall resource.
 
   Implements an instance reinstall.
 
   """
+  POST_OPCODE = opcodes.OpInstanceReinstall
+
   def POST(self):
     """Reinstall an instance.
 
@@ -922,23 +976,38 @@ class R_2_instances_name_replace_disks(baserlib.OpcodeResource):
     """Replaces disks on an instance.
 
     """
-    data = self.request_body.copy()
     static = {
       "instance_name": self.items[0],
       }
 
+    if self.request_body:
+      data = self.request_body
+    elif self.queryargs:
+      # Legacy interface, do not modify/extend
+      data = {
+        "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:
+      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" % 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" % err)
 
     return (data, static)
 
@@ -976,6 +1045,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.
 
@@ -1091,6 +1175,7 @@ class R_2_instances_name_console(baserlib.ResourceBase):
 
   """
   GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
+  GET_OPCODE = opcodes.OpInstanceConsole
 
   def GET(self):
     """Request information for connecting to instance's console.
@@ -1135,9 +1220,11 @@ class R_2_query(baserlib.ResourceBase):
   """
   # Results might contain sensitive information
   GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
+  GET_OPCODE = opcodes.OpQuery
+  PUT_OPCODE = opcodes.OpQuery
 
-  def _Query(self, fields, filter_):
-    return self.GetClient().Query(self.items[0], fields, filter_).ToDict()
+  def _Query(self, fields, qfilter):
+    return self.GetClient().Query(self.items[0], fields, qfilter).ToDict()
 
   def GET(self):
     """Returns resource information.
@@ -1162,13 +1249,20 @@ class R_2_query(baserlib.ResourceBase):
     except KeyError:
       fields = _GetQueryFields(self.queryargs)
 
-    return self._Query(fields, self.request_body.get("filter", None))
+    qfilter = body.get("qfilter", None)
+    # TODO: remove this after 2.7
+    if qfilter is None:
+      qfilter = body.get("filter", None)
+
+    return self._Query(fields, qfilter)
 
 
 class R_2_query_fields(baserlib.ResourceBase):
   """/2/query/[resource]/fields resource.
 
   """
+  GET_OPCODE = opcodes.OpQueryFields
+
   def GET(self):
     """Retrieves list of available fields for a resource.
 
@@ -1193,6 +1287,7 @@ class _R_Tags(baserlib.OpcodeResource):
 
   """
   TAG_LEVEL = None
+  GET_OPCODE = opcodes.OpTagsGet
   PUT_OPCODE = opcodes.OpTagsSet
   DELETE_OPCODE = opcodes.OpTagsDel