Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 0a37de5f

History | View | Annotate | Download (21.3 kB)

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

24 10b207d4 Oleksiy Mishchenko
"""
25 10b207d4 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
from ganeti import opcodes
31 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
32 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
33 59b4eeef Iustin Pop
from ganeti import cli
34 8381fa2d Michael Hanselmann
from ganeti import rapi
35 38206f3c Iustin Pop
from ganeti.rapi import baserlib
36 10b207d4 Oleksiy Mishchenko
37 4e5a68f8 Oleksiy Mishchenko
38 7118a0df Iustin Pop
_COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
39 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
40 9031ee8e Iustin Pop
            "pnode", "snodes",
41 9031ee8e Iustin Pop
            "disk_template",
42 82e186f8 Michael Hanselmann
            "nic.ips", "nic.macs", "nic.modes", "nic.links", "nic.bridges",
43 a8b16c4e Tim Boring
            "network_port",
44 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
45 a5b9d725 Iustin Pop
            "beparams", "hvparams",
46 9031ee8e Iustin Pop
            "oper_state", "oper_ram", "status",
47 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
48 9031ee8e Iustin Pop
49 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
50 9031ee8e Iustin Pop
            "dtotal", "dfree",
51 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
52 7118a0df Iustin Pop
            "pinst_cnt", "sinst_cnt",
53 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
54 7118a0df Iustin Pop
            "pip", "sip", "role",
55 93962b80 Iustin Pop
            "pinst_list", "sinst_list",
56 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
57 4e5a68f8 Oleksiy Mishchenko
58 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
59 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
60 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
61 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
62 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
63 64dae8fc Michael Hanselmann
64 64dae8fc Michael Hanselmann
_NR_MAP = {
65 64dae8fc Michael Hanselmann
  "M": _NR_MASTER,
66 64dae8fc Michael Hanselmann
  "C": _NR_MASTER_CANDIATE,
67 64dae8fc Michael Hanselmann
  "D": _NR_DRAINED,
68 64dae8fc Michael Hanselmann
  "O": _NR_OFFLINE,
69 64dae8fc Michael Hanselmann
  "R": _NR_REGULAR,
70 64dae8fc Michael Hanselmann
  }
71 64dae8fc Michael Hanselmann
72 4e5a68f8 Oleksiy Mishchenko
73 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
74 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
75 4e5a68f8 Oleksiy Mishchenko

76 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
77 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
78 4e5a68f8 Oleksiy Mishchenko

79 4e5a68f8 Oleksiy Mishchenko
  """
80 7e950d31 Iustin Pop
  @staticmethod
81 7e950d31 Iustin Pop
  def GET():
82 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
83 4e5a68f8 Oleksiy Mishchenko

84 4e5a68f8 Oleksiy Mishchenko
    """
85 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
86 4e5a68f8 Oleksiy Mishchenko
87 4e5a68f8 Oleksiy Mishchenko
88 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
89 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
90 4e5a68f8 Oleksiy Mishchenko

91 4e5a68f8 Oleksiy Mishchenko
  """
92 7e950d31 Iustin Pop
  @staticmethod
93 7e950d31 Iustin Pop
  def GET():
94 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
95 4e5a68f8 Oleksiy Mishchenko

96 4e5a68f8 Oleksiy Mishchenko
    """
97 59b4eeef Iustin Pop
    client = baserlib.GetClient()
98 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
99 4e5a68f8 Oleksiy Mishchenko
100 4e5a68f8 Oleksiy Mishchenko
101 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
102 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
103 4e5a68f8 Oleksiy Mishchenko

104 4e5a68f8 Oleksiy Mishchenko
  """
105 7e950d31 Iustin Pop
  @staticmethod
106 7e950d31 Iustin Pop
  def GET():
107 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
108 4e5a68f8 Oleksiy Mishchenko

109 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
110 4e5a68f8 Oleksiy Mishchenko

111 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
112 4e5a68f8 Oleksiy Mishchenko

