RAPI: Instance add/delete implementation.
[ganeti-local] / lib / rapi / rlib1.py
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", "be/vcpus",
38             "be/memory", "be/auto_balance",
39             "oper_state", "status", "tags"]
40
41 N_FIELDS = ["name", "dtotal", "dfree",
42             "mtotal", "mnode", "mfree",
43             "pinst_cnt", "sinst_cnt", "tags"]
44
45
46 class R_version(baserlib.R_Generic):
47   """/version resource.
48
49   This resource should be used to determine the remote API version and to adapt
50   clients accordingly.
51
52   """
53   DOC_URI = "/version"
54
55   def GET(self):
56     """Returns the remote API version.
57
58     """
59     return constants.RAPI_VERSION
60
61
62 class R_tags(baserlib.R_Generic):
63   """/tags resource.
64
65   Manages cluster tags.
66
67   """
68   DOC_URI = "/tags"
69
70   def GET(self):
71     """Returns a list of all cluster tags.
72
73     Example: ["tag1", "tag2", "tag3"]
74
75     """
76     return baserlib._Tags_GET(constants.TAG_CLUSTER)
77
78
79 class R_info(baserlib.R_Generic):
80   """Cluster info.
81
82   """
83   DOC_URI = "/info"
84
85   def GET(self):
86     """Returns cluster information.
87
88     Example: {
89       "config_version": 3,
90       "name": "cluster1.example.com",
91       "software_version": "1.2.4",
92       "os_api_version": 5,
93       "export_version": 0,
94       "master": "node1.example.com",
95       "architecture": [
96         "64bit",
97         "x86_64"
98       ],
99       "hypervisor_type": "xen-pvm",
100       "protocol_version": 12
101     }
102
103     """
104     op = ganeti.opcodes.OpQueryClusterInfo()
105     return ganeti.cli.SubmitOpCode(op)
106
107
108 class R_nodes(baserlib.R_Generic):
109   """/nodes resource.
110
111   """
112   DOC_URI = "/nodes"
113
114   def GET(self):
115     """Returns a list of all nodes.
116
117     Returns:
118       A dictionary with 'name' and 'uri' keys for each of them.
119
120     Example: [
121         {
122           "name": "node1.example.com",
123           "uri": "\/instances\/node1.example.com"
124         },
125         {
126           "name": "node2.example.com",
127           "uri": "\/instances\/node2.example.com"
128         }]
129
130     If the optional 'bulk' argument is provided and set to 'true'
131     value (i.e '?bulk=1'), the output contains detailed
132     information about nodes as a list.
133
134     Example: [
135         {
136           "pinst_cnt": 1,
137           "mfree": 31280,
138           "mtotal": 32763,
139           "name": "www.example.com",
140           "tags": [],
141           "mnode": 512,
142           "dtotal": 5246208,
143           "sinst_cnt": 2,
144           "dfree": 5171712
145         },
146         ...
147     ]
148
149     """
150     op = ganeti.opcodes.OpQueryNodes(output_fields=["name"], names=[])
151     nodeslist = baserlib.ExtractField(ganeti.cli.SubmitOpCode(op), 0)
152
153     if 'bulk' in self.queryargs:
154       op = ganeti.opcodes.OpQueryNodes(output_fields=N_FIELDS,
155                                        names=nodeslist)
156       result = ganeti.cli.SubmitOpCode(op)
157       return baserlib.MapBulkFields(result, N_FIELDS)
158
159     return baserlib.BuildUriList(nodeslist, "/nodes/%s")
160
161
162 class R_nodes_name(baserlib.R_Generic):
163   """/nodes/[node_name] resources.
164
165   """
166   DOC_URI = "/nodes/[node_name]"
167
168   def GET(self):
169     """Send information about a node.
170
171     """
172     node_name = self.items[0]
173     op = ganeti.opcodes.OpQueryNodes(output_fields=N_FIELDS,
174                                      names=[node_name])
175     result = ganeti.cli.SubmitOpCode(op)
176
177     return baserlib.MapFields(N_FIELDS, result[0])
178
179
180 class R_nodes_name_tags(baserlib.R_Generic):
181   """/nodes/[node_name]/tags resource.
182
183   Manages per-node tags.
184
185   """
186   DOC_URI = "/nodes/[node_name]/tags"
187
188   def GET(self):
189     """Returns a list of node tags.
190
191     Example: ["tag1", "tag2", "tag3"]
192
193     """
194     return baserlib._Tags_GET(constants.TAG_NODE, name=self.items[0])
195
196
197 class R_instances(baserlib.R_Generic):
198   """/instances resource.
199
200   """
201   DOC_URI = "/instances"
202
203
204   def GET(self):
205     """Returns a list of all available instances.
206
207     Returns:
208        A dictionary with 'name' and 'uri' keys for each of them.
209
210     Example: [
211         {
212           "name": "web.example.com",
213           "uri": "\/instances\/web.example.com"
214         },
215         {
216           "name": "mail.example.com",
217           "uri": "\/instances\/mail.example.com"
218         }]
219
220     If the optional 'bulk' argument is provided and set to 'true'
221     value (i.e '?bulk=1'), the output contains detailed
222     information about instances as a list.
223
224     Example: [
225         {
226            "status": "running",
227            "bridge": "xen-br0",
228            "name": "web.example.com",
229            "tags": ["tag1", "tag2"],
230            "admin_ram": 512,
231            "sda_size": 20480,
232            "pnode": "node1.example.com",
233            "mac": "01:23:45:67:89:01",
234            "sdb_size": 4096,
235            "snodes": ["node2.example.com"],
236            "disk_template": "drbd",
237            "ip": null,
238            "admin_state": true,
239            "os": "debian-etch",
240            "vcpus": 2,
241            "oper_state": true
242         },
243         ...
244     ]
245
246     """
247     op = ganeti.opcodes.OpQueryInstances(output_fields=["name"], names=[])
248     instanceslist = baserlib.ExtractField(ganeti.cli.SubmitOpCode(op), 0)
249
250     if 'bulk' in self.queryargs:
251       op = ganeti.opcodes.OpQueryInstances(output_fields=I_FIELDS,
252                                            names=instanceslist)
253       result = ganeti.cli.SubmitOpCode(op)
254       return baserlib.MapBulkFields(result, I_FIELDS)
255
256
257     else:
258       return baserlib.BuildUriList(instanceslist, "/instances/%s")
259
260
261 class R_instances_name(baserlib.R_Generic):
262   """/instances/[instance_name] resources.
263
264   """
265   DOC_URI = "/instances/[instance_name]"
266
267   def GET(self):
268     """Send information about an instance.
269
270     """
271     instance_name = self.items[0]
272     op = ganeti.opcodes.OpQueryInstances(output_fields=I_FIELDS,
273                                          names=[instance_name])
274     result = ganeti.cli.SubmitOpCode(op)
275
276     return baserlib.MapFields(I_FIELDS, result[0])
277
278   def DELETE(self):
279     """Removes an instance.
280
281     """
282     instance_name = self.items[0]
283     op = ganeti.opcodes.OpRemoveInstance(instance_name=instance_name,
284                                          ignore_failures=True)
285     job_id = ganeti.cli.SendJob([op])
286
287     return job_id
288
289
290 class R_instances_name_tags(baserlib.R_Generic):
291   """/instances/[instance_name]/tags resource.
292
293   Manages per-instance tags.
294
295   """
296   DOC_URI = "/instances/[instance_name]/tags"
297
298   def GET(self):
299     """Returns a list of instance tags.
300
301     Example: ["tag1", "tag2", "tag3"]
302
303     """
304     return baserlib._Tags_GET(constants.TAG_INSTANCE, name=self.items[0])
305
306
307 class R_os(baserlib.R_Generic):
308   """/os resource.
309
310   """
311   DOC_URI = "/os"
312
313   def GET(self):
314     """Return a list of all OSes.
315
316     Can return error 500 in case of a problem.
317
318     Example: ["debian-etch"]
319
320     """
321     op = ganeti.opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
322                                      names=[])
323     diagnose_data = ganeti.cli.SubmitOpCode(op)
324
325     if not isinstance(diagnose_data, list):
326       raise http.HTTPInternalError(message="Can't get OS list")
327
328     return [row[0] for row in diagnose_data if row[1]]