1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 """Remote API connection map.
31
32 """
33
34
35
36
37
38 import re
39 import urlparse
40
41 from ganeti import constants
42 from ganeti import http
43 from ganeti import utils
44
45 from ganeti.rapi import rlib2
46
47
48 _NAME_PATTERN = r"[\w\._-]+"
49 _DISK_PATTERN = r"\d+"
50
51
52 CONNECTOR = {}
53
54
56 """Map resource to method.
57
58 """
60 """Resource mapper constructor.
61
62 @param connector: a dictionary, mapping method name with URL path regexp
63
64 """
65 if connector is None:
66 connector = CONNECTOR
67 self._connector = connector
68
70 """Find method for a given URI.
71
72 @param uri: string with URI
73
74 @return: None if no method is found or a tuple containing
75 the following fields:
76 - method: name of method mapped to URI
77 - items: a list of variable intems in the path
78 - args: a dictionary with additional parameters from URL
79
80 """
81 if "?" in uri:
82 (path, query) = uri.split("?", 1)
83 args = urlparse.parse_qs(query)
84 else:
85 path = uri
86 query = None
87 args = {}
88
89
90 result = utils.FindMatch(self._connector, path)
91
92 if result is None:
93 raise http.HttpNotFound()
94
95 (handler, groups) = result
96
97 return (handler, groups, args)
98
99
101 """Converts URI pattern into a regular expression group.
102
103 Used by L{_CompileHandlerPath}.
104
105 """
106 if isinstance(value, UriPattern):
107 return "(%s)" % value.content
108 else:
109 return value
110
111
113 """Compiles path for RAPI resource into regular expression.
114
115 @return: Compiled regular expression object
116
117 """
118 return re.compile("^%s$" % "".join(map(_ConvertPattern, args)))
119
120
122 __slots__ = [
123 "content",
124 ]
125
127 self.content = content
128
129
130 -def GetHandlers(node_name_pattern, instance_name_pattern,
131 group_name_pattern, network_name_pattern,
132 job_id_pattern, disk_pattern,
133 query_res_pattern,
134 translate=None):
135 """Returns all supported resources and their handlers.
136
137 C{node_name_pattern} and the other C{*_pattern} parameters are wrapped in
138 L{UriPattern} and, if used in a URI, passed to the function specified using
139 C{translate}. C{translate} receives 1..N parameters which are either plain
140 strings or instances of L{UriPattern} and returns a dictionary key suitable
141 for the caller of C{GetHandlers}. The default implementation in
142 L{_CompileHandlerPath} returns a compiled regular expression in which each
143 pattern is a group.
144
145 @rtype: dict
146
147 """
148 if translate is None:
149 translate_fn = _CompileHandlerPath
150 else:
151 translate_fn = translate
152
153 node_name = UriPattern(node_name_pattern)
154 instance_name = UriPattern(instance_name_pattern)
155 group_name = UriPattern(group_name_pattern)
156 network_name = UriPattern(network_name_pattern)
157 job_id = UriPattern(job_id_pattern)
158 disk = UriPattern(disk_pattern)
159 query_res = UriPattern(query_res_pattern)
160
161
162
163
164
165
166
167
168
169 return {
170 "/": rlib2.R_root,
171 "/2": rlib2.R_2,
172
173 "/version": rlib2.R_version,
174
175 "/2/nodes": rlib2.R_2_nodes,
176
177 translate_fn("/2/nodes/", node_name):
178 rlib2.R_2_nodes_name,
179 translate_fn("/2/nodes/", node_name, "/powercycle"):
180 rlib2.R_2_nodes_name_powercycle,
181 translate_fn("/2/nodes/", node_name, "/tags"):
182 rlib2.R_2_nodes_name_tags,
183 translate_fn("/2/nodes/", node_name, "/role"):
184 rlib2.R_2_nodes_name_role,
185 translate_fn("/2/nodes/", node_name, "/evacuate"):
186 rlib2.R_2_nodes_name_evacuate,
187 translate_fn("/2/nodes/", node_name, "/migrate"):
188 rlib2.R_2_nodes_name_migrate,
189 translate_fn("/2/nodes/", node_name, "/modify"):
190 rlib2.R_2_nodes_name_modify,
191 translate_fn("/2/nodes/", node_name, "/storage"):
192 rlib2.R_2_nodes_name_storage,
193 translate_fn("/2/nodes/", node_name, "/storage/modify"):
194 rlib2.R_2_nodes_name_storage_modify,
195 translate_fn("/2/nodes/", node_name, "/storage/repair"):
196 rlib2.R_2_nodes_name_storage_repair,
197
198 "/2/instances": rlib2.R_2_instances,
199 translate_fn("/2/instances/", instance_name):
200 rlib2.R_2_instances_name,
201 translate_fn("/2/instances/", instance_name, "/info"):
202 rlib2.R_2_instances_name_info,
203 translate_fn("/2/instances/", instance_name, "/tags"):
204 rlib2.R_2_instances_name_tags,
205 translate_fn("/2/instances/", instance_name, "/reboot"):
206 rlib2.R_2_instances_name_reboot,
207 translate_fn("/2/instances/", instance_name, "/reinstall"):
208 rlib2.R_2_instances_name_reinstall,
209 translate_fn("/2/instances/", instance_name, "/replace-disks"):
210 rlib2.R_2_instances_name_replace_disks,
211 translate_fn("/2/instances/", instance_name, "/shutdown"):
212 rlib2.R_2_instances_name_shutdown,
213 translate_fn("/2/instances/", instance_name, "/startup"):
214 rlib2.R_2_instances_name_startup,
215 translate_fn("/2/instances/", instance_name, "/activate-disks"):
216 rlib2.R_2_instances_name_activate_disks,
217 translate_fn("/2/instances/", instance_name, "/deactivate-disks"):
218 rlib2.R_2_instances_name_deactivate_disks,
219 translate_fn("/2/instances/", instance_name, "/recreate-disks"):
220 rlib2.R_2_instances_name_recreate_disks,
221 translate_fn("/2/instances/", instance_name, "/prepare-export"):
222 rlib2.R_2_instances_name_prepare_export,
223 translate_fn("/2/instances/", instance_name, "/export"):
224 rlib2.R_2_instances_name_export,
225 translate_fn("/2/instances/", instance_name, "/migrate"):
226 rlib2.R_2_instances_name_migrate,
227 translate_fn("/2/instances/", instance_name, "/failover"):
228 rlib2.R_2_instances_name_failover,
229 translate_fn("/2/instances/", instance_name, "/rename"):
230 rlib2.R_2_instances_name_rename,
231 translate_fn("/2/instances/", instance_name, "/modify"):
232 rlib2.R_2_instances_name_modify,
233 translate_fn("/2/instances/", instance_name, "/disk/", disk, "/grow"):
234 rlib2.R_2_instances_name_disk_grow,
235 translate_fn("/2/instances/", instance_name, "/console"):
236 rlib2.R_2_instances_name_console,
237
238 "/2/networks": rlib2.R_2_networks,
239 translate_fn("/2/networks/", network_name):
240 rlib2.R_2_networks_name,
241 translate_fn("/2/networks/", network_name, "/connect"):
242 rlib2.R_2_networks_name_connect,
243 translate_fn("/2/networks/", network_name, "/disconnect"):
244 rlib2.R_2_networks_name_disconnect,
245 translate_fn("/2/networks/", network_name, "/modify"):
246 rlib2.R_2_networks_name_modify,
247 translate_fn("/2/networks/", network_name, "/tags"):
248 rlib2.R_2_networks_name_tags,
249
250 "/2/groups": rlib2.R_2_groups,
251 translate_fn("/2/groups/", group_name):
252 rlib2.R_2_groups_name,
253 translate_fn("/2/groups/", group_name, "/modify"):
254 rlib2.R_2_groups_name_modify,
255 translate_fn("/2/groups/", group_name, "/rename"):
256 rlib2.R_2_groups_name_rename,
257 translate_fn("/2/groups/", group_name, "/assign-nodes"):
258 rlib2.R_2_groups_name_assign_nodes,
259 translate_fn("/2/groups/", group_name, "/tags"):
260 rlib2.R_2_groups_name_tags,
261
262 "/2/jobs": rlib2.R_2_jobs,
263 translate_fn("/2/jobs/", job_id):
264 rlib2.R_2_jobs_id,
265 translate_fn("/2/jobs/", job_id, "/wait"):
266 rlib2.R_2_jobs_id_wait,
267
268 "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc,
269 "/2/tags": rlib2.R_2_tags,
270 "/2/info": rlib2.R_2_info,
271 "/2/os": rlib2.R_2_os,
272 "/2/redistribute-config": rlib2.R_2_redist_config,
273 "/2/features": rlib2.R_2_features,
274 "/2/modify": rlib2.R_2_cluster_modify,
275
276 translate_fn("/2/query/", query_res):
277 rlib2.R_2_query,
278 translate_fn("/2/query/", query_res, "/fields"):
279 rlib2.R_2_query_fields,
280 }
281
282
283 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
284 _NAME_PATTERN, _NAME_PATTERN,
285 constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
286 _NAME_PATTERN))
287