113 4e5a68f8 Oleksiy Mishchenko
    """
114 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
115 e3ac208c Guido Trotter
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
116 e3ac208c Guido Trotter
                              names=[])
117 59b4eeef Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
118 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
119 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
120 59b4eeef Iustin Pop
    diagnose_data = result[0]
121 4e5a68f8 Oleksiy Mishchenko
122 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
123 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
124 4e5a68f8 Oleksiy Mishchenko
125 e3ac208c Guido Trotter
    os_names = []
126 e3ac208c Guido Trotter
    for (name, valid, variants) in diagnose_data:
127 e3ac208c Guido Trotter
      if valid:
128 e3ac208c Guido Trotter
        os_names.extend(cli.CalculateOSNames(name, variants))
129 e3ac208c Guido Trotter
130 e3ac208c Guido Trotter
    return os_names
131 51ee2f49 Oleksiy Mishchenko
132 10b207d4 Oleksiy Mishchenko
133 508e9b20 Michael Hanselmann
class R_2_redist_config(baserlib.R_Generic):
134 508e9b20 Michael Hanselmann
  """/2/redistribute-config resource.
135 508e9b20 Michael Hanselmann

136 508e9b20 Michael Hanselmann
  """
137 7e950d31 Iustin Pop
  @staticmethod
138 7e950d31 Iustin Pop
  def PUT():
139 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
140 508e9b20 Michael Hanselmann

141 508e9b20 Michael Hanselmann
    """
142 508e9b20 Michael Hanselmann
    return baserlib.SubmitJob([opcodes.OpRedistributeConfig()])
143 508e9b20 Michael Hanselmann
144 508e9b20 Michael Hanselmann
145 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
146 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
147 10b207d4 Oleksiy Mishchenko

148 10b207d4 Oleksiy Mishchenko
  """
149 7e950d31 Iustin Pop
  @staticmethod
150 7e950d31 Iustin Pop
  def GET():
151 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
152 10b207d4 Oleksiy Mishchenko

153 c41eea6e Iustin Pop
    @return: a dictionary with jobs id and uri.
154 38206f3c Iustin Pop

155 10b207d4 Oleksiy Mishchenko
    """
156 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
157 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
158 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
159 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
160 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
161 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
162 10b207d4 Oleksiy Mishchenko
163 10b207d4 Oleksiy Mishchenko
164 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
165 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
166 10b207d4 Oleksiy Mishchenko

167 10b207d4 Oleksiy Mishchenko
  """
168 10b207d4 Oleksiy Mishchenko
  def GET(self):
169 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
170 10b207d4 Oleksiy Mishchenko

171 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
172 c41eea6e Iustin Pop
        The result includes:
173 c41eea6e Iustin Pop
            - id: job ID as a number
174 c41eea6e Iustin Pop
            - status: current job status as a string
175 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
176 c41eea6e Iustin Pop
              opcodes in the job
177 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
178 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
179 38206f3c Iustin Pop

180 10b207d4 Oleksiy Mishchenko
    """
181 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
182 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
183 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
184 ee69c97f Iustin Pop
              ]
185 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
186 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
187 ee69c97f Iustin Pop
    if result is None:
188 ee69c97f Iustin Pop
      raise http.HttpNotFound()
189 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
190 10b207d4 Oleksiy Mishchenko
191 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
192 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
193 c7f5f338 Oleksiy Mishchenko

194 c7f5f338 Oleksiy Mishchenko
    """
195 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
196 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
197 c7f5f338 Oleksiy Mishchenko
    return result
198 c7f5f338 Oleksiy Mishchenko
199 10b207d4 Oleksiy Mishchenko
200 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
201 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
202 10b207d4 Oleksiy Mishchenko

203 10b207d4 Oleksiy Mishchenko
  """
204 10b207d4 Oleksiy Mishchenko
  def GET(self):
205 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
206 38206f3c Iustin Pop

