Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / baserlib.py @ 414ebaf1

History | View | Annotate | Download (11.3 kB)

1 c2dca9af Oleksiy Mishchenko
#
2 c2dca9af Oleksiy Mishchenko
#
3 c2dca9af Oleksiy Mishchenko
4 c2dca9af Oleksiy Mishchenko
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 c2dca9af Oleksiy Mishchenko
#
6 c2dca9af Oleksiy Mishchenko
# This program is free software; you can redistribute it and/or modify
7 c2dca9af Oleksiy Mishchenko
# it under the terms of the GNU General Public License as published by
8 c2dca9af Oleksiy Mishchenko
# the Free Software Foundation; either version 2 of the License, or
9 c2dca9af Oleksiy Mishchenko
# (at your option) any later version.
10 c2dca9af Oleksiy Mishchenko
#
11 c2dca9af Oleksiy Mishchenko
# This program is distributed in the hope that it will be useful, but
12 c2dca9af Oleksiy Mishchenko
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 c2dca9af Oleksiy Mishchenko
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 c2dca9af Oleksiy Mishchenko
# General Public License for more details.
15 c2dca9af Oleksiy Mishchenko
#
16 c2dca9af Oleksiy Mishchenko
# You should have received a copy of the GNU General Public License
17 c2dca9af Oleksiy Mishchenko
# along with this program; if not, write to the Free Software
18 c2dca9af Oleksiy Mishchenko
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 c2dca9af Oleksiy Mishchenko
# 02110-1301, USA.
20 c2dca9af Oleksiy Mishchenko
21 c2dca9af Oleksiy Mishchenko
22 c2dca9af Oleksiy Mishchenko
"""Remote API base resources library.
23 c2dca9af Oleksiy Mishchenko

24 c2dca9af Oleksiy Mishchenko
"""
25 c2dca9af Oleksiy Mishchenko
26 fe267188 Iustin Pop
# pylint: disable-msg=C0103
27 fe267188 Iustin Pop
28 fe267188 Iustin Pop
# C0103: Invalid name, since the R_* names are not conforming
29 fe267188 Iustin Pop
30 59b4eeef Iustin Pop
import logging
31 59b4eeef Iustin Pop
32 441e7cfd Oleksiy Mishchenko
from ganeti import luxi
33 b5b67ef9 Michael Hanselmann
from ganeti import rapi
34 3d103742 Iustin Pop
from ganeti import http
35 25e39bfa Iustin Pop
from ganeti import ssconf
36 25e39bfa Iustin Pop
from ganeti import constants
37 59b4eeef Iustin Pop
from ganeti import opcodes
38 59b4eeef Iustin Pop
from ganeti import errors
39 441e7cfd Oleksiy Mishchenko
40 c2dca9af Oleksiy Mishchenko
41 af6433c6 Michael Hanselmann
# Dummy value to detect unchanged parameters
42 af6433c6 Michael Hanselmann
_DEFAULT = object()
43 af6433c6 Michael Hanselmann
44 af6433c6 Michael Hanselmann
45 c2dca9af Oleksiy Mishchenko
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
46 c2dca9af Oleksiy Mishchenko
  """Builds a URI list as used by index resources.
47 c2dca9af Oleksiy Mishchenko

48 c41eea6e Iustin Pop
  @param ids: list of ids as strings
49 c41eea6e Iustin Pop
  @param uri_format: format to be applied for URI
50 c41eea6e Iustin Pop
  @param uri_fields: optional parameter for field IDs
51 c2dca9af Oleksiy Mishchenko

52 c2dca9af Oleksiy Mishchenko
  """
53 c2dca9af Oleksiy Mishchenko
  (field_id, field_uri) = uri_fields
54 dca1764e Iustin Pop
55 c2dca9af Oleksiy Mishchenko
  def _MapId(m_id):
56 c2dca9af Oleksiy Mishchenko
    return { field_id: m_id, field_uri: uri_format % m_id, }
