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