Revision 4e5a68f8
b/Makefile.am | ||
---|---|---|
97 | 97 |
lib/rapi/__init__.py \ |
98 | 98 |
lib/rapi/baserlib.py \ |
99 | 99 |
lib/rapi/connector.py \ |
100 |
lib/rapi/rlib1.py \ |
|
101 | 100 |
lib/rapi/rlib2.py |
102 | 101 |
|
103 | 102 |
http_PYTHON = \ |
b/doc/build-rapi-resources-doc | ||
---|---|---|
26 | 26 |
import cgi |
27 | 27 |
import inspect |
28 | 28 |
|
29 |
from ganeti.rapi import rlib1 |
|
30 | 29 |
from ganeti.rapi import rlib2 |
31 | 30 |
from ganeti.rapi import connector |
32 | 31 |
|
... | ... | |
38 | 37 |
# Get list of all resources |
39 | 38 |
all = list(connector.CONNECTOR.itervalues()) |
40 | 39 |
|
41 |
# Sort rlib1 by URI
|
|
40 |
# Sort rlib by URI |
|
42 | 41 |
all.sort(cmp=lambda a, b: cmp(a.DOC_URI, b.DOC_URI)) |
43 | 42 |
|
44 | 43 |
print "<!-- Automatically generated, do not edit -->" |
b/lib/rapi/connector.py | ||
---|---|---|
29 | 29 |
from ganeti import http |
30 | 30 |
|
31 | 31 |
from ganeti.rapi import baserlib |
32 |
from ganeti.rapi import rlib1 |
|
33 | 32 |
from ganeti.rapi import rlib2 |
34 | 33 |
|
35 | 34 |
# the connection map is created at the end of this file |
... | ... | |
152 | 151 |
CONNECTOR.update({ |
153 | 152 |
"/": R_root, |
154 | 153 |
|
155 |
"/version": rlib1.R_version,
|
|
154 |
"/version": rlib2.R_version,
|
|
156 | 155 |
|
157 | 156 |
"/2": R_2, |
158 | 157 |
"/2/jobs": rlib2.R_2_jobs, |
159 | 158 |
"/2/nodes": rlib2.R_2_nodes, |
159 |
re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name, |
|
160 | 160 |
"/2/instances": rlib2.R_2_instances, |
161 |
re.compile(r'^/2/instances/([\w\._-]+)$'): rlib1.R_instances_name,
|
|
161 |
re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name,
|
|
162 | 162 |
re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags, |
163 | 163 |
re.compile(r'^/2/instances/([\w\._-]+)/reboot$'): |
164 | 164 |
rlib2.R_2_instances_name_reboot, |
... | ... | |
167 | 167 |
re.compile(r'^/2/instances/([\w\._-]+)/startup$'): |
168 | 168 |
rlib2.R_2_instances_name_startup, |
169 | 169 |
re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): rlib2.R_2_jobs_id, |
170 |
"/2/tags": rlib2.R_2_tags, |
|
171 |
"/2/info": rlib2.R_2_info, |
|
172 |
"/2/os": rlib2.R_2_os, |
|
170 | 173 |
}) |
/dev/null | ||
---|---|---|
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 |
|
|
22 |
"""Remote API version 1 resources library. |
|
23 |
|
|
24 |
""" |
|
25 |
|
|
26 |
import ganeti.cli |
|
27 |
import ganeti.errors |
|
28 |
import ganeti.opcodes |
|
29 |
|
|
30 |
from ganeti import constants |
|
31 |
from ganeti import http |
|
32 |
|
|
33 |
from ganeti.rapi import baserlib |
|
34 |
|
|
35 |
|
|
36 |
I_FIELDS = ["name", "os", "pnode", "snodes", "admin_state", "disk_template", |
|
37 |
"ip", "mac", "bridge", "sda_size", "sdb_size", "beparams", |
|
38 |
"oper_state", "status", "tags"] |
|
39 |
|
|
40 |
N_FIELDS = ["name", "dtotal", "dfree", |
|
41 |
"mtotal", "mnode", "mfree", |
|
42 |
"pinst_cnt", "sinst_cnt", "tags"] |
|
43 |
|
|
44 |
|
|
45 |
class R_version(baserlib.R_Generic): |
|
46 |
"""/version resource. |
|
47 |
|
|
48 |
This resource should be used to determine the remote API version and |
|
49 |
to adapt clients accordingly. |
|
50 |
|
|
51 |
""" |
|
52 |
DOC_URI = "/version" |
|
53 |
|
|
54 |
def GET(self): |
|
55 |
"""Returns the remote API version. |
|
56 |
|
|
57 |
""" |
|
58 |
return constants.RAPI_VERSION |
|
59 |
|
|
60 |
|
|
61 |
class R_tags(baserlib.R_Generic): |
|
62 |
"""/tags resource. |
|
63 |
|
|
64 |
Manages cluster tags. |
|
65 |
|
|
66 |
""" |
|
67 |
DOC_URI = "/tags" |
|
68 |
|
|
69 |
def GET(self): |
|
70 |
"""Returns a list of all cluster tags. |
|
71 |
|
|
72 |
Example: ["tag1", "tag2", "tag3"] |
|
73 |
|
|
74 |
""" |
|
75 |
return baserlib._Tags_GET(constants.TAG_CLUSTER) |
|
76 |
|
|
77 |
|
|
78 |
class R_info(baserlib.R_Generic): |
|
79 |
"""Cluster info. |
|
80 |
|
|
81 |
""" |
|
82 |
DOC_URI = "/info" |
|
83 |
|
|
84 |
def GET(self): |
|
85 |
"""Returns cluster information. |
|
86 |
|
|
87 |
Example:: |
|
88 |
|
|
89 |
{ |
|
90 |
"config_version": 3, |
|
91 |
"name": "cluster1.example.com", |
|
92 |
"software_version": "1.2.4", |
|
93 |
"os_api_version": 5, |
|
94 |
"export_version": 0, |
|
95 |
"master": "node1.example.com", |
|
96 |
"architecture": [ |
|
97 |
"64bit", |
|
98 |
"x86_64" |
|
99 |
], |
|
100 |
"hypervisor_type": "xen-pvm", |
|
101 |
"protocol_version": 12 |
|
102 |
} |
|
103 |
|
|
104 |
""" |
|
105 |
op = ganeti.opcodes.OpQueryClusterInfo() |
|
106 |
return ganeti.cli.SubmitOpCode(op) |
|
107 |
|
|
108 |
|
|
109 |
class R_nodes_name(baserlib.R_Generic): |
|
110 |
"""/nodes/[node_name] resources. |
|
111 |
|
|
112 |
""" |
|
113 |
DOC_URI = "/nodes/[node_name]" |
|
114 |
|
|
115 |
def GET(self): |
|
116 |
"""Send information about a node. |
|
117 |
|
|
118 |
""" |
|
119 |
node_name = self.items[0] |
|
120 |
op = ganeti.opcodes.OpQueryNodes(output_fields=N_FIELDS, |
|
121 |
names=[node_name]) |
|
122 |
result = ganeti.cli.SubmitOpCode(op) |
|
123 |
|
|
124 |
return baserlib.MapFields(N_FIELDS, result[0]) |
|
125 |
|
|
126 |
|
|
127 |
class R_nodes_name_tags(baserlib.R_Generic): |
|
128 |
"""/nodes/[node_name]/tags resource. |
|
129 |
|
|
130 |
Manages per-node tags. |
|
131 |
|
|
132 |
""" |
|
133 |
DOC_URI = "/nodes/[node_name]/tags" |
|
134 |
|
|
135 |
def GET(self): |
|
136 |
"""Returns a list of node tags. |
|
137 |
|
|
138 |
Example: ["tag1", "tag2", "tag3"] |
|
139 |
|
|
140 |
""" |
|
141 |
return baserlib._Tags_GET(constants.TAG_NODE, name=self.items[0]) |
|
142 |
|
|
143 |
|
|
144 |
class R_instances_name(baserlib.R_Generic): |
|
145 |
"""/instances/[instance_name] resources. |
|
146 |
|
|
147 |
""" |
|
148 |
DOC_URI = "/instances/[instance_name]" |
|
149 |
|
|
150 |
def GET(self): |
|
151 |
"""Send information about an instance. |
|
152 |
|
|
153 |
""" |
|
154 |
instance_name = self.items[0] |
|
155 |
op = ganeti.opcodes.OpQueryInstances(output_fields=I_FIELDS, |
|
156 |
names=[instance_name]) |
|
157 |
result = ganeti.cli.SubmitOpCode(op) |
|
158 |
|
|
159 |
return baserlib.MapFields(I_FIELDS, result[0]) |
|
160 |
|
|
161 |
def DELETE(self): |
|
162 |
"""Removes an instance. |
|
163 |
|
|
164 |
""" |
|
165 |
instance_name = self.items[0] |
|
166 |
op = ganeti.opcodes.OpRemoveInstance(instance_name=instance_name, |
|
167 |
ignore_failures=True) |
|
168 |
job_id = ganeti.cli.SendJob([op]) |
|
169 |
|
|
170 |
return job_id |
|
171 |
|
|
172 |
def PUT(self): |
|
173 |
"""Modify an instance. |
|
174 |
|
|
175 |
""" |
|
176 |
instance_name = self.items[0] |
|
177 |
opts = {} |
|
178 |
|
|
179 |
for key in self.queryargs: |
|
180 |
opts[key] = self.queryargs[key][0] |
|
181 |
|
|
182 |
beparams = baserlib.MakeParamsDict(opts, constants.BES_PARAMETERS) |
|
183 |
hvparams = baserlib.MakeParamsDict(opts, constants.HVS_PARAMETERS) |
|
184 |
|
|
185 |
op = ganeti.opcodes.OpSetInstanceParams( |
|
186 |
instance_name=instance_name, |
|
187 |
ip=opts.get('ip', None), |
|
188 |
bridge=opts.get('bridge', None), |
|
189 |
mac=opts.get('mac', None), |
|
190 |
hvparams=hvparams, |
|
191 |
beparams=beparams, |
|
192 |
force=opts.get('force', None)) |
|
193 |
|
|
194 |
job_id = ganeti.cli.SendJob([op]) |
|
195 |
|
|
196 |
return job_id |
|
197 |
|
|
198 |
|
|
199 |
class R_instances_name_tags(baserlib.R_Generic): |
|
200 |
"""/instances/[instance_name]/tags resource. |
|
201 |
|
|
202 |
Manages per-instance tags. |
|
203 |
|
|
204 |
""" |
|
205 |
DOC_URI = "/instances/[instance_name]/tags" |
|
206 |
|
|
207 |
def GET(self): |
|
208 |
"""Returns a list of instance tags. |
|
209 |
|
|
210 |
Example: ["tag1", "tag2", "tag3"] |
|
211 |
|
|
212 |
""" |
|
213 |
return baserlib._Tags_GET(constants.TAG_INSTANCE, name=self.items[0]) |
|
214 |
|
|
215 |
|
|
216 |
class R_os(baserlib.R_Generic): |
|
217 |
"""/os resource. |
|
218 |
|
|
219 |
""" |
|
220 |
DOC_URI = "/os" |
|
221 |
|
|
222 |
def GET(self): |
|
223 |
"""Return a list of all OSes. |
|
224 |
|
|
225 |
Can return error 500 in case of a problem. |
|
226 |
|
|
227 |
Example: ["debian-etch"] |
|
228 |
|
|
229 |
""" |
|
230 |
op = ganeti.opcodes.OpDiagnoseOS(output_fields=["name", "valid"], |
|
231 |
names=[]) |
|
232 |
diagnose_data = ganeti.cli.SubmitOpCode(op) |
|
233 |
|
|
234 |
if not isinstance(diagnose_data, list): |
|
235 |
raise http.HttpInternalServerError(message="Can't get OS list") |
|
236 |
|
|
237 |
return [row[0] for row in diagnose_data if row[1]] |
b/lib/rapi/rlib2.py | ||
---|---|---|
29 | 29 |
from ganeti import constants |
30 | 30 |
from ganeti.rapi import baserlib |
31 | 31 |
|
32 |
from ganeti.rapi.rlib1 import I_FIELDS, N_FIELDS |
|
32 |
|
|
33 |
I_FIELDS = ["name", "os", "pnode", "snodes", "admin_state", "disk_template", |
|
34 |
"ip", "mac", "bridge", "sda_size", "sdb_size", "beparams", |
|
35 |
"oper_state", "status", "tags"] |
|
36 |
|
|
37 |
N_FIELDS = ["name", "dtotal", "dfree", |
|
38 |
"mtotal", "mnode", "mfree", |
|
39 |
"pinst_cnt", "sinst_cnt", "tags"] |
|
40 |
|
|
41 |
|
|
42 |
class R_version(baserlib.R_Generic): |
|
43 |
"""/version resource. |
|
44 |
|
|
45 |
This resource should be used to determine the remote API version and |
|
46 |
to adapt clients accordingly. |
|
47 |
|
|
48 |
""" |
|
49 |
DOC_URI = "/version" |
|
50 |
|
|
51 |
def GET(self): |
|
52 |
"""Returns the remote API version. |
|
53 |
|
|
54 |
""" |
|
55 |
return constants.RAPI_VERSION |
|
56 |
|
|
57 |
|
|
58 |
class R_2_info(baserlib.R_Generic): |
|
59 |
"""Cluster info. |
|
60 |
|
|
61 |
""" |
|
62 |
DOC_URI = "/2/info" |
|
63 |
|
|
64 |
def GET(self): |
|
65 |
"""Returns cluster information. |
|
66 |
|
|
67 |
Example:: |
|
68 |
|
|
69 |
{ |
|
70 |
"config_version": 3, |
|
71 |
"name": "cluster1.example.com", |
|
72 |
"software_version": "1.2.4", |
|
73 |
"os_api_version": 5, |
|
74 |
"export_version": 0, |
|
75 |
"master": "node1.example.com", |
|
76 |
"architecture": [ |
|
77 |
"64bit", |
|
78 |
"x86_64" |
|
79 |
], |
|
80 |
"hypervisor_type": "xen-pvm", |
|
81 |
"protocol_version": 12 |
|
82 |
} |
|
83 |
|
|
84 |
""" |
|
85 |
op = ganeti.opcodes.OpQueryClusterInfo() |
|
86 |
return ganeti.cli.SubmitOpCode(op) |
|
87 |
|
|
88 |
|
|
89 |
class R_2_tags(baserlib.R_Generic): |
|
90 |
"""/2/tags resource. |
|
91 |
|
|
92 |
Manages cluster tags. |
|
93 |
|
|
94 |
""" |
|
95 |
DOC_URI = "/2/tags" |
|
96 |
|
|
97 |
def GET(self): |
|
98 |
"""Returns a list of all cluster tags. |
|
99 |
|
|
100 |
Example: ["tag1", "tag2", "tag3"] |
|
101 |
|
|
102 |
""" |
|
103 |
return baserlib._Tags_GET(constants.TAG_CLUSTER) |
|
104 |
|
|
105 |
|
|
106 |
class R_2_os(baserlib.R_Generic): |
|
107 |
"""/2/os resource. |
|
108 |
|
|
109 |
""" |
|
110 |
DOC_URI = "/2/os" |
|
111 |
|
|
112 |
def GET(self): |
|
113 |
"""Return a list of all OSes. |
|
114 |
|
|
115 |
Can return error 500 in case of a problem. |
|
116 |
|
|
117 |
Example: ["debian-etch"] |
|
118 |
|
|
119 |
""" |
|
120 |
op = ganeti.opcodes.OpDiagnoseOS(output_fields=["name", "valid"], |
|
121 |
names=[]) |
|
122 |
diagnose_data = ganeti.cli.SubmitOpCode(op) |
|
123 |
|
|
124 |
if not isinstance(diagnose_data, list): |
|
125 |
raise http.HttpInternalServerError(message="Can't get OS list") |
|
126 |
|
|
127 |
return [row[0] for row in diagnose_data if row[1]] |
|
33 | 128 |
|
34 | 129 |
|
35 | 130 |
class R_2_jobs(baserlib.R_Generic): |
... | ... | |
141 | 236 |
uri_fields=("id", "uri")) |
142 | 237 |
|
143 | 238 |
|
144 |
class R_nodes(R_2_nodes):
|
|
145 |
"""/nodes resource
|
|
239 |
class R_2_nodes_name(baserlib.R_Generic):
|
|
240 |
"""/2/nodes/[node_name] resources.
|
|
146 | 241 |
|
147 | 242 |
""" |
148 |
# TODO: Temporary resource will be deprecated |
|
149 |
DOC_URI = "/nodes" |
|
243 |
DOC_URI = "/nodes/[node_name]" |
|
244 |
|
|
245 |
def GET(self): |
|
246 |
"""Send information about a node. |
|
247 |
|
|
248 |
""" |
|
249 |
node_name = self.items[0] |
|
250 |
op = ganeti.opcodes.OpQueryNodes(output_fields=N_FIELDS, |
|
251 |
names=[node_name]) |
|
252 |
result = ganeti.cli.SubmitOpCode(op) |
|
253 |
|
|
254 |
return baserlib.MapFields(N_FIELDS, result[0]) |
|
150 | 255 |
|
151 | 256 |
|
152 | 257 |
class R_2_instances(baserlib.R_Generic): |
... | ... | |
254 | 359 |
return job_id |
255 | 360 |
|
256 | 361 |
|
257 |
class R_instances(R_2_instances):
|
|
258 |
"""/instances resource.
|
|
362 |
class R_2_instances_name(baserlib.R_Generic):
|
|
363 |
"""/2/instances/[instance_name] resources.
|
|
259 | 364 |
|
260 | 365 |
""" |
261 |
# TODO: Temporary resource will be deprecated |
|
262 |
DOC_URI = "/instances" |
|
366 |
DOC_URI = "/2/instances/[instance_name]" |
|
367 |
|
|
368 |
def GET(self): |
|
369 |
"""Send information about an instance. |
|
370 |
|
|
371 |
""" |
|
372 |
instance_name = self.items[0] |
|
373 |
op = ganeti.opcodes.OpQueryInstances(output_fields=I_FIELDS, |
|
374 |
names=[instance_name]) |
|
375 |
result = ganeti.cli.SubmitOpCode(op) |
|
376 |
|
|
377 |
return baserlib.MapFields(I_FIELDS, result[0]) |
|
263 | 378 |
|
264 | 379 |
|
265 | 380 |
class R_2_instances_name_reboot(baserlib.R_Generic): |
b/test/ganeti.rapi.resources_unittest.py | ||
---|---|---|
29 | 29 |
from ganeti import http |
30 | 30 |
|
31 | 31 |
from ganeti.rapi import connector |
32 |
from ganeti.rapi import rlib1 |
|
33 | 32 |
from ganeti.rapi import rlib2 |
34 | 33 |
|
35 | 34 |
|
... | ... | |
50 | 49 |
|
51 | 50 |
self._TestFailingUri("/tags") |
52 | 51 |
self._TestFailingUri("/instances") |
53 |
self._TestUri("/version", (rlib1.R_version, [], {}))
|
|
52 |
self._TestUri("/version", (rlib2.R_version, [], {}))
|
|
54 | 53 |
|
55 | 54 |
self._TestUri('/2/instances/www.test.com', |
56 |
(rlib1.R_instances_name,
|
|
55 |
(rlib2.R_2_instances_name,
|
|
57 | 56 |
['www.test.com'], |
58 | 57 |
{})) |
59 | 58 |
|
Also available in: Unified diff