57 c2dca9af Oleksiy Mishchenko
58 c2dca9af Oleksiy Mishchenko
  # Make sure the result is sorted, makes it nicer to look at and simplifies
59 c2dca9af Oleksiy Mishchenko
  # unittests.
60 c2dca9af Oleksiy Mishchenko
  ids.sort()
61 c2dca9af Oleksiy Mishchenko
62 c2dca9af Oleksiy Mishchenko
  return map(_MapId, ids)
63 c2dca9af Oleksiy Mishchenko
64 c2dca9af Oleksiy Mishchenko
65 c2dca9af Oleksiy Mishchenko
def ExtractField(sequence, index):
66 c2dca9af Oleksiy Mishchenko
  """Creates a list containing one column out of a list of lists.
67 c2dca9af Oleksiy Mishchenko

68 c41eea6e Iustin Pop
  @param sequence: sequence of lists
69 c41eea6e Iustin Pop
  @param index: index of field
70 c2dca9af Oleksiy Mishchenko

71 c2dca9af Oleksiy Mishchenko
  """
72 c2dca9af Oleksiy Mishchenko
  return map(lambda item: item[index], sequence)
73 c2dca9af Oleksiy Mishchenko
74 c2dca9af Oleksiy Mishchenko
75 c2dca9af Oleksiy Mishchenko
def MapFields(names, data):
76 c2dca9af Oleksiy Mishchenko
  """Maps two lists into one dictionary.
77 c2dca9af Oleksiy Mishchenko

78 c41eea6e Iustin Pop
  Example::
79 c41eea6e Iustin Pop
      >>> MapFields(["a", "b"], ["foo", 123])
80 c41eea6e Iustin Pop
      {'a': 'foo', 'b': 123}
81 c2dca9af Oleksiy Mishchenko

82 c41eea6e Iustin Pop
  @param names: field names (list of strings)
83 c41eea6e Iustin Pop
  @param data: field data (list)
84 c2dca9af Oleksiy Mishchenko

85 c2dca9af Oleksiy Mishchenko
  """
86 c2dca9af Oleksiy Mishchenko
  if len(names) != len(data):
87 c2dca9af Oleksiy Mishchenko
    raise AttributeError("Names and data must have the same length")
88 dca1764e Iustin Pop
  return dict(zip(names, data))
89 c2dca9af Oleksiy Mishchenko
90 c2dca9af Oleksiy Mishchenko
91 64246438 Iustin Pop
def _Tags_GET(kind, name):
92 c2dca9af Oleksiy Mishchenko
  """Helper function to retrieve tags.
93 c2dca9af Oleksiy Mishchenko

94 c2dca9af Oleksiy Mishchenko
  """
95 414ebaf1 Michael Hanselmann
  if kind in (constants.TAG_INSTANCE,
96 414ebaf1 Michael Hanselmann
              constants.TAG_NODEGROUP,
97 414ebaf1 Michael Hanselmann
              constants.TAG_NODE):
98 25e39bfa Iustin Pop
    if not name:
99 59b4eeef Iustin Pop
      raise http.HttpBadRequest("Missing name on tag request")
100 59b4eeef Iustin Pop
    cl = GetClient()
101 25e39bfa Iustin Pop
    if kind == constants.TAG_INSTANCE:
102 25e39bfa Iustin Pop
      fn = cl.QueryInstances
103 414ebaf1 Michael Hanselmann
    elif kind == constants.TAG_NODEGROUP:
104 414ebaf1 Michael Hanselmann
      fn = cl.QueryGroups
105 25e39bfa Iustin Pop
    else:
106 25e39bfa Iustin Pop
      fn = cl.QueryNodes
107 25e39bfa Iustin Pop
    result = fn(names=[name], fields=["tags"], use_locking=False)
108 25e39bfa Iustin Pop
    if not result or not result[0]:
109 25e39bfa Iustin Pop
      raise http.HttpBadGateway("Invalid response from tag query")
110 25e39bfa Iustin Pop
    tags = result[0][0]
111 25e39bfa Iustin Pop
  elif kind == constants.TAG_CLUSTER:
112 25e39bfa Iustin Pop
    ssc = ssconf.SimpleStore()
113 25e39bfa Iustin Pop
    tags = ssc.GetClusterTags()
114 25e39bfa Iustin Pop
115 c2dca9af Oleksiy Mishchenko
  return list(tags)
116 c2dca9af Oleksiy Mishchenko
117 c2dca9af Oleksiy Mishchenko
118 64246438 Iustin Pop
def _Tags_PUT(kind, tags, name, dry_run):
119 441e7cfd Oleksiy Mishchenko
  """Helper function to set tags.
120 441e7cfd Oleksiy Mishchenko

121 441e7cfd Oleksiy Mishchenko
  """
122 d1602edc Iustin Pop
  return SubmitJob([opcodes.OpTagsSet(kind=kind, name=name,
123 64246438 Iustin Pop
                                      tags=tags, dry_run=dry_run)])
124 441e7cfd Oleksiy Mishchenko
125 441e7cfd Oleksiy Mishchenko
126 64246438 Iustin Pop
def _Tags_DELETE(kind, tags, name, dry_run):
127 15fd9fd5 Oleksiy Mishchenko
  """Helper function to delete tags.
128 15fd9fd5 Oleksiy Mishchenko

129 15fd9fd5 Oleksiy Mishchenko
  """
130 3f0ab95f Iustin Pop
  return SubmitJob([opcodes.OpTagsDel(kind=kind, name=name,
131 64246438 Iustin Pop
                                      tags=tags, dry_run=dry_run)])
132 15fd9fd5 Oleksiy Mishchenko
133 15fd9fd5 Oleksiy Mishchenko
134 51ee2f49 Oleksiy Mishchenko
def MapBulkFields(itemslist, fields):
135 51ee2f49 Oleksiy Mishchenko
  """Map value to field name in to one dictionary.
136 51ee2f49 Oleksiy Mishchenko

137 c41eea6e Iustin Pop
  @param itemslist: a list of items values
138 c41eea6e Iustin Pop
  @param fields: a list of items names
139 c41eea6e Iustin Pop

140 c41eea6e Iustin Pop
  @return: a list of mapped dictionaries
141 51ee2f49 Oleksiy Mishchenko

142 51ee2f49 Oleksiy Mishchenko
  """
143 51ee2f49 Oleksiy Mishchenko
  items_details = []
144 51ee2f49 Oleksiy Mishchenko
  for item in itemslist:
145 51ee2f49 Oleksiy Mishchenko
    mapped = MapFields(fields, item)
146 51ee2f49 Oleksiy Mishchenko
    items_details.append(mapped)
147 51ee2f49 Oleksiy Mishchenko
  return items_details
148 51ee2f49 Oleksiy Mishchenko
149 51ee2f49 Oleksiy Mishchenko
150 d50b3059 Oleksiy Mishchenko
def MakeParamsDict(opts, params):
151 c41eea6e Iustin Pop
  """Makes params dictionary out of a option set.
152 d50b3059 Oleksiy Mishchenko

153 d50b3059 Oleksiy Mishchenko
  This function returns a dictionary needed for hv or be parameters. But only
154 d50b3059 Oleksiy Mishchenko
  those fields which provided in the option set. Takes parameters frozensets
155 d50b3059 Oleksiy Mishchenko
  from constants.
156 d50b3059 Oleksiy Mishchenko

157 d50b3059 Oleksiy Mishchenko
  @type opts: dict
158 d50b3059 Oleksiy Mishchenko
  @param opts: selected options
159 d50b3059 Oleksiy Mishchenko
  @type params: frozenset
160 d50b3059 Oleksiy Mishchenko
  @param params: subset of options
161 d50b3059 Oleksiy Mishchenko
  @rtype: dict
162 d50b3059 Oleksiy Mishchenko
  @return: dictionary of options, filtered by given subset.
163 d50b3059 Oleksiy Mishchenko

164 d50b3059 Oleksiy Mishchenko
  """
