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 cgi
30 import re
31
32 from ganeti import constants
33 from ganeti import http
34
35 from ganeti.rapi import baserlib
36 from ganeti.rapi import rlib2
37
38
39 CONNECTOR = {}
40
41
43 """Map resource to method.
44
45 """
47 """Resource mapper constructor.
48
49 @param connector: a dictionary, mapping method name with URL path regexp
50
51 """
52 self._connector = connector
53
55 """Find method for a given URI.
56
57 @param uri: string with URI
58
59 @return: None if no method is found or a tuple containing
60 the following fields:
61 - method: name of method mapped to URI
62 - items: a list of variable intems in the path
63 - args: a dictionary with additional parameters from URL
64
65 """
66 if '?' in uri:
67 (path, query) = uri.split('?', 1)
68 args = cgi.parse_qs(query)
69 else:
70 path = uri
71 query = None
72 args = {}
73
74 result = None
75
76 for key, handler in self._connector.iteritems():
77
78 if hasattr(key, "match"):
79 m = key.match(path)
80 if m:
81 result = (handler, list(m.groups()), args)
82 break
83
84
85 elif key == path:
86 result = (handler, [], args)
87 break
88
89 if result:
90 return result
91 else:
92 raise http.HttpNotFound()
93
94
95 -class R_root(baserlib.R_Generic):
96 """/ resource.
97
98 """
99 DOC_URI = "/"
100
102 """Show the list of mapped resources.
103
104 @return: a dictionary with 'name' and 'uri' keys for each of them.
105
106 """
107 root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
108
109 rootlist = []
110 for handler in CONNECTOR.values():
111 m = root_pattern.match(handler.__name__)
112 if m:
113 name = m.group(1)
114 if name != 'root':
115 rootlist.append(name)
116
117 return baserlib.BuildUriList(rootlist, "/%s")
118
119
121 """Return a list of resources underneath given id.
122
123 This is to generalize querying of version resources lists.
124
125 @return: a list of resources names.
126
127 """
128 r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id)
129
130 rlist = []
131 for handler in CONNECTOR.values():
132 m = r_pattern.match(handler.__name__)
133 if m:
134 name = m.group(1)
135 rlist.append(name)
136
137 return rlist
138
139
140 -class R_2(baserlib.R_Generic):
141 """ /2 resource, the root of the version 2 API.
142
143 """
144 DOC_URI = "/2"
145
147 """Show the list of mapped resources.
148
149 @return: a dictionary with 'name' and 'uri' keys for each of them.
150
151 """
152 return baserlib.BuildUriList(_getResources("2"), "/2/%s")
153
154
155 CONNECTOR.update({
156 "/": R_root,
157
158 "/version": rlib2.R_version,
159
160 "/2": R_2,
161 "/2/jobs": rlib2.R_2_jobs,
162 "/2/nodes": rlib2.R_2_nodes,
163 re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name,
164 re.compile(r'^/2/nodes/([\w\._-]+)/tags$'): rlib2.R_2_nodes_name_tags,
165 "/2/instances": rlib2.R_2_instances,
166 re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name,
167 re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags,
168 re.compile(r'^/2/instances/([\w\._-]+)/reboot$'):
169 rlib2.R_2_instances_name_reboot,
170 re.compile(r'^/2/instances/([\w\._-]+)/reinstall$'):
171 rlib2.R_2_instances_name_reinstall,
172 re.compile(r'^/2/instances/([\w\._-]+)/shutdown$'):
173 rlib2.R_2_instances_name_shutdown,
174 re.compile(r'^/2/instances/([\w\._-]+)/startup$'):
175 rlib2.R_2_instances_name_startup,
176 re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): rlib2.R_2_jobs_id,
177 "/2/tags": rlib2.R_2_tags,
178 "/2/info": rlib2.R_2_info,
179 "/2/os": rlib2.R_2_os,
180 })
181