"""
-# pylint: disable-msg=C0103
+# pylint: disable=C0103
# C0103: Invalid name, since the R_* names are not conforming
"name",
"node_cnt",
"node_list",
+ "ipolicy",
] + _COMMON_FIELDS
J_FIELDS_BULK = [
return None
+class R_2(R_root):
+ """/2 resource.
+
+ """
+
+
class R_version(baserlib.ResourceBase):
"""/version resource.
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.
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.
}
-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.
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.
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.
"offline": offline,
"drained": drained,
"force": self.useForce(),
+ "auto_promote": bool(self._checkIntVariable("auto-promote", default=0)),
})
})
+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.
"""/2/groups resource.
"""
+ GET_OPCODE = opcodes.OpGroupQuery
POST_OPCODE = opcodes.OpGroupAdd
POST_RENAME = {
"name": "group_name",
"""/2/instances resource.
"""
+ GET_OPCODE = opcodes.OpInstanceQuery
POST_OPCODE = opcodes.OpInstanceCreate
POST_RENAME = {
"os": "os_type",
"""/2/instances/[instance_name] resource.
"""
+ GET_OPCODE = opcodes.OpInstanceQuery
DELETE_OPCODE = opcodes.OpInstanceRemove
def GET(self):
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.
"""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)
})
+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.
"""
GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
+ GET_OPCODE = opcodes.OpInstanceConsole
def GET(self):
"""Request information for connecting to instance's console.
"""
# 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.
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.
"""
TAG_LEVEL = None
+ GET_OPCODE = opcodes.OpTagsGet
PUT_OPCODE = opcodes.OpTagsSet
DELETE_OPCODE = opcodes.OpTagsDel