Makefile: Fix list of directories
[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=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, network_name_pattern,
93                 job_id_pattern, disk_pattern,
94                 query_res_pattern):
95   """Returns all supported resources and their handlers.
96
97   """
98   # Important note: New resources should always be added under /2. During a
99   # discussion in July 2010 it was decided that having per-resource versions
100   # is more flexible and future-compatible than versioning the whole remote
101   # API.
102   return {
103     "/": rlib2.R_root,
104     "/2": rlib2.R_2,
105
106     "/version": rlib2.R_version,
107
108     "/2/nodes": rlib2.R_2_nodes,
109     re.compile(r"^/2/nodes/(%s)$" % node_name_pattern):
110       rlib2.R_2_nodes_name,
111     re.compile(r"^/2/nodes/(%s)/powercycle$" % node_name_pattern):
112       rlib2.R_2_nodes_name_powercycle,
113     re.compile(r"^/2/nodes/(%s)/tags$" % node_name_pattern):
114       rlib2.R_2_nodes_name_tags,
115     re.compile(r"^/2/nodes/(%s)/role$" % node_name_pattern):
116       rlib2.R_2_nodes_name_role,
117     re.compile(r"^/2/nodes/(%s)/evacuate$" % node_name_pattern):
118       rlib2.R_2_nodes_name_evacuate,
119     re.compile(r"^/2/nodes/(%s)/migrate$" % node_name_pattern):
120       rlib2.R_2_nodes_name_migrate,
121     re.compile(r"^/2/nodes/(%s)/modify$" % node_name_pattern):
122       rlib2.R_2_nodes_name_modify,
123     re.compile(r"^/2/nodes/(%s)/storage$" % node_name_pattern):
124       rlib2.R_2_nodes_name_storage,
125     re.compile(r"^/2/nodes/(%s)/storage/modify$" % node_name_pattern):
126       rlib2.R_2_nodes_name_storage_modify,
127     re.compile(r"^/2/nodes/(%s)/storage/repair$" % node_name_pattern):
128       rlib2.R_2_nodes_name_storage_repair,
129
130     "/2/instances": rlib2.R_2_instances,
131     re.compile(r"^/2/instances/(%s)$" % instance_name_pattern):
132       rlib2.R_2_instances_name,
133     re.compile(r"^/2/instances/(%s)/info$" % instance_name_pattern):
134       rlib2.R_2_instances_name_info,
135     re.compile(r"^/2/instances/(%s)/tags$" % instance_name_pattern):
136       rlib2.R_2_instances_name_tags,
137     re.compile(r"^/2/instances/(%s)/reboot$" % instance_name_pattern):
138       rlib2.R_2_instances_name_reboot,
139     re.compile(r"^/2/instances/(%s)/reinstall$" % instance_name_pattern):
140       rlib2.R_2_instances_name_reinstall,
141     re.compile(r"^/2/instances/(%s)/replace-disks$" % instance_name_pattern):
142       rlib2.R_2_instances_name_replace_disks,
143     re.compile(r"^/2/instances/(%s)/shutdown$" % instance_name_pattern):
144       rlib2.R_2_instances_name_shutdown,
145     re.compile(r"^/2/instances/(%s)/startup$" % instance_name_pattern):
146       rlib2.R_2_instances_name_startup,
147     re.compile(r"^/2/instances/(%s)/activate-disks$" % instance_name_pattern):
148       rlib2.R_2_instances_name_activate_disks,
149     re.compile(r"^/2/instances/(%s)/deactivate-disks$" % instance_name_pattern):
150       rlib2.R_2_instances_name_deactivate_disks,
151     re.compile(r"^/2/instances/(%s)/recreate-disks$" % instance_name_pattern):
152       rlib2.R_2_instances_name_recreate_disks,
153     re.compile(r"^/2/instances/(%s)/prepare-export$" % instance_name_pattern):
154       rlib2.R_2_instances_name_prepare_export,
155     re.compile(r"^/2/instances/(%s)/export$" % instance_name_pattern):
156       rlib2.R_2_instances_name_export,
157     re.compile(r"^/2/instances/(%s)/migrate$" % instance_name_pattern):
158       rlib2.R_2_instances_name_migrate,
159     re.compile(r"^/2/instances/(%s)/failover$" % instance_name_pattern):
160       rlib2.R_2_instances_name_failover,
161     re.compile(r"^/2/instances/(%s)/rename$" % instance_name_pattern):
162       rlib2.R_2_instances_name_rename,
163     re.compile(r"^/2/instances/(%s)/modify$" % instance_name_pattern):
164       rlib2.R_2_instances_name_modify,
165     re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" %
166                (instance_name_pattern, disk_pattern)):
167       rlib2.R_2_instances_name_disk_grow,
168     re.compile(r"^/2/instances/(%s)/console$" % instance_name_pattern):
169       rlib2.R_2_instances_name_console,
170
171     "/2/networks": rlib2.R_2_networks,
172     re.compile(r"^/2/networks/(%s)$" % network_name_pattern):
173       rlib2.R_2_networks_name,
174     re.compile(r"^/2/networks/(%s)/connect$" % network_name_pattern):
175       rlib2.R_2_networks_name_connect,
176     re.compile(r"^/2/networks/(%s)/disconnect$" % network_name_pattern):
177       rlib2.R_2_networks_name_disconnect,
178     re.compile(r"^/2/networks/(%s)/modify$" % network_name_pattern):
179       rlib2.R_2_networks_name_modify,
180     re.compile(r"^/2/networks/(%s)/tags$" % network_name_pattern):
181       rlib2.R_2_networks_name_tags,
182
183     "/2/groups": rlib2.R_2_groups,
184     re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
185       rlib2.R_2_groups_name,
186     re.compile(r"^/2/groups/(%s)/modify$" % group_name_pattern):
187       rlib2.R_2_groups_name_modify,
188     re.compile(r"^/2/groups/(%s)/rename$" % group_name_pattern):
189       rlib2.R_2_groups_name_rename,
190     re.compile(r"^/2/groups/(%s)/assign-nodes$" % group_name_pattern):
191       rlib2.R_2_groups_name_assign_nodes,
192     re.compile(r"^/2/groups/(%s)/tags$" % group_name_pattern):
193       rlib2.R_2_groups_name_tags,
194
195     "/2/jobs": rlib2.R_2_jobs,
196     re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
197       rlib2.R_2_jobs_id,
198     re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
199       rlib2.R_2_jobs_id_wait,
200
201     "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc,
202     "/2/tags": rlib2.R_2_tags,
203     "/2/info": rlib2.R_2_info,
204     "/2/os": rlib2.R_2_os,
205     "/2/redistribute-config": rlib2.R_2_redist_config,
206     "/2/features": rlib2.R_2_features,
207     "/2/modify": rlib2.R_2_cluster_modify,
208     re.compile(r"^/2/query/(%s)$" % query_res_pattern): rlib2.R_2_query,
209     re.compile(r"^/2/query/(%s)/fields$" % query_res_pattern):
210       rlib2.R_2_query_fields,
211     }
212
213
214 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
215                              _NAME_PATTERN, _NAME_PATTERN,
216                              constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
217                              _NAME_PATTERN))