165 d50b3059 Oleksiy Mishchenko
  result = {}
166 d50b3059 Oleksiy Mishchenko
167 d50b3059 Oleksiy Mishchenko
  for p in params:
168 d50b3059 Oleksiy Mishchenko
    try:
169 d50b3059 Oleksiy Mishchenko
      value = opts[p]
170 d50b3059 Oleksiy Mishchenko
    except KeyError:
171 d50b3059 Oleksiy Mishchenko
      continue
172 d50b3059 Oleksiy Mishchenko
    result[p] = value
173 d50b3059 Oleksiy Mishchenko
174 d50b3059 Oleksiy Mishchenko
  return result
175 d50b3059 Oleksiy Mishchenko
176 d50b3059 Oleksiy Mishchenko
177 b166ef84 Michael Hanselmann
def FillOpcode(opcls, body, static, rename=None):
178 cfaeaaf7 Michael Hanselmann
  """Fills an opcode with body parameters.
179 cfaeaaf7 Michael Hanselmann

180 cfaeaaf7 Michael Hanselmann
  Parameter types are checked.
181 cfaeaaf7 Michael Hanselmann

182 cfaeaaf7 Michael Hanselmann
  @type opcls: L{opcodes.OpCode}
183 cfaeaaf7 Michael Hanselmann
  @param opcls: Opcode class
184 cfaeaaf7 Michael Hanselmann
  @type body: dict
185 cfaeaaf7 Michael Hanselmann
  @param body: Body parameters as received from client
186 cfaeaaf7 Michael Hanselmann
  @type static: dict
187 cfaeaaf7 Michael Hanselmann
  @param static: Static parameters which can't be modified by client
188 b166ef84 Michael Hanselmann
  @type rename: dict
189 b166ef84 Michael Hanselmann
  @param rename: Renamed parameters, key as old name, value as new name
190 cfaeaaf7 Michael Hanselmann
  @return: Opcode object
191 cfaeaaf7 Michael Hanselmann

192 cfaeaaf7 Michael Hanselmann
  """
193 cfaeaaf7 Michael Hanselmann
  CheckType(body, dict, "Body contents")
194 cfaeaaf7 Michael Hanselmann
195 b166ef84 Michael Hanselmann
  # Make copy to be modified
196 b166ef84 Michael Hanselmann
  params = body.copy()
197 b166ef84 Michael Hanselmann
198 b166ef84 Michael Hanselmann
  if rename:
199 b166ef84 Michael Hanselmann
    for old, new in rename.items():
200 b166ef84 Michael Hanselmann
      if new in params and old in params:
201 b166ef84 Michael Hanselmann
        raise http.HttpBadRequest("Parameter '%s' was renamed to '%s', but"
202 b166ef84 Michael Hanselmann
                                  " both are specified" %
203 b166ef84 Michael Hanselmann
                                  (old, new))
204 b166ef84 Michael Hanselmann
      if old in params:
205 b166ef84 Michael Hanselmann
        assert new not in params
206 b166ef84 Michael Hanselmann
        params[new] = params.pop(old)
207 b166ef84 Michael Hanselmann
208 cfaeaaf7 Michael Hanselmann
  if static:
209 b166ef84 Michael Hanselmann
    overwritten = set(params.keys()) & set(static.keys())
210 cfaeaaf7 Michael Hanselmann
    if overwritten:
211 cfaeaaf7 Michael Hanselmann
      raise http.HttpBadRequest("Can't overwrite static parameters %r" %
212 cfaeaaf7 Michael Hanselmann
                                overwritten)
