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