4 # Copyright (C) 2006, 2007, 2008 Google Inc.
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.
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.
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
22 """Remote API base resources library.
29 from ganeti import luxi
30 from ganeti import rapi
31 from ganeti import http
32 from ganeti import ssconf
33 from ganeti import constants
36 def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
37 """Builds a URI list as used by index resources.
39 @param ids: list of ids as strings
40 @param uri_format: format to be applied for URI
41 @param uri_fields: optional parameter for field IDs
44 (field_id, field_uri) = uri_fields
47 return { field_id: m_id, field_uri: uri_format % m_id, }
49 # Make sure the result is sorted, makes it nicer to look at and simplifies
53 return map(_MapId, ids)
56 def ExtractField(sequence, index):
57 """Creates a list containing one column out of a list of lists.
59 @param sequence: sequence of lists
60 @param index: index of field
63 return map(lambda item: item[index], sequence)
66 def MapFields(names, data):
67 """Maps two lists into one dictionary.
70 >>> MapFields(["a", "b"], ["foo", 123])
71 {'a': 'foo', 'b': 123}
73 @param names: field names (list of strings)
74 @param data: field data (list)
77 if len(names) != len(data):
78 raise AttributeError("Names and data must have the same length")
79 return dict(zip(names, data))
82 def _Tags_GET(kind, name=""):
83 """Helper function to retrieve tags.
86 if kind == constants.TAG_INSTANCE or kind == constants.TAG_NODE:
88 raise HttpBadRequest("Missing name on tag request")
90 if kind == constants.TAG_INSTANCE:
91 fn = cl.QueryInstances
94 result = fn(names=[name], fields=["tags"], use_locking=False)
95 if not result or not result[0]:
96 raise http.HttpBadGateway("Invalid response from tag query")
98 elif kind == constants.TAG_CLUSTER:
99 ssc = ssconf.SimpleStore()
100 tags = ssc.GetClusterTags()
105 def _Tags_PUT(kind, tags, name=""):
106 """Helper function to set tags.
110 return cl.SubmitJob([ganeti.opcodes.OpAddTags(kind=kind, name=name,
114 def _Tags_DELETE(kind, tags, name=""):
115 """Helper function to delete tags.
119 return cl.SubmitJob([ganeti.opcodes.OpDelTags(kind=kind, name=name,
123 def MapBulkFields(itemslist, fields):
124 """Map value to field name in to one dictionary.
126 @param itemslist: a list of items values
127 @param fields: a list of items names
129 @return: a list of mapped dictionaries
133 for item in itemslist:
134 mapped = MapFields(fields, item)
135 items_details.append(mapped)
139 def MakeParamsDict(opts, params):
140 """Makes params dictionary out of a option set.
142 This function returns a dictionary needed for hv or be parameters. But only
143 those fields which provided in the option set. Takes parameters frozensets
147 @param opts: selected options
148 @type params: frozenset
149 @param params: subset of options
151 @return: dictionary of options, filtered by given subset.
166 class R_Generic(object):
167 """Generic class for resources.
170 # Default permission requirements
172 PUT_ACCESS = [rapi.RAPI_ACCESS_WRITE]
173 POST_ACCESS = [rapi.RAPI_ACCESS_WRITE]
174 DELETE_ACCESS = [rapi.RAPI_ACCESS_WRITE]
176 def __init__(self, items, queryargs, req):
177 """Generic resource constructor.
179 @param items: a list with variables encoded in the URL
180 @param queryargs: a dictionary with additional options from URL
184 self.queryargs = queryargs
188 def getSerialNumber(self):
189 """Get Serial Number.
194 def _checkIntVariable(self, name):
195 """Return the parsed value of an int argument.
198 val = self.queryargs.get(name, 0)
199 if isinstance(val, list):
206 except (ValueError, TypeError), err:
207 raise http.HttpBadRequest("Invalid value for the"
208 " '%s' parameter" % (name,))
211 def getBodyParameter(self, name, *args):
212 """Check and return the value for a given parameter.
214 If a second parameter is not given, an error will be returned,
215 otherwise this parameter specifies the default value.
217 @param name: the required parameter
220 if name in self.req.request_body:
221 return self.req.request_body[name]
225 raise http.HttpBadRequest("Required parameter '%s' is missing" %
228 def useLocking(self):
229 """Check if the request specifies locking.
232 return self._checkIntVariable('lock')
235 """Check if the request specifies bulk querying.
238 return self._checkIntVariable('bulk')