213 cfaeaaf7 Michael Hanselmann
214 cfaeaaf7 Michael Hanselmann
    params.update(static)
215 cfaeaaf7 Michael Hanselmann
216 cfaeaaf7 Michael Hanselmann
  # Convert keys to strings (simplejson decodes them as unicode)
217 cfaeaaf7 Michael Hanselmann
  params = dict((str(key), value) for (key, value) in params.items())
218 cfaeaaf7 Michael Hanselmann
219 cfaeaaf7 Michael Hanselmann
  try:
220 cfaeaaf7 Michael Hanselmann
    op = opcls(**params) # pylint: disable-msg=W0142
221 cfaeaaf7 Michael Hanselmann
    op.Validate(False)
222 cfaeaaf7 Michael Hanselmann
  except (errors.OpPrereqError, TypeError), err:
223 cfaeaaf7 Michael Hanselmann
    raise http.HttpBadRequest("Invalid body parameters: %s" % err)
224 cfaeaaf7 Michael Hanselmann
225 cfaeaaf7 Michael Hanselmann
  return op
226 cfaeaaf7 Michael Hanselmann
227 cfaeaaf7 Michael Hanselmann
228 59b4eeef Iustin Pop
def SubmitJob(op, cl=None):
229 59b4eeef Iustin Pop
  """Generic wrapper for submit job, for better http compatibility.
230 59b4eeef Iustin Pop

231 59b4eeef Iustin Pop
  @type op: list
232 59b4eeef Iustin Pop
  @param op: the list of opcodes for the job
233 59b4eeef Iustin Pop
  @type cl: None or luxi.Client
234 59b4eeef Iustin Pop
  @param cl: optional luxi client to use
235 59b4eeef Iustin Pop
  @rtype: string
236 59b4eeef Iustin Pop
  @return: the job ID
237 59b4eeef Iustin Pop

238 59b4eeef Iustin Pop
  """
239 59b4eeef Iustin Pop
  try:
240 59b4eeef Iustin Pop
    if cl is None:
241 59b4eeef Iustin Pop
      cl = GetClient()
242 59b4eeef Iustin Pop
    return cl.SubmitJob(op)
243 59b4eeef Iustin Pop
  except errors.JobQueueFull:
244 59b4eeef Iustin Pop
    raise http.HttpServiceUnavailable("Job queue is full, needs archiving")
245 59b4eeef Iustin Pop
  except errors.JobQueueDrainError:
246 59b4eeef Iustin Pop
    raise http.HttpServiceUnavailable("Job queue is drained, cannot submit")
247 59b4eeef Iustin Pop
  except luxi.NoMasterError, err:
248 5a1c22fe Iustin Pop
    raise http.HttpBadGateway("Master seems to be unreachable: %s" % str(err))
249 5a1c22fe Iustin Pop
  except luxi.PermissionError:
250 5a1c22fe Iustin Pop
    raise http.HttpInternalServerError("Internal error: no permission to"
251 5a1c22fe Iustin Pop
                                       " connect to the master daemon")
252 59b4eeef Iustin Pop
  except luxi.TimeoutError, err:
253 59b4eeef Iustin Pop
    raise http.HttpGatewayTimeout("Timeout while talking to the master"
254 59b4eeef Iustin Pop
                                  " daemon. Error: %s" % str(err))
255 59b4eeef Iustin Pop
256 e8ebbd2b Michael Hanselmann
257 e8ebbd2b Michael Hanselmann
def HandleItemQueryErrors(fn, *args, **kwargs):
258 e8ebbd2b Michael Hanselmann
  """Converts errors when querying a single item.
259 e8ebbd2b Michael Hanselmann

260 e8ebbd2b Michael Hanselmann
  """
261 e8ebbd2b Michael Hanselmann
  try:
262 e8ebbd2b Michael Hanselmann
    return fn(*args, **kwargs)
263 e8ebbd2b Michael Hanselmann
  except errors.OpPrereqError, err:
264 e8ebbd2b Michael Hanselmann
    if len(err.args) == 2 and err.args[1] == errors.ECODE_NOENT:
265 e8ebbd2b Michael Hanselmann
      raise http.HttpNotFound()
266 e8ebbd2b Michael Hanselmann
267 e8ebbd2b Michael Hanselmann
    raise
268 e8ebbd2b Michael Hanselmann
269 e8ebbd2b Michael Hanselmann
270 59b4eeef Iustin Pop
def GetClient():
271 59b4eeef Iustin Pop
  """Geric wrapper for luxi.Client(), for better http compatiblity.
272 59b4eeef Iustin Pop

273 59b4eeef Iustin Pop
  """
274 59b4eeef Iustin Pop
  try:
275 59b4eeef Iustin Pop
    return luxi.Client()
276 59b4eeef Iustin Pop
  except luxi.NoMasterError, err:
277 59b4eeef Iustin Pop
    raise http.HttpBadGateway("Master seems to unreachable: %s" % str(err))
278 5a1c22fe Iustin Pop
  except luxi.PermissionError:
279 5a1c22fe Iustin Pop
    raise http.HttpInternalServerError("Internal error: no permission to"
280 5a1c22fe Iustin Pop
                                       " connect to the master daemon")
281 59b4eeef Iustin Pop
282 59b4eeef Iustin Pop
283 e51ca051 Michael Hanselmann
def FeedbackFn(msg):
284 e51ca051 Michael Hanselmann
  """Feedback logging function for jobs.
285 59b4eeef Iustin Pop

286 59b4eeef Iustin Pop
  We don't have a stdout for printing log messages, so log them to the
287 59b4eeef Iustin Pop
  http log at least.
288 59b4eeef Iustin Pop

289 e51ca051 Michael Hanselmann
  @param msg: the message
290 2d54e29c Iustin Pop

291 59b4eeef Iustin Pop
  """
292 e51ca051 Michael Hanselmann
  (_, log_type, log_msg) = msg
293 59b4eeef Iustin Pop
  logging.info("%s: %s", log_type, log_msg)
294 59b4eeef Iustin Pop
295 59b4eeef Iustin Pop
296 af6433c6 Michael Hanselmann
def CheckType(value, exptype, descr):
297 af6433c6 Michael Hanselmann
  """Abort request if value type doesn't match expected type.
298 af6433c6 Michael Hanselmann

299 af6433c6 Michael Hanselmann
  @param value: Value
300 af6433c6 Michael Hanselmann
  @type exptype: type
301 af6433c6 Michael Hanselmann
  @param exptype: Expected type
302 af6433c6 Michael Hanselmann
  @type descr: string
303 af6433c6 Michael Hanselmann
  @param descr: Description of value
304 af6433c6 Michael Hanselmann
  @return: Value (allows inline usage)
305 af6433c6 Michael Hanselmann

306 af6433c6 Michael Hanselmann
  """
307 af6433c6 Michael Hanselmann
  if not isinstance(value, exptype):
308 af6433c6 Michael Hanselmann
    raise http.HttpBadRequest("%s: Type is '%s', but '%s' is expected" %
309 af6433c6 Michael Hanselmann
                              (descr, type(value).__name__, exptype.__name__))
310 af6433c6 Michael Hanselmann
311 af6433c6 Michael Hanselmann
  return value
312 af6433c6 Michael Hanselmann
313 af6433c6 Michael Hanselmann
314 af6433c6 Michael Hanselmann
def CheckParameter(data, name, default=_DEFAULT, exptype=_DEFAULT):
315 af6433c6 Michael Hanselmann
  """Check and return the value for a given parameter.
316 af6433c6 Michael Hanselmann

317 af6433c6 Michael Hanselmann
  If no default value was given and the parameter doesn't exist in the input
318 af6433c6 Michael Hanselmann
  data, an error is raise.
319 af6433c6 Michael Hanselmann

320 af6433c6 Michael Hanselmann
  @type data: dict
321 af6433c6 Michael Hanselmann
  @param data: Dictionary containing input data
322 af6433c6 Michael Hanselmann
  @type name: string
323 af6433c6 Michael Hanselmann
  @param name: Parameter name
324 af6433c6 Michael Hanselmann
  @param default: Default value (can be None)
325 af6433c6 Michael Hanselmann
  @param exptype: Expected type (can be None)
326 af6433c6 Michael Hanselmann

327 af6433c6 Michael Hanselmann
  """
