X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/bf968b7ffc2fd7aea5400814648a58275d7c5dec..b459a848dc62e314e61e8ae14edd3ff6cc2b2822:/lib/rapi/connector.py diff --git a/lib/rapi/connector.py b/lib/rapi/connector.py index eeae01e..499e2e6 100644 --- a/lib/rapi/connector.py +++ b/lib/rapi/connector.py @@ -22,17 +22,23 @@ """ +# pylint: disable=C0103 + +# C0103: Invalid name, since the R_* names are not conforming + import cgi import re 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 = {} @@ -42,12 +48,14 @@ class Mapper: """Map resource to method. """ - def __init__(self, connector=CONNECTOR): + def __init__(self, connector=None): """Resource mapper constructor. @param connector: a dictionary, mapping method name with URL path regexp """ + if connector is None: + connector = CONNECTOR self._connector = connector def getController(self, uri): @@ -62,59 +70,50 @@ class Mapper: - 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 + if result is None: + raise http.HttpNotFound() - # String objects - elif key == path: - result = (handler, [], args) - break + (handler, groups) = result - if result: - return result - else: - raise http.HttpNotFound() + return (handler, groups, args) class R_root(baserlib.R_Generic): """/ resource. """ - def GET(self): + _ROOT_PATTERN = re.compile("^R_([a-zA-Z0-9]+)$") + + @classmethod + def GET(cls): """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__) + m = cls._ROOT_PATTERN.match(handler.__name__) if m: name = m.group(1) - if name != 'root': + if name != "root": rootlist.append(name) return baserlib.BuildUriList(rootlist, "/%s") -def _getResources(id): +def _getResources(id_): """Return a list of resources underneath given id. This is to generalize querying of version resources lists. @@ -122,7 +121,7 @@ def _getResources(id): @return: a list of resources names. """ - r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id) + r_pattern = re.compile("^R_%s_([a-zA-Z0-9]+)$" % id_) rlist = [] for handler in CONNECTOR.values(): @@ -135,10 +134,13 @@ def _getResources(id): class R_2(baserlib.R_Generic): - """ /2 resource, the root of the version 2 API. + """/2 resource. + + This is the root of the version 2 API. """ - def GET(self): + @staticmethod + def GET(): """Show the list of mapped resources. @return: a dictionary with 'name' and 'uri' keys for each of them. @@ -147,10 +149,16 @@ class R_2(baserlib.R_Generic): 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, 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, @@ -159,50 +167,92 @@ def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern): "/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)/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)/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): + rlib2.R_2_instances_name_activate_disks, + re.compile(r"^/2/instances/(%s)/deactivate-disks$" % instance_name_pattern): + rlib2.R_2_instances_name_deactivate_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/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): + rlib2.R_2_jobs_id_wait, "/2/tags": rlib2.R_2_tags, "/2/info": rlib2.R_2_info, "/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)) +CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, _NAME_PATTERN, + constants.JOB_ID_TEMPLATE, _DISK_PATTERN, + _NAME_PATTERN))