207 10b207d4 Oleksiy Mishchenko
    """
208 59b4eeef Iustin Pop
    client = baserlib.GetClient()
209 38206f3c Iustin Pop
210 3d103742 Iustin Pop
    if self.useBulk():
211 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
212 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
213 9031ee8e Iustin Pop
    else:
214 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
215 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
216 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
217 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
218 441e7cfd Oleksiy Mishchenko
219 441e7cfd Oleksiy Mishchenko
220 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
221 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
222 028c6b76 Oleksiy Mishchenko

223 028c6b76 Oleksiy Mishchenko
  """
224 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
225 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
226 4e5a68f8 Oleksiy Mishchenko

227 4e5a68f8 Oleksiy Mishchenko
    """
228 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
229 59b4eeef Iustin Pop
    client = baserlib.GetClient()
230 9031ee8e Iustin Pop
    result = client.QueryNodes(names=[node_name], fields=N_FIELDS,
231 3d103742 Iustin Pop
                               use_locking=self.useLocking())
232 4e5a68f8 Oleksiy Mishchenko
233 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
234 028c6b76 Oleksiy Mishchenko
235 028c6b76 Oleksiy Mishchenko
236 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
237 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
238 64dae8fc Michael Hanselmann

239 64dae8fc Michael Hanselmann
  """
240 64dae8fc Michael Hanselmann
  def GET(self):
241 64dae8fc Michael Hanselmann
    """Returns the current node role.
242 64dae8fc Michael Hanselmann

243 64dae8fc Michael Hanselmann
    @return: Node role
244 64dae8fc Michael Hanselmann

245 64dae8fc Michael Hanselmann
    """
246 64dae8fc Michael Hanselmann
    node_name = self.items[0]
247 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
248 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
249 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
250 64dae8fc Michael Hanselmann
251 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
252 64dae8fc Michael Hanselmann
253 64dae8fc Michael Hanselmann
  def PUT(self):
254 64dae8fc Michael Hanselmann
    """Sets the node role.
255 64dae8fc Michael Hanselmann

256 64dae8fc Michael Hanselmann
    @return: a job id
257 64dae8fc Michael Hanselmann

258 64dae8fc Michael Hanselmann
    """
259 64dae8fc Michael Hanselmann
    if not isinstance(self.req.request_body, basestring):
260 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
261 64dae8fc Michael Hanselmann
262 64dae8fc Michael Hanselmann
    node_name = self.items[0]
263 64dae8fc Michael Hanselmann
    role = self.req.request_body
264 64dae8fc Michael Hanselmann
265 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
266 64dae8fc Michael Hanselmann
      candidate = False
267 64dae8fc Michael Hanselmann
      offline = False
268 64dae8fc Michael Hanselmann
      drained = False
269 64dae8fc Michael Hanselmann
270 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
271 64dae8fc Michael Hanselmann
      candidate = True
272 64dae8fc Michael Hanselmann
      offline = drained = None
273 64dae8fc Michael Hanselmann
274 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
275 64dae8fc Michael Hanselmann
      drained = True
276 64dae8fc Michael Hanselmann
      candidate = offline = None
277 64dae8fc Michael Hanselmann
278 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
279 64dae8fc Michael Hanselmann
      offline = True
280 64dae8fc Michael Hanselmann
      candidate = drained = None
281 64dae8fc Michael Hanselmann
282 64dae8fc Michael Hanselmann
    else:
283 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
284 64dae8fc Michael Hanselmann
285 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
286 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
287 64dae8fc Michael Hanselmann
                                 offline=offline,
288 64dae8fc Michael Hanselmann
                                 drained=drained,
289 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
290 64dae8fc Michael Hanselmann
291 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
292 64dae8fc Michael Hanselmann
293 64dae8fc Michael Hanselmann
294 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
295 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
296 73452f12 Michael Hanselmann

297 73452f12 Michael Hanselmann
  """
298 73452f12 Michael Hanselmann
  def POST(self):
299 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
300 73452f12 Michael Hanselmann

301 73452f12 Michael Hanselmann
    """