328 af6433c6 Michael Hanselmann
  try:
329 af6433c6 Michael Hanselmann
    value = data[name]
330 af6433c6 Michael Hanselmann
  except KeyError:
331 af6433c6 Michael Hanselmann
    if default is not _DEFAULT:
332 af6433c6 Michael Hanselmann
      return default
333 af6433c6 Michael Hanselmann
334 af6433c6 Michael Hanselmann
    raise http.HttpBadRequest("Required parameter '%s' is missing" %
335 af6433c6 Michael Hanselmann
                              name)
336 af6433c6 Michael Hanselmann
337 af6433c6 Michael Hanselmann
  if exptype is _DEFAULT:
338 af6433c6 Michael Hanselmann
    return value
339 af6433c6 Michael Hanselmann
340 af6433c6 Michael Hanselmann
  return CheckType(value, exptype, "'%s' parameter" % name)
341 af6433c6 Michael Hanselmann
342 af6433c6 Michael Hanselmann
343 c2dca9af Oleksiy Mishchenko
class R_Generic(object):
344 c2dca9af Oleksiy Mishchenko
  """Generic class for resources.
345 c2dca9af Oleksiy Mishchenko

346 c2dca9af Oleksiy Mishchenko
  """
347 b5b67ef9 Michael Hanselmann
  # Default permission requirements
348 b5b67ef9 Michael Hanselmann
  GET_ACCESS = []
349 b5b67ef9 Michael Hanselmann
  PUT_ACCESS = [rapi.RAPI_ACCESS_WRITE]
350 b5b67ef9 Michael Hanselmann
  POST_ACCESS = [rapi.RAPI_ACCESS_WRITE]
351 b5b67ef9 Michael Hanselmann
  DELETE_ACCESS = [rapi.RAPI_ACCESS_WRITE]
352 b5b67ef9 Michael Hanselmann
353 7a8f64da Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
354 c2dca9af Oleksiy Mishchenko
    """Generic resource constructor.
355 c2dca9af Oleksiy Mishchenko

356 c41eea6e Iustin Pop
    @param items: a list with variables encoded in the URL
357 c41eea6e Iustin Pop
    @param queryargs: a dictionary with additional options from URL
358 c2dca9af Oleksiy Mishchenko

359 c2dca9af Oleksiy Mishchenko
    """
360 c2dca9af Oleksiy Mishchenko
    self.items = items
361 c2dca9af Oleksiy Mishchenko
    self.queryargs = queryargs
362 627ad739 Michael Hanselmann
    self._req = req
363 627ad739 Michael Hanselmann
364 2feecf12 Michael Hanselmann
  def _GetRequestBody(self):
365 2feecf12 Michael Hanselmann
    """Returns the body data.
366 2feecf12 Michael Hanselmann

367 2feecf12 Michael Hanselmann
    """
368 2feecf12 Michael Hanselmann
    return self._req.private.body_data
369 2feecf12 Michael Hanselmann
370 2feecf12 Michael Hanselmann
  request_body = property(fget=_GetRequestBody)
371 3d103742 Iustin Pop
372 3fb8680a Michael Hanselmann
  def _checkIntVariable(self, name, default=0):
373 3d103742 Iustin Pop
    """Return the parsed value of an int argument.
374 3d103742 Iustin Pop

375 3d103742 Iustin Pop
    """
