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