302 73452f12 Michael Hanselmann
    node_name = self.items[0]
303 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
304 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
305 73452f12 Michael Hanselmann
306 73452f12 Michael Hanselmann
    op = opcodes.OpEvacuateNode(node_name=node_name,
307 73452f12 Michael Hanselmann
                                remote_node=remote_node,
308 73452f12 Michael Hanselmann
                                iallocator=iallocator)
309 73452f12 Michael Hanselmann
310 73452f12 Michael Hanselmann
    return baserlib.SubmitJob([op])
311 73452f12 Michael Hanselmann
312 73452f12 Michael Hanselmann
313 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
314 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
315 1c482bab Michael Hanselmann

316 1c482bab Michael Hanselmann
  """
317 1c482bab Michael Hanselmann
  def POST(self):
318 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
319 1c482bab Michael Hanselmann

320 1c482bab Michael Hanselmann
    """
321 1c482bab Michael Hanselmann
    node_name = self.items[0]
322 1c482bab Michael Hanselmann
    live = bool(self._checkIntVariable("live", default=1))
323 1c482bab Michael Hanselmann
324 1c482bab Michael Hanselmann
    op = opcodes.OpMigrateNode(node_name=node_name, live=live)
325 1c482bab Michael Hanselmann
326 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
327 1c482bab Michael Hanselmann
328 1c482bab Michael Hanselmann
329 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
330 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
331 7a95a954 Michael Hanselmann

332 7a95a954 Michael Hanselmann
  """
333 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
334 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
335 7a95a954 Michael Hanselmann
336 7a95a954 Michael Hanselmann
  def GET(self):
337 7a95a954 Michael Hanselmann
    node_name = self.items[0]
338 7a95a954 Michael Hanselmann
339 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
340 7a95a954 Michael Hanselmann
    if not storage_type:
341 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
342 7a95a954 Michael Hanselmann
                                " parameter")
343 7a95a954 Michael Hanselmann
344 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
345 7a95a954 Michael Hanselmann
    if not output_fields:
346 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
347 7a95a954 Michael Hanselmann
                                " parameter")
348 7a95a954 Michael Hanselmann
349 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
350 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
351 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
352 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
353 7a95a954 Michael Hanselmann
354 7a95a954 Michael Hanselmann
355 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
356 1e82bc80 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify ressource.
357 1e82bc80 Michael Hanselmann

358 1e82bc80 Michael Hanselmann
  """
359 1e82bc80 Michael Hanselmann
  def PUT(self):
360 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
361 1e82bc80 Michael Hanselmann
362 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
363 1e82bc80 Michael Hanselmann
    if not storage_type:
364 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
365 1e82bc80 Michael Hanselmann
                                " parameter")
366 1e82bc80 Michael Hanselmann
367 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
368 1e82bc80 Michael Hanselmann
    if not name:
369 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
370 1e82bc80 Michael Hanselmann
                                " parameter")
371 1e82bc80 Michael Hanselmann
372 1e82bc80 Michael Hanselmann
    changes = {}
373 1e82bc80 Michael Hanselmann
374 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
375 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
376 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
377 1e82bc80 Michael Hanselmann
378 1e82bc80 Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
379 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
380 1e82bc80 Michael Hanselmann
                                     name=name,
381 1e82bc80 Michael Hanselmann
                                     changes=changes)
382 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
383 1e82bc80 Michael Hanselmann
384 1e82bc80 Michael Hanselmann
385 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
386 723f4565 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair ressource.
387 723f4565 Michael Hanselmann

