baserlib: Rename R_Generic to ResourceBase
[ganeti-local] / lib / rapi / connector.py
1 #
2 #
3
4 # Copyright (C) 2006, 2007, 2008 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21 """Remote API connection map.
22
23 """
24
25 # pylint: disable-msg=C0103
26
27 # C0103: Invalid name, since the R_* names are not conforming
28
29 import cgi
30 import re
31
32 from ganeti import constants
33 from ganeti import http
34 from ganeti import utils
35
36 from ganeti.rapi import rlib2
37
38
39 _NAME_PATTERN = r"[\w\._-]+"
40 _DISK_PATTERN = r"\d+"
41
42 # the connection map is created at the end of this file
43 CONNECTOR = {}
44
45
46 class Mapper:
47   """Map resource to method.
48
49   """
50   def __init__(self, connector=None):
51     """Resource mapper constructor.
52
53     @param connector: a dictionary, mapping method name with URL path regexp
54
55     """
56     if connector is None:
57       connector = CONNECTOR
58     self._connector = connector
59
60   def getController(self, uri):
61     """Find method for a given URI.
62
63     @param uri: string with URI
64
65     @return: None if no method is found or a tuple containing
66         the following fields:
67             - method: name of method mapped to URI
68             - items: a list of variable intems in the path
69             - args: a dictionary with additional parameters from URL
70
71     """
72     if "?" in uri:
73       (path, query) = uri.split("?", 1)
74       args = cgi.parse_qs(query)
75     else:
76       path = uri
77       query = None
78       args = {}
79
80     # Try to find handler for request path
81     result = utils.FindMatch(self._connector, path)
82
83     if result is None:
84       raise http.HttpNotFound()
85
86     (handler, groups) = result
87
88     return (handler, groups, args)
89
90
91 def GetHandlers(node_name_pattern, instance_name_pattern,
92                 group_name_pattern, job_id_pattern, disk_pattern,
93                 query_res_pattern):
94   """Returns all supported resources and their handlers.
95
96   """
97   # Important note: New resources should always be added under /2. During a
98   # discussion in July 2010 it was decided that having per-resource versions
99   # is more flexible and future-compatible than versioning the whole remote
100   # API.
101   return {
102     "/": rlib2.R_root,
103
104     "/version": rlib2.R_version,
105
106     "/2/nodes": rlib2.R_2_nodes,
107     re.compile(r"^/2/nodes/(%s)$" % node_name_pattern):
108       rlib2.R_2_nodes_name,
109     re.compile(r"^/2/nodes/(%s)/tags$" % node_name_pattern):
110       rlib2.R_2_nodes_name_tags,
111     re.compile(r"^/2/nodes/(%s)/role$" % node_name_pattern):
112       rlib2.R_2_nodes_name_role,
113     re.compile(r"^/2/nodes/(%s)/evacuate$" % node_name_pattern):
114       rlib2.R_2_nodes_name_evacuate,
115     re.compile(r"^/2/nodes/(%s)/migrate$" % node_name_pattern):
116       rlib2.R_2_nodes_name_migrate,
117     re.compile(r"^/2/nodes/(%s)/storage$" % node_name_pattern):
118       rlib2.R_2_nodes_name_storage,
119     re.compile(r"^/2/nodes/(%s)/storage/modify$" % node_name_pattern):
120       rlib2.R_2_nodes_name_storage_modify,
121     re.compile(r"^/2/nodes/(%s)/storage/repair$" % node_name_pattern):
122       rlib2.R_2_nodes_name_storage_repair,
123
124     "/2/instances": rlib2.R_2_instances,
125     re.compile(r"^/2/instances/(%s)$" % instance_name_pattern):
126       rlib2.R_2_instances_name,
127     re.compile(r"^/2/instances/(%s)/info$" % instance_name_pattern):
128       rlib2.R_2_instances_name_info,
129     re.compile(r"^/2/instances/(%s)/tags$" % instance_name_pattern):
130       rlib2.R_2_instances_name_tags,
131     re.compile(r"^/2/instances/(%s)/reboot$" % instance_name_pattern):
132       rlib2.R_2_instances_name_reboot,
133     re.compile(r"^/2/instances/(%s)/reinstall$" % instance_name_pattern):
134       rlib2.R_2_instances_name_reinstall,
135     re.compile(r"^/2/instances/(%s)/replace-disks$" % instance_name_pattern):
136       rlib2.R_2_instances_name_replace_disks,
137     re.compile(r"^/2/instances/(%s)/shutdown$" % instance_name_pattern):
138       rlib2.R_2_instances_name_shutdown,
139     re.compile(r"^/2/instances/(%s)/startup$" % instance_name_pattern):
140       rlib2.R_2_instances_name_startup,
141     re.compile(r"^/2/instances/(%s)/activate-disks$" % instance_name_pattern):
142       rlib2.R_2_instances_name_activate_disks,
143     re.compile(r"^/2/instances/(%s)/deactivate-disks$" % instance_name_pattern):
144       rlib2.R_2_instances_name_deactivate_disks,
145     re.compile(r"^/2/instances/(%s)/prepare-export$" % instance_name_pattern):
146       rlib2.R_2_instances_name_prepare_export,
147     re.compile(r"^/2/instances/(%s)/export$" % instance_name_pattern):
148       rlib2.R_2_instances_name_export,
149     re.compile(r"^/2/instances/(%s)/migrate$" % instance_name_pattern):
150       rlib2.R_2_instances_name_migrate,
151     re.compile(r"^/2/instances/(%s)/failover$" % instance_name_pattern):
152       rlib2.R_2_instances_name_failover,
153     re.compile(r"^/2/instances/(%s)/rename$" % instance_name_pattern):
154       rlib2.R_2_instances_name_rename,
155     re.compile(r"^/2/instances/(%s)/modify$" % instance_name_pattern):
156       rlib2.R_2_instances_name_modify,
157     re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" %
158                (instance_name_pattern, disk_pattern)):
159       rlib2.R_2_instances_name_disk_grow,
160     re.compile(r"^/2/instances/(%s)/console$" % instance_name_pattern):
161       rlib2.R_2_instances_name_console,
162
163     "/2/groups": rlib2.R_2_groups,
164     re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
165       rlib2.R_2_groups_name,
166     re.compile(r"^/2/groups/(%s)/modify$" % group_name_pattern):
167       rlib2.R_2_groups_name_modify,
168     re.compile(r"^/2/groups/(%s)/rename$" % group_name_pattern):
169       rlib2.R_2_groups_name_rename,
170     re.compile(r"^/2/groups/(%s)/assign-nodes$" % group_name_pattern):
171       rlib2.R_2_groups_name_assign_nodes,
172     re.compile(r"^/2/groups/(%s)/tags$" % group_name_pattern):
173       rlib2.R_2_groups_name_tags,
174
175     "/2/jobs": rlib2.R_2_jobs,
176     re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
177       rlib2.R_2_jobs_id,
178     re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
179       rlib2.R_2_jobs_id_wait,
180
181     "/2/tags": rlib2.R_2_tags,
182     "/2/info": rlib2.R_2_info,
183     "/2/os": rlib2.R_2_os,
184     "/2/redistribute-config": rlib2.R_2_redist_config,
185     "/2/features": rlib2.R_2_features,
186     "/2/modify": rlib2.R_2_cluster_modify,
187     re.compile(r"^/2/query/(%s)$" % query_res_pattern): rlib2.R_2_query,
188     re.compile(r"^/2/query/(%s)/fields$" % query_res_pattern):
189       rlib2.R_2_query_fields,
190     }
191
192
193 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, _NAME_PATTERN,
194                              constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
195                              _NAME_PATTERN))