376 3fb8680a Michael Hanselmann
    val = self.queryargs.get(name, default)
377 3d103742 Iustin Pop
    if isinstance(val, list):
378 3d103742 Iustin Pop
      if val:
379 3d103742 Iustin Pop
        val = val[0]
380 3d103742 Iustin Pop
      else:
381 3fb8680a Michael Hanselmann
        val = default
382 3d103742 Iustin Pop
    try:
383 3d103742 Iustin Pop
      val = int(val)
384 7c4d6c7b Michael Hanselmann
    except (ValueError, TypeError):
385 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Invalid value for the"
386 3d103742 Iustin Pop
                                " '%s' parameter" % (name,))
387 3d103742 Iustin Pop
    return val
388 3d103742 Iustin Pop
389 e5b7c4ca Iustin Pop
  def _checkStringVariable(self, name, default=None):
390 e5b7c4ca Iustin Pop
    """Return the parsed value of an int argument.
391 e5b7c4ca Iustin Pop

392 e5b7c4ca Iustin Pop
    """
393 e5b7c4ca Iustin Pop
    val = self.queryargs.get(name, default)
394 e5b7c4ca Iustin Pop
    if isinstance(val, list):
395 e5b7c4ca Iustin Pop
      if val:
396 e5b7c4ca Iustin Pop
        val = val[0]
397 e5b7c4ca Iustin Pop
      else:
398 e5b7c4ca Iustin Pop
        val = default
399 e5b7c4ca Iustin Pop
    return val
400 3d103742 Iustin Pop
401 6e99c5a0 Iustin Pop
  def getBodyParameter(self, name, *args):
402 6e99c5a0 Iustin Pop
    """Check and return the value for a given parameter.
403 6e99c5a0 Iustin Pop

404 6e99c5a0 Iustin Pop
    If a second parameter is not given, an error will be returned,
405 6e99c5a0 Iustin Pop
    otherwise this parameter specifies the default value.
406 6e99c5a0 Iustin Pop

407 6e99c5a0 Iustin Pop
    @param name: the required parameter
408 6e99c5a0 Iustin Pop

409 6e99c5a0 Iustin Pop
    """
410 af6433c6 Michael Hanselmann
    if args:
411 1c54156d Luca Bigliardi
      return CheckParameter(self.request_body, name, default=args[0])
412 ab221ddf Michael Hanselmann
413 1c54156d Luca Bigliardi
    return CheckParameter(self.request_body, name)
414 6e99c5a0 Iustin Pop
415 3d103742 Iustin Pop
  def useLocking(self):
416 3d103742 Iustin Pop
    """Check if the request specifies locking.
417 3d103742 Iustin Pop

418 3d103742 Iustin Pop
    """
419 b939de46 Michael Hanselmann
    return bool(self._checkIntVariable("lock"))
420 3d103742 Iustin Pop
421 3d103742 Iustin Pop
  def useBulk(self):
422 3d103742 Iustin Pop
    """Check if the request specifies bulk querying.
423 3d103742 Iustin Pop

424 3d103742 Iustin Pop
    """
425 b939de46 Michael Hanselmann
    return bool(self._checkIntVariable("bulk"))
426 6f59b964 Iustin Pop
427 3427d34f Michael Hanselmann
  def useForce(self):
428 3427d34f Michael Hanselmann
    """Check if the request specifies a forced operation.
429 3427d34f Michael Hanselmann

430 3427d34f Michael Hanselmann
    """
431 b939de46 Michael Hanselmann
    return bool(self._checkIntVariable("force"))
432 3427d34f Michael Hanselmann
433 6f59b964 Iustin Pop
  def dryRun(self):
434 6f59b964 Iustin Pop
    """Check if the request specifies dry-run mode.
435 6f59b964 Iustin Pop

436 6f59b964 Iustin Pop
    """
437 b939de46 Michael Hanselmann
    return bool(self._checkIntVariable("dry-run"))