388 723f4565 Michael Hanselmann
  """
389 723f4565 Michael Hanselmann
  def PUT(self):
390 723f4565 Michael Hanselmann
    node_name = self.items[0]
391 723f4565 Michael Hanselmann
392 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
393 723f4565 Michael Hanselmann
    if not storage_type:
394 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
395 723f4565 Michael Hanselmann
                                " parameter")
396 723f4565 Michael Hanselmann
397 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
398 723f4565 Michael Hanselmann
    if not name:
399 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
400 723f4565 Michael Hanselmann
                                " parameter")
401 723f4565 Michael Hanselmann
402 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
403 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
404 723f4565 Michael Hanselmann
                                     name=name)
405 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
406 723f4565 Michael Hanselmann
407 723f4565 Michael Hanselmann
408 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
409 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
410 441e7cfd Oleksiy Mishchenko

411 441e7cfd Oleksiy Mishchenko
  """
412 441e7cfd Oleksiy Mishchenko
  def GET(self):
413 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
414 441e7cfd Oleksiy Mishchenko

415 441e7cfd Oleksiy Mishchenko
    """
416 59b4eeef Iustin Pop
    client = baserlib.GetClient()
417 441e7cfd Oleksiy Mishchenko
418 3d103742 Iustin Pop
    use_locking = self.useLocking()
419 3d103742 Iustin Pop
    if self.useBulk():
420 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
421 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
422 441e7cfd Oleksiy Mishchenko
    else:
423 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
424 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
425 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
426 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
427 441e7cfd Oleksiy Mishchenko
428 21f04e5e Oleksiy Mishchenko
  def POST(self):
429 2f7635f4 Oleksiy Mishchenko
    """Create an instance.
430 2f7635f4 Oleksiy Mishchenko

431 5fcc718f Iustin Pop
    @return: a job id
432 2f7635f4 Oleksiy Mishchenko

433 2f7635f4 Oleksiy Mishchenko
    """
434 6e99c5a0 Iustin Pop
    if not isinstance(self.req.request_body, dict):
435 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
436 6e99c5a0 Iustin Pop
437 6e99c5a0 Iustin Pop
    beparams = baserlib.MakeParamsDict(self.req.request_body,
438 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
439 6e99c5a0 Iustin Pop
    hvparams = baserlib.MakeParamsDict(self.req.request_body,
440 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
441 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
442 6e99c5a0 Iustin Pop
443 6e99c5a0 Iustin Pop
    # disk processing
444 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
445 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
446 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
447 6e99c5a0 Iustin Pop
    disks = []
448 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
449 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
450 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
451 69b99987 Michael Hanselmann
                                  " be an integer" % idx)
452 6e99c5a0 Iustin Pop
      disks.append({"size": d})
453 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
454 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
455 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
456 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
457 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
458 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
459 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
460 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
461 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
462 69b99987 Michael Hanselmann
      nics[0]["bridge"] = fn("bridge")
463 2f7635f4 Oleksiy Mishchenko
464 59b4eeef Iustin Pop
    op = opcodes.OpCreateInstance(
465 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
466 59b4eeef Iustin Pop
      instance_name=fn('name'),
467 59b4eeef Iustin Pop
      disks=disks,
468 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
469 59b4eeef Iustin Pop
      os_type=fn('os'),
470 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
471 59b4eeef Iustin Pop
      snode=fn('snode', None),
472 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
473 59b4eeef Iustin Pop
      nics=nics,
474 59b4eeef Iustin Pop
      start=fn('start', True),
475 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
476 460d22be Iustin Pop
      name_check=fn('name_check', True),
477 59b4eeef Iustin Pop
      wait_for_sync=True,
478 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
479 59b4eeef Iustin Pop
      hvparams=hvparams,
480 59b4eeef Iustin Pop
      beparams=beparams,
481 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
482 59b4eeef Iustin Pop
      file_driver=fn('file_driver', 'loop'),
483 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
484 59b4eeef Iustin Pop
      )
485 59b4eeef Iustin Pop
486 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
487 2f7635f4 Oleksiy Mishchenko
488 441e7cfd Oleksiy Mishchenko
489 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
490 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
491 028c6b76 Oleksiy Mishchenko

492 028c6b76 Oleksiy Mishchenko
  """
493 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
494 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
495 4e5a68f8 Oleksiy Mishchenko

