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