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, filter_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 filter_uuid = UriPattern(filter_pattern)
160 query_res = UriPattern(query_res_pattern)
161
162
163
164
165
166
167
168
169
170 return {
171 "/": rlib2.R_root,
172 "/2": rlib2.R_2,
173
174 "/version": rlib2.R_version,
175
176 "/2/nodes": rlib2.R_2_nodes,
177
178 translate_fn("/2/nodes/", node_name):
179 rlib2.R_2_nodes_name,
180 translate_fn("/2/nodes/", node_name, "/powercycle"):
181 rlib2.R_2_nodes_name_powercycle,
182 translate_fn("/2/nodes/", node_name, "/tags"):
183 rlib2.R_2_nodes_name_tags,
184 translate_fn("/2/nodes/", node_name, "/role"):
185 rlib2.R_2_nodes_name_role,
186 translate_fn("/2/nodes/", node_name, "/evacuate"):
187 rlib2.R_2_nodes_name_evacuate,
188 translate_fn("/2/nodes/", node_name, "/migrate"):
189 rlib2.R_2_nodes_name_migrate,
190 translate_fn("/2/nodes/", node_name, "/modify"):
191 rlib2.R_2_nodes_name_modify,
192 translate_fn("/2/nodes/", node_name, "/storage"):
193 rlib2.R_2_nodes_name_storage,
194 translate_fn("/2/nodes/", node_name, "/storage/modify"):
195 rlib2.R_2_nodes_name_storage_modify,
196 translate_fn("/2/nodes/", node_name, "/storage/repair"):
197 rlib2.R_2_nodes_name_storage_repair,
198
199 "/2/instances": rlib2.R_2_instances,
200 translate_fn("/2/instances/", instance_name):
201 rlib2.R_2_instances_name,
202 translate_fn("/2/instances/", instance_name, "/info"):
203 rlib2.R_2_instances_name_info,
204 translate_fn("/2/instances/", instance_name, "/tags"):
205 rlib2.R_2_instances_name_tags,
206 translate_fn("/2/instances/", instance_name, "/reboot"):
207 rlib2.R_2_instances_name_reboot,
208 translate_fn("/2/instances/", instance_name, "/reinstall"):
209 rlib2.R_2_instances_name_reinstall,
210 translate_fn("/2/instances/", instance_name, "/replace-disks"):
211 rlib2.R_2_instances_name_replace_disks,
212 translate_fn("/2/instances/", instance_name, "/shutdown"):
213 rlib2.R_2_instances_name_shutdown,
214 translate_fn("/2/instances/", instance_name, "/startup"):
215 rlib2.R_2_instances_name_startup,
216 translate_fn("/2/instances/", instance_name, "/activate-disks"):
217 rlib2.R_2_instances_name_activate_disks,
218 translate_fn("/2/instances/", instance_name, "/deactivate-disks"):
219 rlib2.R_2_instances_name_deactivate_disks,
220 translate_fn("/2/instances/", instance_name, "/recreate-disks"):
221 rlib2.R_2_instances_name_recreate_disks,
222 translate_fn("/2/instances/", instance_name, "/prepare-export"):
223 rlib2.R_2_instances_name_prepare_export,
224 translate_fn("/2/instances/", instance_name, "/export"):
225 rlib2.R_2_instances_name_export,
226 translate_fn("/2/instances/", instance_name, "/migrate"):
227 rlib2.R_2_instances_name_migrate,
228 translate_fn("/2/instances/", instance_name, "/failover"):
229 rlib2.R_2_instances_name_failover,
230 translate_fn("/2/instances/", instance_name, "/rename"):
231 rlib2.R_2_instances_name_rename,
232 translate_fn("/2/instances/", instance_name, "/modify"):
233 rlib2.R_2_instances_name_modify,
234 translate_fn("/2/instances/", instance_name, "/disk/", disk, "/grow"):
235 rlib2.R_2_instances_name_disk_grow,
236 translate_fn("/2/instances/", instance_name, "/console"):
237 rlib2.R_2_instances_name_console,
238
239 "/2/networks": rlib2.R_2_networks,
240 translate_fn("/2/networks/", network_name):
241 rlib2.R_2_networks_name,
242 translate_fn("/2/networks/", network_name, "/connect"):
243 rlib2.R_2_networks_name_connect,
244 translate_fn("/2/networks/", network_name, "/disconnect"):
245 rlib2.R_2_networks_name_disconnect,
246 translate_fn("/2/networks/", network_name, "/modify"):
247 rlib2.R_2_networks_name_modify,
248 translate_fn("/2/networks/", network_name, "/tags"):
249 rlib2.R_2_networks_name_tags,
250
251 "/2/groups": rlib2.R_2_groups,
252 translate_fn("/2/groups/", group_name):
253 rlib2.R_2_groups_name,
254 translate_fn("/2/groups/", group_name, "/modify"):
255 rlib2.R_2_groups_name_modify,
256 translate_fn("/2/groups/", group_name, "/rename"):
257 rlib2.R_2_groups_name_rename,
258 translate_fn("/2/groups/", group_name, "/assign-nodes"):
259 rlib2.R_2_groups_name_assign_nodes,
260 translate_fn("/2/groups/", group_name, "/tags"):
261 rlib2.R_2_groups_name_tags,
262
263 "/2/jobs": rlib2.R_2_jobs,
264 translate_fn("/2/jobs/", job_id):
265 rlib2.R_2_jobs_id,
266 translate_fn("/2/jobs/", job_id, "/wait"):
267 rlib2.R_2_jobs_id_wait,
268
269 "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc,
270 "/2/tags": rlib2.R_2_tags,
271 "/2/info": rlib2.R_2_info,
272 "/2/os": rlib2.R_2_os,
273 "/2/redistribute-config": rlib2.R_2_redist_config,
274 "/2/features": rlib2.R_2_features,
275 "/2/modify": rlib2.R_2_cluster_modify,
276
277 translate_fn("/2/query/", query_res):
278 rlib2.R_2_query,
279 translate_fn("/2/query/", query_res, "/fields"):
280 rlib2.R_2_query_fields,
281
282 "/2/filters": rlib2.R_2_filters,
283 translate_fn("/2/filters/", filter_uuid):
284 rlib2.R_2_filters_uuid,
285 }
286
287
288 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
289 _NAME_PATTERN, _NAME_PATTERN,
290 constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
291 _NAME_PATTERN, _NAME_PATTERN))
292