496 4e5a68f8 Oleksiy Mishchenko
    """
497 59b4eeef Iustin Pop
    client = baserlib.GetClient()
498 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
499 9031ee8e Iustin Pop
    result = client.QueryInstances(names=[instance_name], fields=I_FIELDS,
500 3d103742 Iustin Pop
                                   use_locking=self.useLocking())
501 4e5a68f8 Oleksiy Mishchenko
502 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
503 028c6b76 Oleksiy Mishchenko
504 6e99c5a0 Iustin Pop
  def DELETE(self):
505 6e99c5a0 Iustin Pop
    """Delete an instance.
506 6e99c5a0 Iustin Pop

507 6e99c5a0 Iustin Pop
    """
508 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
509 6f59b964 Iustin Pop
                                  ignore_failures=False,
510 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
511 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
512 6e99c5a0 Iustin Pop
513 028c6b76 Oleksiy Mishchenko
514 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
515 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
516 d8260842 Michael Hanselmann

517 d8260842 Michael Hanselmann
  """
518 d8260842 Michael Hanselmann
  def GET(self):
519 d8260842 Michael Hanselmann
    """Request detailed instance information.
520 d8260842 Michael Hanselmann

521 d8260842 Michael Hanselmann
    """
522 d8260842 Michael Hanselmann
    instance_name = self.items[0]
523 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
524 d8260842 Michael Hanselmann
525 d8260842 Michael Hanselmann
    op = opcodes.OpQueryInstanceData(instances=[instance_name],
526 d8260842 Michael Hanselmann
                                     static=static)
527 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
528 d8260842 Michael Hanselmann
529 d8260842 Michael Hanselmann
530 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
531 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
532 2276aa29 Oleksiy Mishchenko

533 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
534 2276aa29 Oleksiy Mishchenko

535 2276aa29 Oleksiy Mishchenko
  """
536 21f04e5e Oleksiy Mishchenko
  def POST(self):
537 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
538 2276aa29 Oleksiy Mishchenko

539 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
540 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
541 0c55c24b Oleksiy Mishchenko

542 2276aa29 Oleksiy Mishchenko
    """
543 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
544 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
545 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
546 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
547 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
548 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
549 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
550 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
551 2276aa29 Oleksiy Mishchenko
552 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
553 2276aa29 Oleksiy Mishchenko
554 2276aa29 Oleksiy Mishchenko
555 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
556 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
557 0c55c24b Oleksiy Mishchenko

558 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
559 0c55c24b Oleksiy Mishchenko

560 0c55c24b Oleksiy Mishchenko
  """
561 21f04e5e Oleksiy Mishchenko
  def PUT(self):
562 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
563 0c55c24b Oleksiy Mishchenko

564 c41eea6e Iustin Pop
    The URI takes force=[False|True] parameter to start the instance
565 c41eea6e Iustin Pop
    if even if secondary disks are failing.
566 0c55c24b Oleksiy Mishchenko

567 0c55c24b Oleksiy Mishchenko
    """
568 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
569 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
570 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
571 6f59b964 Iustin Pop
                                   force=force_startup,
572 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
573 0c55c24b Oleksiy Mishchenko
574 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
575 0c55c24b Oleksiy Mishchenko
576 0c55c24b Oleksiy Mishchenko
577 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
578 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
579 0c55c24b Oleksiy Mishchenko

580 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
581 0c55c24b Oleksiy Mishchenko

582 0c55c24b Oleksiy Mishchenko
  """
583 21f04e5e Oleksiy Mishchenko
  def PUT(self):
584 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
585 0c55c24b Oleksiy Mishchenko

586 0c55c24b Oleksiy Mishchenko
    """
587 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
588 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
589 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
590 0c55c24b Oleksiy Mishchenko
591 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
592 0c55c24b Oleksiy Mishchenko
593 0c55c24b Oleksiy Mishchenko
594 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
595 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
596 e5b7c4ca Iustin Pop

597 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
598 e5b7c4ca Iustin Pop

