Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / baserlib.py @ 25e39bfa

History | View | Annotate | Download (5.9 kB)

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 base resources library.
23

24
"""
25

    
26
import ganeti.cli
27
import ganeti.opcodes
28

    
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
34

    
35

    
36
def BuildUriList(ids, uri_format, uri_fields=("name", "uri")):
37
  """Builds a URI list as used by index resources.
38

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
42

43
  """
44
  (field_id, field_uri) = uri_fields
45

    
46
  def _MapId(m_id):
47
    return { field_id: m_id, field_uri: uri_format % m_id, }
48

    
49
  # Make sure the result is sorted, makes it nicer to look at and simplifies
50
  # unittests.
51
  ids.sort()
52

    
53
  return map(_MapId, ids)
54

    
55

    
56
def ExtractField(sequence, index):
57
  """Creates a list containing one column out of a list of lists.
58

59
  @param sequence: sequence of lists
60
  @param index: index of field
61

62
  """
63
  return map(lambda item: item[index], sequence)
64

    
65

    
66
def MapFields(names, data):
67
  """Maps two lists into one dictionary.
68

69
  Example::
70
      >>> MapFields(["a", "b"], ["foo", 123])
71
      {'a': 'foo', 'b': 123}
72

73
  @param names: field names (list of strings)
74
  @param data: field data (list)
75

76
  """
77
  if len(names) != len(data):
78
    raise AttributeError("Names and data must have the same length")
79
  return dict(zip(names, data))
80

    
81

    
82
def _Tags_GET(kind, name=""):
83
  """Helper function to retrieve tags.
84

85
  """
86
  if kind == constants.TAG_INSTANCE or kind == constants.TAG_NODE:
87
    if not name:
88
      raise HttpBadRequest("Missing name on tag request")
89
    cl = luxi.Client()
90
    if kind == constants.TAG_INSTANCE:
91
      fn = cl.QueryInstances
92
    else:
93
      fn = cl.QueryNodes
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")
97
    tags = result[0][0]
98
  elif kind == constants.TAG_CLUSTER:
99
    ssc = ssconf.SimpleStore()
100
    tags = ssc.GetClusterTags()
101

    
102
  return list(tags)
103

    
104

    
105
def _Tags_PUT(kind, tags, name=""):
106
  """Helper function to set tags.
107

108
  """
109
  cl = luxi.Client()
110
  return cl.SubmitJob([ganeti.opcodes.OpAddTags(kind=kind, name=name,
111
                                                tags=tags)])
112

    
113

    
114
def _Tags_DELETE(kind, tags, name=""):
115
  """Helper function to delete tags.
116

117
  """
118
  cl = luxi.Client()
119
  return cl.SubmitJob([ganeti.opcodes.OpDelTags(kind=kind, name=name,
120
                                                tags=tags)])
121

    
122

    
123
def MapBulkFields(itemslist, fields):
124
  """Map value to field name in to one dictionary.
125

126
  @param itemslist: a list of items values
127
  @param fields: a list of items names
128

129
  @return: a list of mapped dictionaries
130

131
  """
132
  items_details = []
133
  for item in itemslist:
134
    mapped = MapFields(fields, item)
135
    items_details.append(mapped)
136
  return items_details
137

    
138

    
139
def MakeParamsDict(opts, params):
140
  """Makes params dictionary out of a option set.
141

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
144
  from constants.
145

146
  @type opts: dict
147
  @param opts: selected options
148
  @type params: frozenset
149
  @param params: subset of options
150
  @rtype: dict
151
  @return: dictionary of options, filtered by given subset.
152

153
  """
154
  result = {}
155

    
156
  for p in params:
157
    try:
158
      value = opts[p]
159
    except KeyError:
160
      continue
161
    result[p] = value
162

    
163
  return result
164

    
165

    
166
class R_Generic(object):
167
  """Generic class for resources.
168

169
  """
170
  # Default permission requirements
171
  GET_ACCESS = []
172
  PUT_ACCESS = [rapi.RAPI_ACCESS_WRITE]
173
  POST_ACCESS = [rapi.RAPI_ACCESS_WRITE]
174
  DELETE_ACCESS = [rapi.RAPI_ACCESS_WRITE]
175

    
176
  def __init__(self, items, queryargs, req):
177
    """Generic resource constructor.
178

179
    @param items: a list with variables encoded in the URL
180
    @param queryargs: a dictionary with additional options from URL
181

182
    """
183
    self.items = items
184
    self.queryargs = queryargs
185
    self.req = req
186
    self.sn = None
187

    
188
  def getSerialNumber(self):
189
    """Get Serial Number.
190

191
    """
192
    return self.sn
193

    
194
  def _checkIntVariable(self, name):
195
    """Return the parsed value of an int argument.
196

197
    """
198
    val = self.queryargs.get(name, 0)
199
    if isinstance(val, list):
200
      if val:
201
        val = val[0]
202
      else:
203
        val = 0
204
    try:
205
      val = int(val)
206
    except (ValueError, TypeError), err:
207
      raise http.HttpBadRequest("Invalid value for the"
208
                                " '%s' parameter" % (name,))
209
    return val
210

    
211
  def getBodyParameter(self, name, *args):
212
    """Check and return the value for a given parameter.
213

214
    If a second parameter is not given, an error will be returned,
215
    otherwise this parameter specifies the default value.
216

217
    @param name: the required parameter
218

219
    """
220
    if name in self.req.request_body:
221
      return self.req.request_body[name]
222
    elif args:
223
      return args[0]
224
    else:
225
      raise http.HttpBadRequest("Required parameter '%s' is missing" %
226
                                name)
227

    
228
  def useLocking(self):
229
    """Check if the request specifies locking.
230

231
    """
232
    return self._checkIntVariable('lock')
233

    
234
  def useBulk(self):
235
    """Check if the request specifies bulk querying.
236

237
    """
238
    return self._checkIntVariable('bulk')