"""
-# pylint: disable-msg=C0103
+# pylint: disable=C0103
# C0103: Invalid name, since the R_* names are not conforming
from ganeti import constants
from ganeti import http
+from ganeti import utils
-from ganeti.rapi import baserlib
from ganeti.rapi import rlib2
_NAME_PATTERN = r"[\w\._-]+"
+_DISK_PATTERN = r"\d+"
# the connection map is created at the end of this file
CONNECTOR = {}
- args: a dictionary with additional parameters from URL
"""
- if '?' in uri:
- (path, query) = uri.split('?', 1)
+ if "?" in uri:
+ (path, query) = uri.split("?", 1)
args = cgi.parse_qs(query)
else:
path = uri
query = None
args = {}
- result = None
+ # Try to find handler for request path
+ result = utils.FindMatch(self._connector, path)
- for key, handler in self._connector.iteritems():
- # Regex objects
- if hasattr(key, "match"):
- m = key.match(path)
- if m:
- result = (handler, list(m.groups()), args)
- break
-
- # String objects
- elif key == path:
- result = (handler, [], args)
- break
-
- if result:
- return result
- else:
+ if result is None:
raise http.HttpNotFound()
+ (handler, groups) = result
-class R_root(baserlib.R_Generic):
- """/ resource.
-
- """
- @staticmethod
- def GET():
- """Show the list of mapped resources.
-
- @return: a dictionary with 'name' and 'uri' keys for each of them.
-
- """
- root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
-
- rootlist = []
- for handler in CONNECTOR.values():
- m = root_pattern.match(handler.__name__)
- if m:
- name = m.group(1)
- if name != 'root':
- rootlist.append(name)
-
- return baserlib.BuildUriList(rootlist, "/%s")
-
-
-def _getResources(id_):
- """Return a list of resources underneath given id.
-
- This is to generalize querying of version resources lists.
+ return (handler, groups, args)
- @return: a list of resources names.
- """
- r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id_)
-
- rlist = []
- for handler in CONNECTOR.values():
- m = r_pattern.match(handler.__name__)
- if m:
- name = m.group(1)
- rlist.append(name)
-
- return rlist
-
-
-class R_2(baserlib.R_Generic):
- """ /2 resource, the root of the version 2 API.
-
- """
- @staticmethod
- def GET():
- """Show the list of mapped resources.
-
- @return: a dictionary with 'name' and 'uri' keys for each of them.
-
- """
- return baserlib.BuildUriList(_getResources("2"), "/2/%s")
-
-
-def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern):
+def GetHandlers(node_name_pattern, instance_name_pattern,
+ group_name_pattern, network_name_pattern,
+ job_id_pattern, disk_pattern,
+ query_res_pattern):
"""Returns all supported resources and their handlers.
"""
+ # Important note: New resources should always be added under /2. During a
+ # discussion in July 2010 it was decided that having per-resource versions
+ # is more flexible and future-compatible than versioning the whole remote
+ # API.
return {
- "/": R_root,
+ "/": rlib2.R_root,
+ "/2": rlib2.R_2,
"/version": rlib2.R_version,
- "/2": R_2,
-
"/2/nodes": rlib2.R_2_nodes,
- re.compile(r'^/2/nodes/(%s)$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)$" % node_name_pattern):
rlib2.R_2_nodes_name,
- re.compile(r'^/2/nodes/(%s)/tags$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/powercycle$" % node_name_pattern):
+ rlib2.R_2_nodes_name_powercycle,
+ re.compile(r"^/2/nodes/(%s)/tags$" % node_name_pattern):
rlib2.R_2_nodes_name_tags,
- re.compile(r'^/2/nodes/(%s)/role$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/role$" % node_name_pattern):
rlib2.R_2_nodes_name_role,
- re.compile(r'^/2/nodes/(%s)/evacuate$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/evacuate$" % node_name_pattern):
rlib2.R_2_nodes_name_evacuate,
- re.compile(r'^/2/nodes/(%s)/migrate$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/migrate$" % node_name_pattern):
rlib2.R_2_nodes_name_migrate,
- re.compile(r'^/2/nodes/(%s)/storage$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/modify$" % node_name_pattern):
+ rlib2.R_2_nodes_name_modify,
+ re.compile(r"^/2/nodes/(%s)/storage$" % node_name_pattern):
rlib2.R_2_nodes_name_storage,
- re.compile(r'^/2/nodes/(%s)/storage/modify$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/storage/modify$" % node_name_pattern):
rlib2.R_2_nodes_name_storage_modify,
- re.compile(r'^/2/nodes/(%s)/storage/repair$' % node_name_pattern):
+ re.compile(r"^/2/nodes/(%s)/storage/repair$" % node_name_pattern):
rlib2.R_2_nodes_name_storage_repair,
"/2/instances": rlib2.R_2_instances,
- re.compile(r'^/2/instances/(%s)$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)$" % instance_name_pattern):
rlib2.R_2_instances_name,
- re.compile(r'^/2/instances/(%s)/info$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/info$" % instance_name_pattern):
rlib2.R_2_instances_name_info,
- re.compile(r'^/2/instances/(%s)/tags$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/tags$" % instance_name_pattern):
rlib2.R_2_instances_name_tags,
- re.compile(r'^/2/instances/(%s)/reboot$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/reboot$" % instance_name_pattern):
rlib2.R_2_instances_name_reboot,
- re.compile(r'^/2/instances/(%s)/reinstall$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/reinstall$" % instance_name_pattern):
rlib2.R_2_instances_name_reinstall,
- re.compile(r'^/2/instances/(%s)/replace-disks$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/replace-disks$" % instance_name_pattern):
rlib2.R_2_instances_name_replace_disks,
- re.compile(r'^/2/instances/(%s)/shutdown$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/shutdown$" % instance_name_pattern):
rlib2.R_2_instances_name_shutdown,
- re.compile(r'^/2/instances/(%s)/startup$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/startup$" % instance_name_pattern):
rlib2.R_2_instances_name_startup,
- re.compile(r'^/2/instances/(%s)/activate-disks$' % instance_name_pattern):
+ re.compile(r"^/2/instances/(%s)/activate-disks$" % instance_name_pattern):
rlib2.R_2_instances_name_activate_disks,
- re.compile(r'^/2/instances/(%s)/deactivate-disks$' % instance_name_pattern):
+ 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):
+ rlib2.R_2_instances_name_export,
+ re.compile(r"^/2/instances/(%s)/migrate$" % instance_name_pattern):
+ rlib2.R_2_instances_name_migrate,
+ re.compile(r"^/2/instances/(%s)/failover$" % instance_name_pattern):
+ rlib2.R_2_instances_name_failover,
+ re.compile(r"^/2/instances/(%s)/rename$" % instance_name_pattern):
+ rlib2.R_2_instances_name_rename,
+ re.compile(r"^/2/instances/(%s)/modify$" % instance_name_pattern):
+ rlib2.R_2_instances_name_modify,
+ re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" %
+ (instance_name_pattern, disk_pattern)):
+ rlib2.R_2_instances_name_disk_grow,
+ re.compile(r"^/2/instances/(%s)/console$" % instance_name_pattern):
+ rlib2.R_2_instances_name_console,
+
+ "/2/networks": rlib2.R_2_networks,
+ re.compile(r"^/2/networks/(%s)$" % network_name_pattern):
+ rlib2.R_2_networks_name,
+ re.compile(r"^/2/networks/(%s)/connect$" % network_name_pattern):
+ rlib2.R_2_networks_name_connect,
+ re.compile(r"^/2/networks/(%s)/disconnect$" % network_name_pattern):
+ rlib2.R_2_networks_name_disconnect,
+
+ "/2/groups": rlib2.R_2_groups,
+ re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
+ rlib2.R_2_groups_name,
+ re.compile(r"^/2/groups/(%s)/modify$" % group_name_pattern):
+ rlib2.R_2_groups_name_modify,
+ re.compile(r"^/2/groups/(%s)/rename$" % group_name_pattern):
+ rlib2.R_2_groups_name_rename,
+ re.compile(r"^/2/groups/(%s)/assign-nodes$" % group_name_pattern):
+ rlib2.R_2_groups_name_assign_nodes,
+ re.compile(r"^/2/groups/(%s)/tags$" % group_name_pattern):
+ rlib2.R_2_groups_name_tags,
"/2/jobs": rlib2.R_2_jobs,
- re.compile(r'/2/jobs/(%s)$' % job_id_pattern):
+ re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
rlib2.R_2_jobs_id,
- re.compile(r'/2/jobs/(%s)/wait$' % job_id_pattern):
+ re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
rlib2.R_2_jobs_id_wait,
"/2/tags": rlib2.R_2_tags,
"/2/os": rlib2.R_2_os,
"/2/redistribute-config": rlib2.R_2_redist_config,
"/2/features": rlib2.R_2_features,
+ "/2/modify": rlib2.R_2_cluster_modify,
+ re.compile(r"^/2/query/(%s)$" % query_res_pattern): rlib2.R_2_query,
+ re.compile(r"^/2/query/(%s)/fields$" % query_res_pattern):
+ rlib2.R_2_query_fields,
}
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
- constants.JOB_ID_TEMPLATE))
+ _NAME_PATTERN, _NAME_PATTERN,
+ constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
+ _NAME_PATTERN))