599 e5b7c4ca Iustin Pop
  """
600 e5b7c4ca Iustin Pop
  def POST(self):
601 e5b7c4ca Iustin Pop
    """Reinstall an instance.
602 e5b7c4ca Iustin Pop

603 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
604 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
605 e5b7c4ca Iustin Pop
    automatically.
606 e5b7c4ca Iustin Pop

607 e5b7c4ca Iustin Pop
    """
608 e5b7c4ca Iustin Pop
    instance_name = self.items[0]
609 e5b7c4ca Iustin Pop
    ostype = self._checkStringVariable('os')
610 e5b7c4ca Iustin Pop
    nostartup = self._checkIntVariable('nostartup')
611 e5b7c4ca Iustin Pop
    ops = [
612 e5b7c4ca Iustin Pop
      opcodes.OpShutdownInstance(instance_name=instance_name),
613 e5b7c4ca Iustin Pop
      opcodes.OpReinstallInstance(instance_name=instance_name, os_type=ostype),
614 e5b7c4ca Iustin Pop
      ]
615 e5b7c4ca Iustin Pop
    if not nostartup:
616 e5b7c4ca Iustin Pop
      ops.append(opcodes.OpStartupInstance(instance_name=instance_name,
617 e5b7c4ca Iustin Pop
                                           force=False))
618 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
619 e5b7c4ca Iustin Pop
620 e5b7c4ca Iustin Pop
621 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
622 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
623 4c98b915 Michael Hanselmann

624 4c98b915 Michael Hanselmann
  """
625 4c98b915 Michael Hanselmann
  def POST(self):
626 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
627 4c98b915 Michael Hanselmann

628 4c98b915 Michael Hanselmann
    """
629 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
630 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
631 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
632 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
633 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
634 4c98b915 Michael Hanselmann
635 4c98b915 Michael Hanselmann
    if raw_disks:
636 4c98b915 Michael Hanselmann
      try:
637 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
638 4c98b915 Michael Hanselmann
      except ValueError, err:
639 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
640 4c98b915 Michael Hanselmann
    else:
641 4c98b915 Michael Hanselmann
      disks = []
642 4c98b915 Michael Hanselmann
643 4c98b915 Michael Hanselmann
    op = opcodes.OpReplaceDisks(instance_name=instance_name,
644 4c98b915 Michael Hanselmann
                                remote_node=remote_node,
645 4c98b915 Michael Hanselmann
                                mode=mode,
646 4c98b915 Michael Hanselmann
                                disks=disks,
647 4c98b915 Michael Hanselmann
                                iallocator=iallocator)
648 4c98b915 Michael Hanselmann
649 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
650 4c98b915 Michael Hanselmann
651 4c98b915 Michael Hanselmann
652 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
653 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
654 2197b66f René Nussbaumer

655 2197b66f René Nussbaumer
  """
656 2197b66f René Nussbaumer
  def PUT(self):
657 2197b66f René Nussbaumer
    """Activate disks for an instance.
658 2197b66f René Nussbaumer

659 2197b66f René Nussbaumer
    The URI might contain ignore_size to ignore current recorded size.
660 2197b66f René Nussbaumer

661 2197b66f René Nussbaumer
    """
662 2197b66f René Nussbaumer
    instance_name = self.items[0]
663 2197b66f René Nussbaumer
    ignore_size = bool(self._checkIntVariable('ignore_size'))
