1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Remote API base resources library.
23
24 """
25
26
27
28
29
30 import logging
31
32 from ganeti import luxi
33 from ganeti import rapi
34 from ganeti import http
35 from ganeti import ssconf
36 from ganeti import constants
37 from ganeti import opcodes
38 from ganeti import errors
39
40
41
42 _DEFAULT = object()
43
44
45 -def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
46 """Builds a URI list as used by index resources.
47
48 @param ids: list of ids as strings
49 @param uri_format: format to be applied for URI
50 @param uri_fields: optional parameter for field IDs
51
52 """
53 (field_id, field_uri) = uri_fields
54
55 def _MapId(m_id):
56 return { field_id: m_id, field_uri: uri_format % m_id, }
57
58
59
60 ids.sort()
61
62 return map(_MapId, ids)
63
64
66 """Creates a list containing one column out of a list of lists.
67
68 @param sequence: sequence of lists
69 @param index: index of field
70
71 """
72 return map(lambda item: item[index], sequence)
73
74
76 """Maps two lists into one dictionary.
77
78 Example::
79 >>> MapFields(["a", "b"], ["foo", 123])
80 {'a': 'foo', 'b': 123}
81
82 @param names: field names (list of strings)
83 @param data: field data (list)
84
85 """
86 if len(names) != len(data):
87 raise AttributeError("Names and data must have the same length")
88 return dict(zip(names, data))
89
90
112
113
120
121
128
129
131 """Map value to field name in to one dictionary.
132
133 @param itemslist: a list of items values
134 @param fields: a list of items names
135
136 @return: a list of mapped dictionaries
137
138 """
139 items_details = []
140 for item in itemslist:
141 mapped = MapFields(fields, item)
142 items_details.append(mapped)
143 return items_details
144
145
147 """Makes params dictionary out of a option set.
148
149 This function returns a dictionary needed for hv or be parameters. But only
150 those fields which provided in the option set. Takes parameters frozensets
151 from constants.
152
153 @type opts: dict
154 @param opts: selected options
155 @type params: frozenset
156 @param params: subset of options
157 @rtype: dict
158 @return: dictionary of options, filtered by given subset.
159
160 """
161 result = {}
162
163 for p in params:
164 try:
165 value = opts[p]
166 except KeyError:
167 continue
168 result[p] = value
169
170 return result
171
172
197
198
210
211
213 """Geric wrapper for luxi.Client(), for better http compatiblity.
214
215 """
216 try:
217 return luxi.Client()
218 except luxi.NoMasterError, err:
219 raise http.HttpBadGateway("Master seems to unreachable: %s" % str(err))
220
221
223 """Feedback logging function for http case.
224
225 We don't have a stdout for printing log messages, so log them to the
226 http log at least.
227
228 @param ts: the timestamp (unused)
229
230 """
231 logging.info("%s: %s", log_type, log_msg)
232
233
235 """Abort request if value type doesn't match expected type.
236
237 @param value: Value
238 @type exptype: type
239 @param exptype: Expected type
240 @type descr: string
241 @param descr: Description of value
242 @return: Value (allows inline usage)
243
244 """
245 if not isinstance(value, exptype):
246 raise http.HttpBadRequest("%s: Type is '%s', but '%s' is expected" %
247 (descr, type(value).__name__, exptype.__name__))
248
249 return value
250
251
253 """Check and return the value for a given parameter.
254
255 If no default value was given and the parameter doesn't exist in the input
256 data, an error is raise.
257
258 @type data: dict
259 @param data: Dictionary containing input data
260 @type name: string
261 @param name: Parameter name
262 @param default: Default value (can be None)
263 @param exptype: Expected type (can be None)
264
265 """
266 try:
267 value = data[name]
268 except KeyError:
269 if default is not _DEFAULT:
270 return default
271
272 raise http.HttpBadRequest("Required parameter '%s' is missing" %
273 name)
274
275 if exptype is _DEFAULT:
276 return value
277
278 return CheckType(value, exptype, "'%s' parameter" % name)
279
280
282 """Generic class for resources.
283
284 """
285
286 GET_ACCESS = []
287 PUT_ACCESS = [rapi.RAPI_ACCESS_WRITE]
288 POST_ACCESS = [rapi.RAPI_ACCESS_WRITE]
289 DELETE_ACCESS = [rapi.RAPI_ACCESS_WRITE]
290
291 - def __init__(self, items, queryargs, req):
292 """Generic resource constructor.
293
294 @param items: a list with variables encoded in the URL
295 @param queryargs: a dictionary with additional options from URL
296
297 """
298 self.items = items
299 self.queryargs = queryargs
300 self.req = req
301 self.sn = None
302
304 """Get Serial Number.
305
306 """
307 return self.sn
308
310 """Return the parsed value of an int argument.
311
312 """
313 val = self.queryargs.get(name, default)
314 if isinstance(val, list):
315 if val:
316 val = val[0]
317 else:
318 val = default
319 try:
320 val = int(val)
321 except (ValueError, TypeError):
322 raise http.HttpBadRequest("Invalid value for the"
323 " '%s' parameter" % (name,))
324 return val
325
327 """Return the parsed value of an int argument.
328
329 """
330 val = self.queryargs.get(name, default)
331 if isinstance(val, list):
332 if val:
333 val = val[0]
334 else:
335 val = default
336 return val
337
338 - def getBodyParameter(self, name, *args):
339 """Check and return the value for a given parameter.
340
341 If a second parameter is not given, an error will be returned,
342 otherwise this parameter specifies the default value.
343
344 @param name: the required parameter
345
346 """
347 if args:
348 return CheckParameter(self.req.request_body, name, default=args[0])
349
350 return CheckParameter(self.req.request_body, name)
351
353 """Check if the request specifies locking.
354
355 """
356 return self._checkIntVariable('lock')
357
359 """Check if the request specifies bulk querying.
360
361 """
362 return self._checkIntVariable('bulk')
363
365 """Check if the request specifies a forced operation.
366
367 """
368 return self._checkIntVariable('force')
369
371 """Check if the request specifies dry-run mode.
372
373 """
374 return self._checkIntVariable('dry-run')
375