664 2197b66f René Nussbaumer
665 2197b66f René Nussbaumer
    op = opcodes.OpActivateInstanceDisks(instance_name=instance_name,
666 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
667 2197b66f René Nussbaumer
668 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
669 2197b66f René Nussbaumer
670 2197b66f René Nussbaumer
671 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
672 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
673 0a37de5f René Nussbaumer

674 0a37de5f René Nussbaumer
  """
675 0a37de5f René Nussbaumer
  def PUT(self):
676 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
677 0a37de5f René Nussbaumer

678 0a37de5f René Nussbaumer
    """
679 0a37de5f René Nussbaumer
    instance_name = self.items[0]
680 0a37de5f René Nussbaumer
681 0a37de5f René Nussbaumer
    op = opcodes.OpDeActivateInstanceDisks(instance_name=instance_name)
682 0a37de5f René Nussbaumer
683 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
684 0a37de5f René Nussbaumer
685 0a37de5f René Nussbaumer
686 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
687 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
688 441e7cfd Oleksiy Mishchenko

689 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
690 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
691 441e7cfd Oleksiy Mishchenko

692 441e7cfd Oleksiy Mishchenko
  """
693 7a6b9510 Iustin Pop
  TAG_LEVEL = None
694 18cb43a2 Oleksiy Mishchenko
695 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
696 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
697 18cb43a2 Oleksiy Mishchenko

698 18cb43a2 Oleksiy Mishchenko
    We have to override the default to sort out cluster naming case.
699 18cb43a2 Oleksiy Mishchenko

700 18cb43a2 Oleksiy Mishchenko
    """
701 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
702 18cb43a2 Oleksiy Mishchenko
703 18cb43a2 Oleksiy Mishchenko
    if self.TAG_LEVEL != constants.TAG_CLUSTER:
704 18cb43a2 Oleksiy Mishchenko
      self.name = items[0]
705 18cb43a2 Oleksiy Mishchenko
    else:
706 18cb43a2 Oleksiy Mishchenko
      self.name = ""
707 441e7cfd Oleksiy Mishchenko
708 441e7cfd Oleksiy Mishchenko
  def GET(self):
709 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
710 441e7cfd Oleksiy Mishchenko

711 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
712 441e7cfd Oleksiy Mishchenko

713 441e7cfd Oleksiy Mishchenko
    """
714 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
715 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
716 441e7cfd Oleksiy Mishchenko
717 21f04e5e Oleksiy Mishchenko
  def PUT(self):
718 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
719 441e7cfd Oleksiy Mishchenko

720 c41eea6e Iustin Pop
    The request as a list of strings should be PUT to this URI. And
721 c41eea6e Iustin Pop
    you'll have back a job id.
722 441e7cfd Oleksiy Mishchenko

723 441e7cfd Oleksiy Mishchenko
    """
724 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
725 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
726 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
727 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
728 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
729 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
730 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
731 15fd9fd5 Oleksiy Mishchenko
732 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
733 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
734 15fd9fd5 Oleksiy Mishchenko

735 18cb43a2 Oleksiy Mishchenko
    In order to delete a set of tags, the DELETE
736 c41eea6e Iustin Pop
    request should be addressed to URI like:
737 18cb43a2 Oleksiy Mishchenko
    /tags?tag=[tag]&tag=[tag]
738 15fd9fd5 Oleksiy Mishchenko

739 15fd9fd5 Oleksiy Mishchenko
    """
740 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
741 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
742 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
743 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
744 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
745 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
746 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
747 6f59b964 Iustin Pop
                                 name=self.name,
748 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
749 18cb43a2 Oleksiy Mishchenko
750 18cb43a2 Oleksiy Mishchenko
751 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
752 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
753 18cb43a2 Oleksiy Mishchenko

754 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
755 18cb43a2 Oleksiy Mishchenko

756 18cb43a2 Oleksiy Mishchenko
  """
757 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
758 18cb43a2 Oleksiy Mishchenko
759 18cb43a2 Oleksiy Mishchenko
760 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
761 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
762 18cb43a2 Oleksiy Mishchenko

763 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
764 18cb43a2 Oleksiy Mishchenko

765 18cb43a2 Oleksiy Mishchenko
  """
766 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
767 18cb43a2 Oleksiy Mishchenko
768 18cb43a2 Oleksiy Mishchenko
769 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
770 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
771 18cb43a2 Oleksiy Mishchenko

772 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
773 18cb43a2 Oleksiy Mishchenko

774 18cb43a2 Oleksiy Mishchenko
  """
775 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER