Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ f3c1a70c

History | View | Annotate | Download (37 kB)

1 10b207d4 Oleksiy Mishchenko
#
2 10b207d4 Oleksiy Mishchenko
#
3 10b207d4 Oleksiy Mishchenko
4 4ff922a2 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 f3c1a70c Michael Hanselmann
"""Remote API resource implementations.
23 10b207d4 Oleksiy Mishchenko

24 f3c1a70c Michael Hanselmann
PUT or POST?
25 f3c1a70c Michael Hanselmann
============
26 88394aa7 René Nussbaumer

27 f3c1a70c Michael Hanselmann
According to RFC2616 the main difference between PUT and POST is that
28 f3c1a70c Michael Hanselmann
POST can create new resources but PUT can only create the resource the
29 f3c1a70c Michael Hanselmann
URI was pointing to on the PUT request.
30 88394aa7 René Nussbaumer

31 f3c1a70c Michael Hanselmann
In the context of this module POST on ``/2/instances`` to chance an existing
32 f3c1a70c Michael Hanselmann
entity is legitimate, while PUT would not be. PUT creates a new entity (e.g. a
33 f3c1a70c Michael Hanselmann
new instance) with a name specified in the request.
34 88394aa7 René Nussbaumer

35 f3c1a70c Michael Hanselmann
Quoting from RFC2616, section 9.6:
36 f3c1a70c Michael Hanselmann

37 f3c1a70c Michael Hanselmann
  The fundamental difference between the POST and PUT requests is reflected in
38 f3c1a70c Michael Hanselmann
  the different meaning of the Request-URI. The URI in a POST request
39 f3c1a70c Michael Hanselmann
  identifies the resource that will handle the enclosed entity. That resource
40 f3c1a70c Michael Hanselmann
  might be a data-accepting process, a gateway to some other protocol, or a
41 f3c1a70c Michael Hanselmann
  separate entity that accepts annotations. In contrast, the URI in a PUT
42 f3c1a70c Michael Hanselmann
  request identifies the entity enclosed with the request -- the user agent
43 f3c1a70c Michael Hanselmann
  knows what URI is intended and the server MUST NOT attempt to apply the
44 f3c1a70c Michael Hanselmann
  request to some other resource. If the server desires that the request be
45 f3c1a70c Michael Hanselmann
  applied to a different URI, it MUST send a 301 (Moved Permanently) response;
46 f3c1a70c Michael Hanselmann
  the user agent MAY then make its own decision regarding whether or not to
47 f3c1a70c Michael Hanselmann
  redirect the request.
48 f3c1a70c Michael Hanselmann

49 f3c1a70c Michael Hanselmann
So when adding new methods, if they are operating on the URI entity itself,
50 f3c1a70c Michael Hanselmann
PUT should be prefered over POST.
51 88394aa7 René Nussbaumer

52 10b207d4 Oleksiy Mishchenko
"""
53 10b207d4 Oleksiy Mishchenko
54 fe267188 Iustin Pop
# pylint: disable-msg=C0103
55 fe267188 Iustin Pop
56 fe267188 Iustin Pop
# C0103: Invalid name, since the R_* names are not conforming
57 fe267188 Iustin Pop
58 59b4eeef Iustin Pop
from ganeti import opcodes
59 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
60 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
61 59b4eeef Iustin Pop
from ganeti import cli
62 8381fa2d Michael Hanselmann
from ganeti import rapi
63 d1c172de Michael Hanselmann
from ganeti import ht
64 e987f166 Michael Hanselmann
from ganeti import compat
65 38206f3c Iustin Pop
from ganeti.rapi import baserlib
66 10b207d4 Oleksiy Mishchenko
67 4e5a68f8 Oleksiy Mishchenko
68 7118a0df Iustin Pop
_COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
69 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
70 9031ee8e Iustin Pop
            "pnode", "snodes",
71 9031ee8e Iustin Pop
            "disk_template",
72 82e186f8 Michael Hanselmann
            "nic.ips", "nic.macs", "nic.modes", "nic.links", "nic.bridges",
73 a8b16c4e Tim Boring
            "network_port",
74 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
75 a5b9d725 Iustin Pop
            "beparams", "hvparams",
76 4ea3de4e Balazs Lecz
            "oper_state", "oper_ram", "oper_vcpus", "status",
77 90224407 Iustin Pop
            "custom_hvparams", "custom_beparams", "custom_nicparams",
78 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
79 9031ee8e Iustin Pop
80 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
81 9031ee8e Iustin Pop
            "dtotal", "dfree",
82 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
83 7118a0df Iustin Pop
            "pinst_cnt", "sinst_cnt",
84 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
85 7118a0df Iustin Pop
            "pip", "sip", "role",
86 93962b80 Iustin Pop
            "pinst_list", "sinst_list",
87 c190e817 Iustin Pop
            "master_capable", "vm_capable",
88 fd254195 Iustin Pop
            "group.uuid",
89 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
90 4e5a68f8 Oleksiy Mishchenko
91 f4e86448 Michael Hanselmann
G_FIELDS = [
92 f4e86448 Michael Hanselmann
  "alloc_policy",
93 f4e86448 Michael Hanselmann
  "name",
94 f4e86448 Michael Hanselmann
  "node_cnt",
95 f4e86448 Michael Hanselmann
  "node_list",
96 f4e86448 Michael Hanselmann
  ] + _COMMON_FIELDS
97 0897dc97 Adeodato Simo
98 bd7b2070 Michael Hanselmann
J_FIELDS_BULK = [
99 e987f166 Michael Hanselmann
  "id", "ops", "status", "summary",
100 bd7b2070 Michael Hanselmann
  "opstatus",
101 e987f166 Michael Hanselmann
  "received_ts", "start_ts", "end_ts",
102 e987f166 Michael Hanselmann
  ]
103 e987f166 Michael Hanselmann
104 bd7b2070 Michael Hanselmann
J_FIELDS = J_FIELDS_BULK + [
105 bd7b2070 Michael Hanselmann
  "oplog",
106 bd7b2070 Michael Hanselmann
  "opresult",
107 bd7b2070 Michael Hanselmann
  ]
108 bd7b2070 Michael Hanselmann
109 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
110 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
111 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
112 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
113 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
114 64dae8fc Michael Hanselmann
115 64dae8fc Michael Hanselmann
_NR_MAP = {
116 1e28e3b8 Michael Hanselmann
  constants.NR_MASTER: _NR_MASTER,
117 1e28e3b8 Michael Hanselmann
  constants.NR_MCANDIDATE: _NR_MASTER_CANDIATE,
118 1e28e3b8 Michael Hanselmann
  constants.NR_DRAINED: _NR_DRAINED,
119 1e28e3b8 Michael Hanselmann
  constants.NR_OFFLINE: _NR_OFFLINE,
120 1e28e3b8 Michael Hanselmann
  constants.NR_REGULAR: _NR_REGULAR,
121 64dae8fc Michael Hanselmann
  }
122 64dae8fc Michael Hanselmann
123 1e28e3b8 Michael Hanselmann
assert frozenset(_NR_MAP.keys()) == constants.NR_ALL
124 1e28e3b8 Michael Hanselmann
125 d975f482 Michael Hanselmann
# Request data version field
126 d975f482 Michael Hanselmann
_REQ_DATA_VERSION = "__version__"
127 d975f482 Michael Hanselmann
128 6395cebb Michael Hanselmann
# Feature string for instance creation request data version 1
129 6395cebb Michael Hanselmann
_INST_CREATE_REQV1 = "instance-create-reqv1"
130 6395cebb Michael Hanselmann
131 c744425f Michael Hanselmann
# Feature string for instance reinstall request version 1
132 c744425f Michael Hanselmann
_INST_REINSTALL_REQV1 = "instance-reinstall-reqv1"
133 c744425f Michael Hanselmann
134 b7a1c816 Michael Hanselmann
# Feature string for node migration version 1
135 b7a1c816 Michael Hanselmann
_NODE_MIGRATE_REQV1 = "node-migrate-reqv1"
136 b7a1c816 Michael Hanselmann
137 de40437a Michael Hanselmann
# Feature string for node evacuation with LU-generated jobs
138 de40437a Michael Hanselmann
_NODE_EVAC_RES1 = "node-evac-res1"
139 de40437a Michael Hanselmann
140 b4fcee5b Michael Hanselmann
ALL_FEATURES = frozenset([
141 b4fcee5b Michael Hanselmann
  _INST_CREATE_REQV1,
142 b4fcee5b Michael Hanselmann
  _INST_REINSTALL_REQV1,
143 b4fcee5b Michael Hanselmann
  _NODE_MIGRATE_REQV1,
144 b4fcee5b Michael Hanselmann
  _NODE_EVAC_RES1,
145 b4fcee5b Michael Hanselmann
  ])
146 b4fcee5b Michael Hanselmann
147 793a8f7c Michael Hanselmann
# Timeout for /2/jobs/[job_id]/wait. Gives job up to 10 seconds to change.
148 793a8f7c Michael Hanselmann
_WFJC_TIMEOUT = 10
149 793a8f7c Michael Hanselmann
150 4e5a68f8 Oleksiy Mishchenko
151 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
152 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
153 4e5a68f8 Oleksiy Mishchenko

154 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
155 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
156 4e5a68f8 Oleksiy Mishchenko

157 4e5a68f8 Oleksiy Mishchenko
  """
158 7e950d31 Iustin Pop
  @staticmethod
159 7e950d31 Iustin Pop
  def GET():
160 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
161 4e5a68f8 Oleksiy Mishchenko

162 4e5a68f8 Oleksiy Mishchenko
    """
163 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
164 4e5a68f8 Oleksiy Mishchenko
165 4e5a68f8 Oleksiy Mishchenko
166 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
167 b58a4d16 Michael Hanselmann
  """/2/info resource.
168 4e5a68f8 Oleksiy Mishchenko

169 4e5a68f8 Oleksiy Mishchenko
  """
170 7e950d31 Iustin Pop
  @staticmethod
171 7e950d31 Iustin Pop
  def GET():
172 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
173 4e5a68f8 Oleksiy Mishchenko

174 4e5a68f8 Oleksiy Mishchenko
    """
175 59b4eeef Iustin Pop
    client = baserlib.GetClient()
176 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
177 4e5a68f8 Oleksiy Mishchenko
178 4e5a68f8 Oleksiy Mishchenko
179 7eac4a4d Michael Hanselmann
class R_2_features(baserlib.R_Generic):
180 7eac4a4d Michael Hanselmann
  """/2/features resource.
181 7eac4a4d Michael Hanselmann

182 7eac4a4d Michael Hanselmann
  """
183 7eac4a4d Michael Hanselmann
  @staticmethod
184 7eac4a4d Michael Hanselmann
  def GET():
185 7eac4a4d Michael Hanselmann
    """Returns list of optional RAPI features implemented.
186 7eac4a4d Michael Hanselmann

187 7eac4a4d Michael Hanselmann
    """
188 b4fcee5b Michael Hanselmann
    return list(ALL_FEATURES)
189 7eac4a4d Michael Hanselmann
190 7eac4a4d Michael Hanselmann
191 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
192 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
193 4e5a68f8 Oleksiy Mishchenko

194 4e5a68f8 Oleksiy Mishchenko
  """
195 7e950d31 Iustin Pop
  @staticmethod
196 7e950d31 Iustin Pop
  def GET():
197 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
198 4e5a68f8 Oleksiy Mishchenko

199 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
200 4e5a68f8 Oleksiy Mishchenko

201 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
202 4e5a68f8 Oleksiy Mishchenko

203 4e5a68f8 Oleksiy Mishchenko
    """
204 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
205 da2d02e7 Iustin Pop
    op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[])
206 59b4eeef Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
207 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
208 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
209 59b4eeef Iustin Pop
    diagnose_data = result[0]
210 4e5a68f8 Oleksiy Mishchenko
211 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
212 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
213 4e5a68f8 Oleksiy Mishchenko
214 e3ac208c Guido Trotter
    os_names = []
215 d22dfef7 Iustin Pop
    for (name, variants) in diagnose_data:
216 d22dfef7 Iustin Pop
      os_names.extend(cli.CalculateOSNames(name, variants))
217 e3ac208c Guido Trotter
218 e3ac208c Guido Trotter
    return os_names
219 51ee2f49 Oleksiy Mishchenko
220 10b207d4 Oleksiy Mishchenko
221 508e9b20 Michael Hanselmann
class R_2_redist_config(baserlib.R_Generic):
222 508e9b20 Michael Hanselmann
  """/2/redistribute-config resource.
223 508e9b20 Michael Hanselmann

224 508e9b20 Michael Hanselmann
  """
225 7e950d31 Iustin Pop
  @staticmethod
226 7e950d31 Iustin Pop
  def PUT():
227 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
228 508e9b20 Michael Hanselmann

229 508e9b20 Michael Hanselmann
    """
230 d1240007 Iustin Pop
    return baserlib.SubmitJob([opcodes.OpClusterRedistConf()])
231 508e9b20 Michael Hanselmann
232 508e9b20 Michael Hanselmann
233 62e999a5 Michael Hanselmann
class R_2_cluster_modify(baserlib.R_Generic):
234 62e999a5 Michael Hanselmann
  """/2/modify resource.
235 62e999a5 Michael Hanselmann

236 62e999a5 Michael Hanselmann
  """
237 62e999a5 Michael Hanselmann
  def PUT(self):
238 62e999a5 Michael Hanselmann
    """Modifies cluster parameters.
239 62e999a5 Michael Hanselmann

240 62e999a5 Michael Hanselmann
    @return: a job id
241 62e999a5 Michael Hanselmann

242 62e999a5 Michael Hanselmann
    """
243 a6682fdc Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpClusterSetParams, self.request_body,
244 62e999a5 Michael Hanselmann
                             None)
245 62e999a5 Michael Hanselmann
246 62e999a5 Michael Hanselmann
    return baserlib.SubmitJob([op])
247 62e999a5 Michael Hanselmann
248 62e999a5 Michael Hanselmann
249 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
250 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
251 10b207d4 Oleksiy Mishchenko

252 10b207d4 Oleksiy Mishchenko
  """
253 e987f166 Michael Hanselmann
  def GET(self):
254 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
255 10b207d4 Oleksiy Mishchenko

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

258 10b207d4 Oleksiy Mishchenko
    """
259 e987f166 Michael Hanselmann
    client = baserlib.GetClient()
260 e987f166 Michael Hanselmann
261 e987f166 Michael Hanselmann
    if self.useBulk():
262 bd7b2070 Michael Hanselmann
      bulkdata = client.QueryJobs(None, J_FIELDS_BULK)
263 bd7b2070 Michael Hanselmann
      return baserlib.MapBulkFields(bulkdata, J_FIELDS_BULK)
264 e987f166 Michael Hanselmann
    else:
265 e987f166 Michael Hanselmann
      jobdata = map(compat.fst, client.QueryJobs(None, ["id"]))
266 e987f166 Michael Hanselmann
      return baserlib.BuildUriList(jobdata, "/2/jobs/%s",
267 e987f166 Michael Hanselmann
                                   uri_fields=("id", "uri"))
268 10b207d4 Oleksiy Mishchenko
269 10b207d4 Oleksiy Mishchenko
270 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
271 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
272 10b207d4 Oleksiy Mishchenko

273 10b207d4 Oleksiy Mishchenko
  """
274 10b207d4 Oleksiy Mishchenko
  def GET(self):
275 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
276 10b207d4 Oleksiy Mishchenko

277 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
278 c41eea6e Iustin Pop
        The result includes:
279 c41eea6e Iustin Pop
            - id: job ID as a number
280 c41eea6e Iustin Pop
            - status: current job status as a string
281 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
282 c41eea6e Iustin Pop
              opcodes in the job
283 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
284 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
285 38206f3c Iustin Pop

286 10b207d4 Oleksiy Mishchenko
    """
287 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
288 e987f166 Michael Hanselmann
    result = baserlib.GetClient().QueryJobs([job_id, ], J_FIELDS)[0]
289 ee69c97f Iustin Pop
    if result is None:
290 ee69c97f Iustin Pop
      raise http.HttpNotFound()
291 e987f166 Michael Hanselmann
    return baserlib.MapFields(J_FIELDS, result)
292 10b207d4 Oleksiy Mishchenko
293 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
294 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
295 c7f5f338 Oleksiy Mishchenko

296 c7f5f338 Oleksiy Mishchenko
    """
297 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
298 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
299 c7f5f338 Oleksiy Mishchenko
    return result
300 c7f5f338 Oleksiy Mishchenko
301 10b207d4 Oleksiy Mishchenko
302 793a8f7c Michael Hanselmann
class R_2_jobs_id_wait(baserlib.R_Generic):
303 793a8f7c Michael Hanselmann
  """/2/jobs/[job_id]/wait resource.
304 793a8f7c Michael Hanselmann

305 793a8f7c Michael Hanselmann
  """
306 793a8f7c Michael Hanselmann
  # WaitForJobChange provides access to sensitive information and blocks
307 793a8f7c Michael Hanselmann
  # machine resources (it's a blocking RAPI call), hence restricting access.
308 793a8f7c Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
309 793a8f7c Michael Hanselmann
310 793a8f7c Michael Hanselmann
  def GET(self):
311 793a8f7c Michael Hanselmann
    """Waits for job changes.
312 793a8f7c Michael Hanselmann

313 793a8f7c Michael Hanselmann
    """
314 793a8f7c Michael Hanselmann
    job_id = self.items[0]
315 793a8f7c Michael Hanselmann
316 793a8f7c Michael Hanselmann
    fields = self.getBodyParameter("fields")
317 793a8f7c Michael Hanselmann
    prev_job_info = self.getBodyParameter("previous_job_info", None)
318 793a8f7c Michael Hanselmann
    prev_log_serial = self.getBodyParameter("previous_log_serial", None)
319 793a8f7c Michael Hanselmann
320 793a8f7c Michael Hanselmann
    if not isinstance(fields, list):
321 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'fields' parameter should be a list")
322 793a8f7c Michael Hanselmann
323 793a8f7c Michael Hanselmann
    if not (prev_job_info is None or isinstance(prev_job_info, list)):
324 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_job_info' parameter should"
325 793a8f7c Michael Hanselmann
                                " be a list")
326 793a8f7c Michael Hanselmann
327 793a8f7c Michael Hanselmann
    if not (prev_log_serial is None or
328 793a8f7c Michael Hanselmann
            isinstance(prev_log_serial, (int, long))):
329 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_log_serial' parameter should"
330 793a8f7c Michael Hanselmann
                                " be a number")
331 793a8f7c Michael Hanselmann
332 793a8f7c Michael Hanselmann
    client = baserlib.GetClient()
333 793a8f7c Michael Hanselmann
    result = client.WaitForJobChangeOnce(job_id, fields,
334 793a8f7c Michael Hanselmann
                                         prev_job_info, prev_log_serial,
335 793a8f7c Michael Hanselmann
                                         timeout=_WFJC_TIMEOUT)
336 793a8f7c Michael Hanselmann
    if not result:
337 793a8f7c Michael Hanselmann
      raise http.HttpNotFound()
338 793a8f7c Michael Hanselmann
339 793a8f7c Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
340 793a8f7c Michael Hanselmann
      # No changes
341 793a8f7c Michael Hanselmann
      return None
342 793a8f7c Michael Hanselmann
343 793a8f7c Michael Hanselmann
    (job_info, log_entries) = result
344 793a8f7c Michael Hanselmann
345 793a8f7c Michael Hanselmann
    return {
346 793a8f7c Michael Hanselmann
      "job_info": job_info,
347 793a8f7c Michael Hanselmann
      "log_entries": log_entries,
348 793a8f7c Michael Hanselmann
      }
349 793a8f7c Michael Hanselmann
350 793a8f7c Michael Hanselmann
351 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
352 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
353 10b207d4 Oleksiy Mishchenko

354 10b207d4 Oleksiy Mishchenko
  """
355 10b207d4 Oleksiy Mishchenko
  def GET(self):
356 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
357 38206f3c Iustin Pop

358 10b207d4 Oleksiy Mishchenko
    """
359 59b4eeef Iustin Pop
    client = baserlib.GetClient()
360 38206f3c Iustin Pop
361 3d103742 Iustin Pop
    if self.useBulk():
362 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
363 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
364 9031ee8e Iustin Pop
    else:
365 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
366 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
367 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
368 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
369 441e7cfd Oleksiy Mishchenko
370 441e7cfd Oleksiy Mishchenko
371 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
372 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name] resource.
373 028c6b76 Oleksiy Mishchenko

374 028c6b76 Oleksiy Mishchenko
  """
375 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
376 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
377 4e5a68f8 Oleksiy Mishchenko

378 4e5a68f8 Oleksiy Mishchenko
    """
379 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
380 59b4eeef Iustin Pop
    client = baserlib.GetClient()
381 e8ebbd2b Michael Hanselmann
382 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryNodes,
383 e8ebbd2b Michael Hanselmann
                                            names=[node_name], fields=N_FIELDS,
384 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
385 4e5a68f8 Oleksiy Mishchenko
386 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
387 028c6b76 Oleksiy Mishchenko
388 028c6b76 Oleksiy Mishchenko
389 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
390 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
391 64dae8fc Michael Hanselmann

392 64dae8fc Michael Hanselmann
  """
393 64dae8fc Michael Hanselmann
  def GET(self):
394 64dae8fc Michael Hanselmann
    """Returns the current node role.
395 64dae8fc Michael Hanselmann

396 64dae8fc Michael Hanselmann
    @return: Node role
397 64dae8fc Michael Hanselmann

398 64dae8fc Michael Hanselmann
    """
399 64dae8fc Michael Hanselmann
    node_name = self.items[0]
400 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
401 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
402 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
403 64dae8fc Michael Hanselmann
404 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
405 64dae8fc Michael Hanselmann
406 64dae8fc Michael Hanselmann
  def PUT(self):
407 64dae8fc Michael Hanselmann
    """Sets the node role.
408 64dae8fc Michael Hanselmann

409 64dae8fc Michael Hanselmann
    @return: a job id
410 64dae8fc Michael Hanselmann

411 64dae8fc Michael Hanselmann
    """
412 627ad739 Michael Hanselmann
    if not isinstance(self.request_body, basestring):
413 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
414 64dae8fc Michael Hanselmann
415 64dae8fc Michael Hanselmann
    node_name = self.items[0]
416 627ad739 Michael Hanselmann
    role = self.request_body
417 64dae8fc Michael Hanselmann
418 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
419 64dae8fc Michael Hanselmann
      candidate = False
420 64dae8fc Michael Hanselmann
      offline = False
421 64dae8fc Michael Hanselmann
      drained = False
422 64dae8fc Michael Hanselmann
423 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
424 64dae8fc Michael Hanselmann
      candidate = True
425 64dae8fc Michael Hanselmann
      offline = drained = None
426 64dae8fc Michael Hanselmann
427 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
428 64dae8fc Michael Hanselmann
      drained = True
429 64dae8fc Michael Hanselmann
      candidate = offline = None
430 64dae8fc Michael Hanselmann
431 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
432 64dae8fc Michael Hanselmann
      offline = True
433 64dae8fc Michael Hanselmann
      candidate = drained = None
434 64dae8fc Michael Hanselmann
435 64dae8fc Michael Hanselmann
    else:
436 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
437 64dae8fc Michael Hanselmann
438 f13973c4 Iustin Pop
    op = opcodes.OpNodeSetParams(node_name=node_name,
439 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
440 64dae8fc Michael Hanselmann
                                 offline=offline,
441 64dae8fc Michael Hanselmann
                                 drained=drained,
442 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
443 64dae8fc Michael Hanselmann
444 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
445 64dae8fc Michael Hanselmann
446 64dae8fc Michael Hanselmann
447 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
448 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
449 73452f12 Michael Hanselmann

450 73452f12 Michael Hanselmann
  """
451 73452f12 Michael Hanselmann
  def POST(self):
452 de40437a Michael Hanselmann
    """Evacuate all instances off a node.
453 73452f12 Michael Hanselmann

454 73452f12 Michael Hanselmann
    """
455 de40437a Michael Hanselmann
    op = baserlib.FillOpcode(opcodes.OpNodeEvacuate, self.request_body, {
456 de40437a Michael Hanselmann
      "node_name": self.items[0],
457 de40437a Michael Hanselmann
      "dry_run": self.dryRun(),
458 de40437a Michael Hanselmann
      })
459 941b9309 Iustin Pop
460 de40437a Michael Hanselmann
    return baserlib.SubmitJob([op])
461 73452f12 Michael Hanselmann
462 73452f12 Michael Hanselmann
463 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
464 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
465 1c482bab Michael Hanselmann

466 1c482bab Michael Hanselmann
  """
467 1c482bab Michael Hanselmann
  def POST(self):
468 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
469 1c482bab Michael Hanselmann

470 1c482bab Michael Hanselmann
    """
471 1c482bab Michael Hanselmann
    node_name = self.items[0]
472 1c482bab Michael Hanselmann
473 b7a1c816 Michael Hanselmann
    if self.queryargs:
474 b7a1c816 Michael Hanselmann
      # Support old-style requests
475 b7a1c816 Michael Hanselmann
      if "live" in self.queryargs and "mode" in self.queryargs:
476 b7a1c816 Michael Hanselmann
        raise http.HttpBadRequest("Only one of 'live' and 'mode' should"
477 b7a1c816 Michael Hanselmann
                                  " be passed")
478 b7a1c816 Michael Hanselmann
479 b7a1c816 Michael Hanselmann
      if "live" in self.queryargs:
480 b7a1c816 Michael Hanselmann
        if self._checkIntVariable("live", default=1):
481 b7a1c816 Michael Hanselmann
          mode = constants.HT_MIGRATION_LIVE
482 b7a1c816 Michael Hanselmann
        else:
483 b7a1c816 Michael Hanselmann
          mode = constants.HT_MIGRATION_NONLIVE
484 52194140 Iustin Pop
      else:
485 b7a1c816 Michael Hanselmann
        mode = self._checkStringVariable("mode", default=None)
486 b7a1c816 Michael Hanselmann
487 b7a1c816 Michael Hanselmann
      data = {
488 b7a1c816 Michael Hanselmann
        "mode": mode,
489 b7a1c816 Michael Hanselmann
        }
490 52194140 Iustin Pop
    else:
491 b7a1c816 Michael Hanselmann
      data = self.request_body
492 52194140 Iustin Pop
493 b7a1c816 Michael Hanselmann
    op = baserlib.FillOpcode(opcodes.OpNodeMigrate, data, {
494 b7a1c816 Michael Hanselmann
      "node_name": node_name,
495 b7a1c816 Michael Hanselmann
      })
496 1c482bab Michael Hanselmann
497 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
498 1c482bab Michael Hanselmann
499 1c482bab Michael Hanselmann
500 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
501 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage resource.
502 7a95a954 Michael Hanselmann

503 7a95a954 Michael Hanselmann
  """
504 ad8d0595 Iustin Pop
  # LUNodeQueryStorage acquires locks, hence restricting access to GET
505 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
506 7a95a954 Michael Hanselmann
507 7a95a954 Michael Hanselmann
  def GET(self):
508 7a95a954 Michael Hanselmann
    node_name = self.items[0]
509 7a95a954 Michael Hanselmann
510 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
511 7a95a954 Michael Hanselmann
    if not storage_type:
512 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
513 7a95a954 Michael Hanselmann
                                " parameter")
514 7a95a954 Michael Hanselmann
515 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
516 7a95a954 Michael Hanselmann
    if not output_fields:
517 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
518 7a95a954 Michael Hanselmann
                                " parameter")
519 7a95a954 Michael Hanselmann
520 ad8d0595 Iustin Pop
    op = opcodes.OpNodeQueryStorage(nodes=[node_name],
521 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
522 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
523 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
524 7a95a954 Michael Hanselmann
525 7a95a954 Michael Hanselmann
526 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
527 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify resource.
528 1e82bc80 Michael Hanselmann

529 1e82bc80 Michael Hanselmann
  """
530 1e82bc80 Michael Hanselmann
  def PUT(self):
531 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
532 1e82bc80 Michael Hanselmann
533 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
534 1e82bc80 Michael Hanselmann
    if not storage_type:
535 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
536 1e82bc80 Michael Hanselmann
                                " parameter")
537 1e82bc80 Michael Hanselmann
538 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
539 1e82bc80 Michael Hanselmann
    if not name:
540 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
541 1e82bc80 Michael Hanselmann
                                " parameter")
542 1e82bc80 Michael Hanselmann
543 1e82bc80 Michael Hanselmann
    changes = {}
544 1e82bc80 Michael Hanselmann
545 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
546 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
547 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
548 1e82bc80 Michael Hanselmann
549 2cee4077 Iustin Pop
    op = opcodes.OpNodeModifyStorage(node_name=node_name,
550 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
551 1e82bc80 Michael Hanselmann
                                     name=name,
552 1e82bc80 Michael Hanselmann
                                     changes=changes)
553 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
554 1e82bc80 Michael Hanselmann
555 1e82bc80 Michael Hanselmann
556 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
557 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair resource.
558 723f4565 Michael Hanselmann

559 723f4565 Michael Hanselmann
  """
560 723f4565 Michael Hanselmann
  def PUT(self):
561 723f4565 Michael Hanselmann
    node_name = self.items[0]
562 723f4565 Michael Hanselmann
563 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
564 723f4565 Michael Hanselmann
    if not storage_type:
565 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
566 723f4565 Michael Hanselmann
                                " parameter")
567 723f4565 Michael Hanselmann
568 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
569 723f4565 Michael Hanselmann
    if not name:
570 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
571 723f4565 Michael Hanselmann
                                " parameter")
572 723f4565 Michael Hanselmann
573 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
574 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
575 723f4565 Michael Hanselmann
                                     name=name)
576 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
577 723f4565 Michael Hanselmann
578 723f4565 Michael Hanselmann
579 90e99856 Adeodato Simo
def _ParseCreateGroupRequest(data, dry_run):
580 90e99856 Adeodato Simo
  """Parses a request for creating a node group.
581 90e99856 Adeodato Simo

582 fabf1731 Iustin Pop
  @rtype: L{opcodes.OpGroupAdd}
583 90e99856 Adeodato Simo
  @return: Group creation opcode
584 90e99856 Adeodato Simo

585 90e99856 Adeodato Simo
  """
586 527fbde8 Michael Hanselmann
  override = {
587 527fbde8 Michael Hanselmann
    "dry_run": dry_run,
588 527fbde8 Michael Hanselmann
    }
589 90e99856 Adeodato Simo
590 527fbde8 Michael Hanselmann
  rename = {
591 527fbde8 Michael Hanselmann
    "name": "group_name",
592 527fbde8 Michael Hanselmann
    }
593 527fbde8 Michael Hanselmann
594 527fbde8 Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpGroupAdd, data, override,
595 527fbde8 Michael Hanselmann
                             rename=rename)
596 90e99856 Adeodato Simo
597 90e99856 Adeodato Simo
598 0897dc97 Adeodato Simo
class R_2_groups(baserlib.R_Generic):
599 0897dc97 Adeodato Simo
  """/2/groups resource.
600 0897dc97 Adeodato Simo

601 0897dc97 Adeodato Simo
  """
602 0897dc97 Adeodato Simo
  def GET(self):
603 0897dc97 Adeodato Simo
    """Returns a list of all node groups.
604 0897dc97 Adeodato Simo

605 0897dc97 Adeodato Simo
    """
606 0897dc97 Adeodato Simo
    client = baserlib.GetClient()
607 0897dc97 Adeodato Simo
608 0897dc97 Adeodato Simo
    if self.useBulk():
609 0897dc97 Adeodato Simo
      bulkdata = client.QueryGroups([], G_FIELDS, False)
610 0897dc97 Adeodato Simo
      return baserlib.MapBulkFields(bulkdata, G_FIELDS)
611 0897dc97 Adeodato Simo
    else:
612 0897dc97 Adeodato Simo
      data = client.QueryGroups([], ["name"], False)
613 0897dc97 Adeodato Simo
      groupnames = [row[0] for row in data]
614 0897dc97 Adeodato Simo
      return baserlib.BuildUriList(groupnames, "/2/groups/%s",
615 0897dc97 Adeodato Simo
                                   uri_fields=("name", "uri"))
616 0897dc97 Adeodato Simo
617 0dbaa9ca Adeodato Simo
  def POST(self):
618 0dbaa9ca Adeodato Simo
    """Create a node group.
619 0dbaa9ca Adeodato Simo

620 0dbaa9ca Adeodato Simo
    @return: a job id
621 0dbaa9ca Adeodato Simo

622 0dbaa9ca Adeodato Simo
    """
623 0dbaa9ca Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
624 90e99856 Adeodato Simo
    op = _ParseCreateGroupRequest(self.request_body, self.dryRun())
625 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
626 0dbaa9ca Adeodato Simo
627 0897dc97 Adeodato Simo
628 0897dc97 Adeodato Simo
class R_2_groups_name(baserlib.R_Generic):
629 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name] resource.
630 0897dc97 Adeodato Simo

631 0897dc97 Adeodato Simo
  """
632 0897dc97 Adeodato Simo
  def GET(self):
633 0897dc97 Adeodato Simo
    """Send information about a node group.
634 0897dc97 Adeodato Simo

635 0897dc97 Adeodato Simo
    """
636 0897dc97 Adeodato Simo
    group_name = self.items[0]
637 0897dc97 Adeodato Simo
    client = baserlib.GetClient()
638 0897dc97 Adeodato Simo
639 0897dc97 Adeodato Simo
    result = baserlib.HandleItemQueryErrors(client.QueryGroups,
640 0897dc97 Adeodato Simo
                                            names=[group_name], fields=G_FIELDS,
641 0897dc97 Adeodato Simo
                                            use_locking=self.useLocking())
642 0897dc97 Adeodato Simo
643 0897dc97 Adeodato Simo
    return baserlib.MapFields(G_FIELDS, result[0])
644 0897dc97 Adeodato Simo
645 0dbaa9ca Adeodato Simo
  def DELETE(self):
646 0dbaa9ca Adeodato Simo
    """Delete a node group.
647 0dbaa9ca Adeodato Simo

648 0dbaa9ca Adeodato Simo
    """
649 4d1baa51 Iustin Pop
    op = opcodes.OpGroupRemove(group_name=self.items[0],
650 0dbaa9ca Adeodato Simo
                               dry_run=bool(self.dryRun()))
651 0dbaa9ca Adeodato Simo
652 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
653 0dbaa9ca Adeodato Simo
654 0dbaa9ca Adeodato Simo
655 f18fab7d Adeodato Simo
def _ParseModifyGroupRequest(name, data):
656 f18fab7d Adeodato Simo
  """Parses a request for modifying a node group.
657 f18fab7d Adeodato Simo

658 7cbf74f0 Iustin Pop
  @rtype: L{opcodes.OpGroupSetParams}
659 f18fab7d Adeodato Simo
  @return: Group modify opcode
660 f18fab7d Adeodato Simo

661 f18fab7d Adeodato Simo
  """
662 df340fae Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpGroupSetParams, data, {
663 df340fae Michael Hanselmann
    "group_name": name,
664 df340fae Michael Hanselmann
    })
665 df340fae Michael Hanselmann
666 f18fab7d Adeodato Simo
667 f18fab7d Adeodato Simo
668 f18fab7d Adeodato Simo
class R_2_groups_name_modify(baserlib.R_Generic):
669 f18fab7d Adeodato Simo
  """/2/groups/[group_name]/modify resource.
670 f18fab7d Adeodato Simo

671 f18fab7d Adeodato Simo
  """
672 f18fab7d Adeodato Simo
  def PUT(self):
673 f18fab7d Adeodato Simo
    """Changes some parameters of node group.
674 f18fab7d Adeodato Simo

675 f18fab7d Adeodato Simo
    @return: a job id
676 f18fab7d Adeodato Simo

677 f18fab7d Adeodato Simo
    """
678 f18fab7d Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
679 f18fab7d Adeodato Simo
680 f18fab7d Adeodato Simo
    op = _ParseModifyGroupRequest(self.items[0], self.request_body)
681 f18fab7d Adeodato Simo
682 f18fab7d Adeodato Simo
    return baserlib.SubmitJob([op])
683 f18fab7d Adeodato Simo
684 f18fab7d Adeodato Simo
685 0dbaa9ca Adeodato Simo
def _ParseRenameGroupRequest(name, data, dry_run):
686 0dbaa9ca Adeodato Simo
  """Parses a request for renaming a node group.
687 0dbaa9ca Adeodato Simo

688 0dbaa9ca Adeodato Simo
  @type name: string
689 0dbaa9ca Adeodato Simo
  @param name: name of the node group to rename
690 0dbaa9ca Adeodato Simo
  @type data: dict
691 0dbaa9ca Adeodato Simo
  @param data: the body received by the rename request
692 0dbaa9ca Adeodato Simo
  @type dry_run: bool
693 0dbaa9ca Adeodato Simo
  @param dry_run: whether to perform a dry run
694 0dbaa9ca Adeodato Simo

695 a8173e82 Iustin Pop
  @rtype: L{opcodes.OpGroupRename}
696 0dbaa9ca Adeodato Simo
  @return: Node group rename opcode
697 0dbaa9ca Adeodato Simo

698 0dbaa9ca Adeodato Simo
  """
699 8a08be3b Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpGroupRename, data, {
700 8a08be3b Michael Hanselmann
    "group_name": name,
701 8a08be3b Michael Hanselmann
    "dry_run": dry_run,
702 8a08be3b Michael Hanselmann
    })
703 0dbaa9ca Adeodato Simo
704 0dbaa9ca Adeodato Simo
705 0dbaa9ca Adeodato Simo
class R_2_groups_name_rename(baserlib.R_Generic):
706 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name]/rename resource.
707 0dbaa9ca Adeodato Simo

708 0dbaa9ca Adeodato Simo
  """
709 0dbaa9ca Adeodato Simo
  def PUT(self):
710 0dbaa9ca Adeodato Simo
    """Changes the name of a node group.
711 0dbaa9ca Adeodato Simo

712 0dbaa9ca Adeodato Simo
    @return: a job id
713 0dbaa9ca Adeodato Simo

714 0dbaa9ca Adeodato Simo
    """
715 0dbaa9ca Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
716 0dbaa9ca Adeodato Simo
    op = _ParseRenameGroupRequest(self.items[0], self.request_body,
717 0dbaa9ca Adeodato Simo
                                  self.dryRun())
718 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
719 0897dc97 Adeodato Simo
720 0897dc97 Adeodato Simo
721 4245446f Adeodato Simo
class R_2_groups_name_assign_nodes(baserlib.R_Generic):
722 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name]/assign-nodes resource.
723 4245446f Adeodato Simo

724 4245446f Adeodato Simo
  """
725 4245446f Adeodato Simo
  def PUT(self):
726 4245446f Adeodato Simo
    """Assigns nodes to a group.
727 4245446f Adeodato Simo

728 4245446f Adeodato Simo
    @return: a job id
729 4245446f Adeodato Simo

730 4245446f Adeodato Simo
    """
731 934704ae Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpGroupAssignNodes, self.request_body, {
732 4245446f Adeodato Simo
      "group_name": self.items[0],
733 4245446f Adeodato Simo
      "dry_run": self.dryRun(),
734 4245446f Adeodato Simo
      "force": self.useForce(),
735 4245446f Adeodato Simo
      })
736 4245446f Adeodato Simo
737 4245446f Adeodato Simo
    return baserlib.SubmitJob([op])
738 4245446f Adeodato Simo
739 4245446f Adeodato Simo
740 6395cebb Michael Hanselmann
def _ParseInstanceCreateRequestVersion1(data, dry_run):
741 6395cebb Michael Hanselmann
  """Parses an instance creation request version 1.
742 6395cebb Michael Hanselmann

743 e1530b10 Iustin Pop
  @rtype: L{opcodes.OpInstanceCreate}
744 6395cebb Michael Hanselmann
  @return: Instance creation opcode
745 6395cebb Michael Hanselmann

746 6395cebb Michael Hanselmann
  """
747 526a662a Michael Hanselmann
  override = {
748 526a662a Michael Hanselmann
    "dry_run": dry_run,
749 526a662a Michael Hanselmann
    }
750 6395cebb Michael Hanselmann
751 526a662a Michael Hanselmann
  rename = {
752 526a662a Michael Hanselmann
    "os": "os_type",
753 526a662a Michael Hanselmann
    "name": "instance_name",
754 526a662a Michael Hanselmann
    }
755 526a662a Michael Hanselmann
756 526a662a Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpInstanceCreate, data, override,
757 526a662a Michael Hanselmann
                             rename=rename)
758 6395cebb Michael Hanselmann
759 6395cebb Michael Hanselmann
760 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
761 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
762 441e7cfd Oleksiy Mishchenko

763 441e7cfd Oleksiy Mishchenko
  """
764 441e7cfd Oleksiy Mishchenko
  def GET(self):
765 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
766 441e7cfd Oleksiy Mishchenko

767 441e7cfd Oleksiy Mishchenko
    """
768 59b4eeef Iustin Pop
    client = baserlib.GetClient()
769 441e7cfd Oleksiy Mishchenko
770 3d103742 Iustin Pop
    use_locking = self.useLocking()
771 3d103742 Iustin Pop
    if self.useBulk():
772 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
773 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
774 441e7cfd Oleksiy Mishchenko
    else:
775 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
776 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
777 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
778 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
779 441e7cfd Oleksiy Mishchenko
780 d975f482 Michael Hanselmann
  def POST(self):
781 d975f482 Michael Hanselmann
    """Create an instance.
782 d975f482 Michael Hanselmann

783 d975f482 Michael Hanselmann
    @return: a job id
784 d975f482 Michael Hanselmann

785 d975f482 Michael Hanselmann
    """
786 1c54156d Luca Bigliardi
    if not isinstance(self.request_body, dict):
787 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
788 d975f482 Michael Hanselmann
789 d975f482 Michael Hanselmann
    # Default to request data version 0
790 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
791 d975f482 Michael Hanselmann
792 d975f482 Michael Hanselmann
    if data_version == 0:
793 3fd7f652 Michael Hanselmann
      raise http.HttpBadRequest("Instance creation request version 0 is no"
794 3fd7f652 Michael Hanselmann
                                " longer supported")
795 6395cebb Michael Hanselmann
    elif data_version == 1:
796 4b163794 Michael Hanselmann
      data = self.request_body.copy()
797 4b163794 Michael Hanselmann
      # Remove "__version__"
798 4b163794 Michael Hanselmann
      data.pop(_REQ_DATA_VERSION, None)
799 4b163794 Michael Hanselmann
      op = _ParseInstanceCreateRequestVersion1(data, self.dryRun())
800 d975f482 Michael Hanselmann
    else:
801 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
802 12eff9b9 Michael Hanselmann
                                data_version)
803 d975f482 Michael Hanselmann
804 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
805 2f7635f4 Oleksiy Mishchenko
806 441e7cfd Oleksiy Mishchenko
807 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
808 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name] resource.
809 028c6b76 Oleksiy Mishchenko

810 028c6b76 Oleksiy Mishchenko
  """
811 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
812 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
813 4e5a68f8 Oleksiy Mishchenko

814 4e5a68f8 Oleksiy Mishchenko
    """
815 59b4eeef Iustin Pop
    client = baserlib.GetClient()
816 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
817 e8ebbd2b Michael Hanselmann
818 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryInstances,
819 e8ebbd2b Michael Hanselmann
                                            names=[instance_name],
820 e8ebbd2b Michael Hanselmann
                                            fields=I_FIELDS,
821 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
822 4e5a68f8 Oleksiy Mishchenko
823 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
824 028c6b76 Oleksiy Mishchenko
825 6e99c5a0 Iustin Pop
  def DELETE(self):
826 6e99c5a0 Iustin Pop
    """Delete an instance.
827 6e99c5a0 Iustin Pop

828 6e99c5a0 Iustin Pop
    """
829 3cd2d4b1 Iustin Pop
    op = opcodes.OpInstanceRemove(instance_name=self.items[0],
830 6f59b964 Iustin Pop
                                  ignore_failures=False,
831 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
832 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
833 6e99c5a0 Iustin Pop
834 028c6b76 Oleksiy Mishchenko
835 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
836 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
837 d8260842 Michael Hanselmann

838 d8260842 Michael Hanselmann
  """
839 d8260842 Michael Hanselmann
  def GET(self):
840 d8260842 Michael Hanselmann
    """Request detailed instance information.
841 d8260842 Michael Hanselmann

842 d8260842 Michael Hanselmann
    """
843 d8260842 Michael Hanselmann
    instance_name = self.items[0]
844 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
845 d8260842 Michael Hanselmann
846 dc28c4e4 Iustin Pop
    op = opcodes.OpInstanceQueryData(instances=[instance_name],
847 d8260842 Michael Hanselmann
                                     static=static)
848 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
849 d8260842 Michael Hanselmann
850 d8260842 Michael Hanselmann
851 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
852 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
853 2276aa29 Oleksiy Mishchenko

854 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
855 2276aa29 Oleksiy Mishchenko

856 2276aa29 Oleksiy Mishchenko
  """
857 21f04e5e Oleksiy Mishchenko
  def POST(self):
858 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
859 2276aa29 Oleksiy Mishchenko

860 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
861 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
862 0c55c24b Oleksiy Mishchenko

863 2276aa29 Oleksiy Mishchenko
    """
864 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
865 d0c8c01d Iustin Pop
    reboot_type = self.queryargs.get("type",
866 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
867 d0c8c01d Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable("ignore_secondaries"))
868 90ab1a95 Iustin Pop
    op = opcodes.OpInstanceReboot(instance_name=instance_name,
869 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
870 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
871 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
872 2276aa29 Oleksiy Mishchenko
873 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
874 2276aa29 Oleksiy Mishchenko
875 2276aa29 Oleksiy Mishchenko
876 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
877 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
878 0c55c24b Oleksiy Mishchenko

879 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
880 0c55c24b Oleksiy Mishchenko

881 0c55c24b Oleksiy Mishchenko
  """
882 21f04e5e Oleksiy Mishchenko
  def PUT(self):
883 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
884 0c55c24b Oleksiy Mishchenko

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

888 0c55c24b Oleksiy Mishchenko
    """
889 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
890 d0c8c01d Iustin Pop
    force_startup = bool(self._checkIntVariable("force"))
891 d0c8c01d Iustin Pop
    no_remember = bool(self._checkIntVariable("no_remember"))
892 c873d91c Iustin Pop
    op = opcodes.OpInstanceStartup(instance_name=instance_name,
893 6f59b964 Iustin Pop
                                   force=force_startup,
894 2ba39b8f Iustin Pop
                                   dry_run=bool(self.dryRun()),
895 2ba39b8f Iustin Pop
                                   no_remember=no_remember)
896 0c55c24b Oleksiy Mishchenko
897 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
898 0c55c24b Oleksiy Mishchenko
899 0c55c24b Oleksiy Mishchenko
900 6aac5aef Iustin Pop
def _ParseShutdownInstanceRequest(name, data, dry_run, no_remember):
901 7fa310f6 René Nussbaumer
  """Parses a request for an instance shutdown.
902 7fa310f6 René Nussbaumer

903 7fa310f6 René Nussbaumer
  @rtype: L{opcodes.OpInstanceShutdown}
904 7fa310f6 René Nussbaumer
  @return: Instance shutdown opcode
905 7fa310f6 René Nussbaumer

906 7fa310f6 René Nussbaumer
  """
907 7fa310f6 René Nussbaumer
  return baserlib.FillOpcode(opcodes.OpInstanceShutdown, data, {
908 7fa310f6 René Nussbaumer
    "instance_name": name,
909 7fa310f6 René Nussbaumer
    "dry_run": dry_run,
910 6aac5aef Iustin Pop
    "no_remember": no_remember,
911 7fa310f6 René Nussbaumer
    })
912 7fa310f6 René Nussbaumer
913 7fa310f6 René Nussbaumer
914 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
915 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
916 0c55c24b Oleksiy Mishchenko

917 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
918 0c55c24b Oleksiy Mishchenko

919 0c55c24b Oleksiy Mishchenko
  """
920 21f04e5e Oleksiy Mishchenko
  def PUT(self):
921 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
922 0c55c24b Oleksiy Mishchenko

923 7fa310f6 René Nussbaumer
    @return: a job id
924 7fa310f6 René Nussbaumer

925 0c55c24b Oleksiy Mishchenko
    """
926 7fa310f6 René Nussbaumer
    baserlib.CheckType(self.request_body, dict, "Body contents")
927 7fa310f6 René Nussbaumer
928 d0c8c01d Iustin Pop
    no_remember = bool(self._checkIntVariable("no_remember"))
929 7fa310f6 René Nussbaumer
    op = _ParseShutdownInstanceRequest(self.items[0], self.request_body,
930 6aac5aef Iustin Pop
                                       bool(self.dryRun()), no_remember)
931 0c55c24b Oleksiy Mishchenko
932 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
933 0c55c24b Oleksiy Mishchenko
934 0c55c24b Oleksiy Mishchenko
935 c744425f Michael Hanselmann
def _ParseInstanceReinstallRequest(name, data):
936 c744425f Michael Hanselmann
  """Parses a request for reinstalling an instance.
937 c744425f Michael Hanselmann

938 c744425f Michael Hanselmann
  """
939 c744425f Michael Hanselmann
  if not isinstance(data, dict):
940 c744425f Michael Hanselmann
    raise http.HttpBadRequest("Invalid body contents, not a dictionary")
941 c744425f Michael Hanselmann
942 bd0807fe Guido Trotter
  ostype = baserlib.CheckParameter(data, "os", default=None)
943 c744425f Michael Hanselmann
  start = baserlib.CheckParameter(data, "start", exptype=bool,
944 c744425f Michael Hanselmann
                                  default=True)
945 c744425f Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default=None)
946 c744425f Michael Hanselmann
947 c744425f Michael Hanselmann
  ops = [
948 ee3e37a7 Iustin Pop
    opcodes.OpInstanceShutdown(instance_name=name),
949 5073fd8f Iustin Pop
    opcodes.OpInstanceReinstall(instance_name=name, os_type=ostype,
950 c744425f Michael Hanselmann
                                osparams=osparams),
951 c744425f Michael Hanselmann
    ]
952 c744425f Michael Hanselmann
953 c744425f Michael Hanselmann
  if start:
954 c873d91c Iustin Pop
    ops.append(opcodes.OpInstanceStartup(instance_name=name, force=False))
955 c744425f Michael Hanselmann
956 c744425f Michael Hanselmann
  return ops
957 c744425f Michael Hanselmann
958 c744425f Michael Hanselmann
959 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
960 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
961 e5b7c4ca Iustin Pop

962 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
963 e5b7c4ca Iustin Pop

964 e5b7c4ca Iustin Pop
  """
965 e5b7c4ca Iustin Pop
  def POST(self):
966 e5b7c4ca Iustin Pop
    """Reinstall an instance.
967 e5b7c4ca Iustin Pop

968 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
969 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
970 e5b7c4ca Iustin Pop
    automatically.
971 e5b7c4ca Iustin Pop

972 e5b7c4ca Iustin Pop
    """
973 c744425f Michael Hanselmann
    if self.request_body:
974 c744425f Michael Hanselmann
      if self.queryargs:
975 c744425f Michael Hanselmann
        raise http.HttpBadRequest("Can't combine query and body parameters")
976 c744425f Michael Hanselmann
977 c744425f Michael Hanselmann
      body = self.request_body
978 bd0807fe Guido Trotter
    elif self.queryargs:
979 c744425f Michael Hanselmann
      # Legacy interface, do not modify/extend
980 c744425f Michael Hanselmann
      body = {
981 c744425f Michael Hanselmann
        "os": self._checkStringVariable("os"),
982 c744425f Michael Hanselmann
        "start": not self._checkIntVariable("nostartup"),
983 c744425f Michael Hanselmann
        }
984 bd0807fe Guido Trotter
    else:
985 bd0807fe Guido Trotter
      body = {}
986 c744425f Michael Hanselmann
987 c744425f Michael Hanselmann
    ops = _ParseInstanceReinstallRequest(self.items[0], body)
988 c744425f Michael Hanselmann
989 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
990 e5b7c4ca Iustin Pop
991 e5b7c4ca Iustin Pop
992 d1c172de Michael Hanselmann
def _ParseInstanceReplaceDisksRequest(name, data):
993 d1c172de Michael Hanselmann
  """Parses a request for an instance export.
994 d1c172de Michael Hanselmann

995 d1c172de Michael Hanselmann
  @rtype: L{opcodes.OpInstanceReplaceDisks}
996 d1c172de Michael Hanselmann
  @return: Instance export opcode
997 d1c172de Michael Hanselmann

998 d1c172de Michael Hanselmann
  """
999 d1c172de Michael Hanselmann
  override = {
1000 d1c172de Michael Hanselmann
    "instance_name": name,
1001 d1c172de Michael Hanselmann
    }
1002 d1c172de Michael Hanselmann
1003 d1c172de Michael Hanselmann
  # Parse disks
1004 d1c172de Michael Hanselmann
  try:
1005 d1c172de Michael Hanselmann
    raw_disks = data["disks"]
1006 d1c172de Michael Hanselmann
  except KeyError:
1007 d1c172de Michael Hanselmann
    pass
1008 d1c172de Michael Hanselmann
  else:
1009 d1c172de Michael Hanselmann
    if not ht.TListOf(ht.TInt)(raw_disks): # pylint: disable-msg=E1102
1010 d1c172de Michael Hanselmann
      # Backwards compatibility for strings of the format "1, 2, 3"
1011 d1c172de Michael Hanselmann
      try:
1012 d1c172de Michael Hanselmann
        data["disks"] = [int(part) for part in raw_disks.split(",")]
1013 d1c172de Michael Hanselmann
      except (TypeError, ValueError), err:
1014 d1c172de Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
1015 d1c172de Michael Hanselmann
1016 d1c172de Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpInstanceReplaceDisks, data, override)
1017 d1c172de Michael Hanselmann
1018 d1c172de Michael Hanselmann
1019 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
1020 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
1021 4c98b915 Michael Hanselmann

1022 4c98b915 Michael Hanselmann
  """
1023 4c98b915 Michael Hanselmann
  def POST(self):
1024 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
1025 4c98b915 Michael Hanselmann

1026 4c98b915 Michael Hanselmann
    """
1027 d1c172de Michael Hanselmann
    op = _ParseInstanceReplaceDisksRequest(self.items[0], self.request_body)
1028 4c98b915 Michael Hanselmann
1029 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
1030 4c98b915 Michael Hanselmann
1031 4c98b915 Michael Hanselmann
1032 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
1033 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
1034 2197b66f René Nussbaumer

1035 2197b66f René Nussbaumer
  """
1036 2197b66f René Nussbaumer
  def PUT(self):
1037 2197b66f René Nussbaumer
    """Activate disks for an instance.
1038 2197b66f René Nussbaumer

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

1041 2197b66f René Nussbaumer
    """
1042 2197b66f René Nussbaumer
    instance_name = self.items[0]
1043 d0c8c01d Iustin Pop
    ignore_size = bool(self._checkIntVariable("ignore_size"))
1044 2197b66f René Nussbaumer
1045 83f5d475 Iustin Pop
    op = opcodes.OpInstanceActivateDisks(instance_name=instance_name,
1046 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
1047 2197b66f René Nussbaumer
1048 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
1049 2197b66f René Nussbaumer
1050 2197b66f René Nussbaumer
1051 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
1052 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
1053 0a37de5f René Nussbaumer

1054 0a37de5f René Nussbaumer
  """
1055 0a37de5f René Nussbaumer
  def PUT(self):
1056 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
1057 0a37de5f René Nussbaumer

1058 0a37de5f René Nussbaumer
    """
1059 0a37de5f René Nussbaumer
    instance_name = self.items[0]
1060 0a37de5f René Nussbaumer
1061 e176281f Iustin Pop
    op = opcodes.OpInstanceDeactivateDisks(instance_name=instance_name)
1062 0a37de5f René Nussbaumer
1063 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
1064 0a37de5f René Nussbaumer
1065 0a37de5f René Nussbaumer
1066 ebeb600f Michael Hanselmann
class R_2_instances_name_prepare_export(baserlib.R_Generic):
1067 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/prepare-export resource.
1068 ebeb600f Michael Hanselmann

1069 ebeb600f Michael Hanselmann
  """
1070 ebeb600f Michael Hanselmann
  def PUT(self):
1071 ebeb600f Michael Hanselmann
    """Prepares an export for an instance.
1072 ebeb600f Michael Hanselmann

1073 ebeb600f Michael Hanselmann
    @return: a job id
1074 ebeb600f Michael Hanselmann

1075 ebeb600f Michael Hanselmann
    """
1076 ebeb600f Michael Hanselmann
    instance_name = self.items[0]
1077 ebeb600f Michael Hanselmann
    mode = self._checkStringVariable("mode")
1078 ebeb600f Michael Hanselmann
1079 71910715 Iustin Pop
    op = opcodes.OpBackupPrepare(instance_name=instance_name,
1080 ebeb600f Michael Hanselmann
                                 mode=mode)
1081 ebeb600f Michael Hanselmann
1082 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1083 ebeb600f Michael Hanselmann
1084 ebeb600f Michael Hanselmann
1085 ebeb600f Michael Hanselmann
def _ParseExportInstanceRequest(name, data):
1086 ebeb600f Michael Hanselmann
  """Parses a request for an instance export.
1087 ebeb600f Michael Hanselmann

1088 4ff922a2 Iustin Pop
  @rtype: L{opcodes.OpBackupExport}
1089 ebeb600f Michael Hanselmann
  @return: Instance export opcode
1090 ebeb600f Michael Hanselmann

1091 ebeb600f Michael Hanselmann
  """
1092 07ce3e70 Michael Hanselmann
  # Rename "destination" to "target_node"
1093 07ce3e70 Michael Hanselmann
  try:
1094 07ce3e70 Michael Hanselmann
    data["target_node"] = data.pop("destination")
1095 07ce3e70 Michael Hanselmann
  except KeyError:
1096 07ce3e70 Michael Hanselmann
    pass
1097 07ce3e70 Michael Hanselmann
1098 07ce3e70 Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpBackupExport, data, {
1099 07ce3e70 Michael Hanselmann
    "instance_name": name,
1100 07ce3e70 Michael Hanselmann
    })
1101 ebeb600f Michael Hanselmann
1102 ebeb600f Michael Hanselmann
1103 ebeb600f Michael Hanselmann
class R_2_instances_name_export(baserlib.R_Generic):
1104 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/export resource.
1105 ebeb600f Michael Hanselmann

1106 ebeb600f Michael Hanselmann
  """
1107 ebeb600f Michael Hanselmann
  def PUT(self):
1108 ebeb600f Michael Hanselmann
    """Exports an instance.
1109 ebeb600f Michael Hanselmann

1110 ebeb600f Michael Hanselmann
    @return: a job id
1111 ebeb600f Michael Hanselmann

1112 ebeb600f Michael Hanselmann
    """
1113 ebeb600f Michael Hanselmann
    if not isinstance(self.request_body, dict):
1114 ebeb600f Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1115 ebeb600f Michael Hanselmann
1116 ebeb600f Michael Hanselmann
    op = _ParseExportInstanceRequest(self.items[0], self.request_body)
1117 ebeb600f Michael Hanselmann
1118 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1119 ebeb600f Michael Hanselmann
1120 ebeb600f Michael Hanselmann
1121 5823e0d2 Michael Hanselmann
def _ParseMigrateInstanceRequest(name, data):
1122 5823e0d2 Michael Hanselmann
  """Parses a request for an instance migration.
1123 5823e0d2 Michael Hanselmann

1124 75c866c2 Iustin Pop
  @rtype: L{opcodes.OpInstanceMigrate}
1125 5823e0d2 Michael Hanselmann
  @return: Instance migration opcode
1126 5823e0d2 Michael Hanselmann

1127 5823e0d2 Michael Hanselmann
  """
1128 c1a27c9a Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpInstanceMigrate, data, {
1129 c1a27c9a Michael Hanselmann
    "instance_name": name,
1130 c1a27c9a Michael Hanselmann
    })
1131 5823e0d2 Michael Hanselmann
1132 5823e0d2 Michael Hanselmann
1133 5823e0d2 Michael Hanselmann
class R_2_instances_name_migrate(baserlib.R_Generic):
1134 5823e0d2 Michael Hanselmann
  """/2/instances/[instance_name]/migrate resource.
1135 5823e0d2 Michael Hanselmann

1136 5823e0d2 Michael Hanselmann
  """
1137 5823e0d2 Michael Hanselmann
  def PUT(self):
1138 5823e0d2 Michael Hanselmann
    """Migrates an instance.
1139 5823e0d2 Michael Hanselmann

1140 5823e0d2 Michael Hanselmann
    @return: a job id
1141 5823e0d2 Michael Hanselmann

1142 5823e0d2 Michael Hanselmann
    """
1143 5823e0d2 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1144 5823e0d2 Michael Hanselmann
1145 5823e0d2 Michael Hanselmann
    op = _ParseMigrateInstanceRequest(self.items[0], self.request_body)
1146 5823e0d2 Michael Hanselmann
1147 5823e0d2 Michael Hanselmann
    return baserlib.SubmitJob([op])
1148 5823e0d2 Michael Hanselmann
1149 5823e0d2 Michael Hanselmann
1150 c0a146a1 Michael Hanselmann
class R_2_instances_name_failover(baserlib.R_Generic):
1151 c0a146a1 Michael Hanselmann
  """/2/instances/[instance_name]/failover resource.
1152 c0a146a1 Michael Hanselmann

1153 c0a146a1 Michael Hanselmann
  """
1154 c0a146a1 Michael Hanselmann
  def PUT(self):
1155 c0a146a1 Michael Hanselmann
    """Does a failover of an instance.
1156 c0a146a1 Michael Hanselmann

1157 c0a146a1 Michael Hanselmann
    @return: a job id
1158 c0a146a1 Michael Hanselmann

1159 c0a146a1 Michael Hanselmann
    """
1160 c0a146a1 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1161 c0a146a1 Michael Hanselmann
1162 c0a146a1 Michael Hanselmann
    op = baserlib.FillOpcode(opcodes.OpInstanceFailover, self.request_body, {
1163 c0a146a1 Michael Hanselmann
      "instance_name": self.items[0],
1164 c0a146a1 Michael Hanselmann
      })
1165 c0a146a1 Michael Hanselmann
1166 c0a146a1 Michael Hanselmann
    return baserlib.SubmitJob([op])
1167 c0a146a1 Michael Hanselmann
1168 c0a146a1 Michael Hanselmann
1169 d56e7dc7 Michael Hanselmann
def _ParseRenameInstanceRequest(name, data):
1170 d56e7dc7 Michael Hanselmann
  """Parses a request for renaming an instance.
1171 d56e7dc7 Michael Hanselmann

1172 5659e2e2 Iustin Pop
  @rtype: L{opcodes.OpInstanceRename}
1173 d56e7dc7 Michael Hanselmann
  @return: Instance rename opcode
1174 d56e7dc7 Michael Hanselmann

1175 d56e7dc7 Michael Hanselmann
  """
1176 88bc199a Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpInstanceRename, data, {
1177 88bc199a Michael Hanselmann
    "instance_name": name,
1178 88bc199a Michael Hanselmann
    })
1179 d56e7dc7 Michael Hanselmann
1180 d56e7dc7 Michael Hanselmann
1181 d56e7dc7 Michael Hanselmann
class R_2_instances_name_rename(baserlib.R_Generic):
1182 d56e7dc7 Michael Hanselmann
  """/2/instances/[instance_name]/rename resource.
1183 d56e7dc7 Michael Hanselmann

1184 d56e7dc7 Michael Hanselmann
  """
1185 d56e7dc7 Michael Hanselmann
  def PUT(self):
1186 d56e7dc7 Michael Hanselmann
    """Changes the name of an instance.
1187 d56e7dc7 Michael Hanselmann

1188 d56e7dc7 Michael Hanselmann
    @return: a job id
1189 d56e7dc7 Michael Hanselmann

1190 d56e7dc7 Michael Hanselmann
    """
1191 d56e7dc7 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1192 d56e7dc7 Michael Hanselmann
1193 d56e7dc7 Michael Hanselmann
    op = _ParseRenameInstanceRequest(self.items[0], self.request_body)
1194 d56e7dc7 Michael Hanselmann
1195 d56e7dc7 Michael Hanselmann
    return baserlib.SubmitJob([op])
1196 d56e7dc7 Michael Hanselmann
1197 d56e7dc7 Michael Hanselmann
1198 3882937a Michael Hanselmann
def _ParseModifyInstanceRequest(name, data):
1199 3882937a Michael Hanselmann
  """Parses a request for modifying an instance.
1200 3882937a Michael Hanselmann

1201 9a3cc7ae Iustin Pop
  @rtype: L{opcodes.OpInstanceSetParams}
1202 3882937a Michael Hanselmann
  @return: Instance modify opcode
1203 3882937a Michael Hanselmann

1204 3882937a Michael Hanselmann
  """
1205 ee5549c7 Michael Hanselmann
  return baserlib.FillOpcode(opcodes.OpInstanceSetParams, data, {
1206 ee5549c7 Michael Hanselmann
    "instance_name": name,
1207 ee5549c7 Michael Hanselmann
    })
1208 3882937a Michael Hanselmann
1209 3882937a Michael Hanselmann
1210 3882937a Michael Hanselmann
class R_2_instances_name_modify(baserlib.R_Generic):
1211 3882937a Michael Hanselmann
  """/2/instances/[instance_name]/modify resource.
1212 3882937a Michael Hanselmann

1213 3882937a Michael Hanselmann
  """
1214 3882937a Michael Hanselmann
  def PUT(self):
1215 3882937a Michael Hanselmann
    """Changes some parameters of an instance.
1216 3882937a Michael Hanselmann

1217 3882937a Michael Hanselmann
    @return: a job id
1218 3882937a Michael Hanselmann

1219 3882937a Michael Hanselmann
    """
1220 3882937a Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1221 3882937a Michael Hanselmann
1222 3882937a Michael Hanselmann
    op = _ParseModifyInstanceRequest(self.items[0], self.request_body)
1223 3882937a Michael Hanselmann
1224 3882937a Michael Hanselmann
    return baserlib.SubmitJob([op])
1225 3882937a Michael Hanselmann
1226 3882937a Michael Hanselmann
1227 e23881ed Michael Hanselmann
class R_2_instances_name_disk_grow(baserlib.R_Generic):
1228 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name]/disk/[disk_index]/grow resource.
1229 e23881ed Michael Hanselmann

1230 e23881ed Michael Hanselmann
  """
1231 e23881ed Michael Hanselmann
  def POST(self):
1232 e23881ed Michael Hanselmann
    """Increases the size of an instance disk.
1233 e23881ed Michael Hanselmann

1234 e23881ed Michael Hanselmann
    @return: a job id
1235 e23881ed Michael Hanselmann

1236 e23881ed Michael Hanselmann
    """
1237 60472d29 Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpInstanceGrowDisk, self.request_body, {
1238 e23881ed Michael Hanselmann
      "instance_name": self.items[0],
1239 e23881ed Michael Hanselmann
      "disk": int(self.items[1]),
1240 e23881ed Michael Hanselmann
      })
1241 e23881ed Michael Hanselmann
1242 e23881ed Michael Hanselmann
    return baserlib.SubmitJob([op])
1243 e23881ed Michael Hanselmann
1244 e23881ed Michael Hanselmann
1245 b82d4c5e Michael Hanselmann
class R_2_instances_name_console(baserlib.R_Generic):
1246 b82d4c5e Michael Hanselmann
  """/2/instances/[instance_name]/console resource.
1247 b82d4c5e Michael Hanselmann

1248 b82d4c5e Michael Hanselmann
  """
1249 b82d4c5e Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
1250 b82d4c5e Michael Hanselmann
1251 b82d4c5e Michael Hanselmann
  def GET(self):
1252 b82d4c5e Michael Hanselmann
    """Request information for connecting to instance's console.
1253 b82d4c5e Michael Hanselmann

1254 b82d4c5e Michael Hanselmann
    @return: Serialized instance console description, see
1255 b82d4c5e Michael Hanselmann
             L{objects.InstanceConsole}
1256 b82d4c5e Michael Hanselmann

1257 b82d4c5e Michael Hanselmann
    """
1258 b82d4c5e Michael Hanselmann
    client = baserlib.GetClient()
1259 b82d4c5e Michael Hanselmann
1260 b82d4c5e Michael Hanselmann
    ((console, ), ) = client.QueryInstances([self.items[0]], ["console"], False)
1261 b82d4c5e Michael Hanselmann
1262 b82d4c5e Michael Hanselmann
    if console is None:
1263 b82d4c5e Michael Hanselmann
      raise http.HttpServiceUnavailable("Instance console unavailable")
1264 b82d4c5e Michael Hanselmann
1265 b82d4c5e Michael Hanselmann
    assert isinstance(console, dict)
1266 b82d4c5e Michael Hanselmann
    return console
1267 b82d4c5e Michael Hanselmann
1268 b82d4c5e Michael Hanselmann
1269 208a6cff Michael Hanselmann
def _GetQueryFields(args):
1270 208a6cff Michael Hanselmann
  """
1271 208a6cff Michael Hanselmann

1272 208a6cff Michael Hanselmann
  """
1273 208a6cff Michael Hanselmann
  try:
1274 208a6cff Michael Hanselmann
    fields = args["fields"]
1275 208a6cff Michael Hanselmann
  except KeyError:
1276 208a6cff Michael Hanselmann
    raise http.HttpBadRequest("Missing 'fields' query argument")
1277 208a6cff Michael Hanselmann
1278 208a6cff Michael Hanselmann
  return _SplitQueryFields(fields[0])
1279 208a6cff Michael Hanselmann
1280 208a6cff Michael Hanselmann
1281 208a6cff Michael Hanselmann
def _SplitQueryFields(fields):
1282 208a6cff Michael Hanselmann
  """
1283 208a6cff Michael Hanselmann

1284 208a6cff Michael Hanselmann
  """
1285 208a6cff Michael Hanselmann
  return [i.strip() for i in fields.split(",")]
1286 208a6cff Michael Hanselmann
1287 208a6cff Michael Hanselmann
1288 208a6cff Michael Hanselmann
class R_2_query(baserlib.R_Generic):
1289 208a6cff Michael Hanselmann
  """/2/query/[resource] resource.
1290 208a6cff Michael Hanselmann

1291 208a6cff Michael Hanselmann
  """
1292 208a6cff Michael Hanselmann
  # Results might contain sensitive information
1293 208a6cff Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
1294 208a6cff Michael Hanselmann
1295 208a6cff Michael Hanselmann
  def _Query(self, fields, filter_):
1296 208a6cff Michael Hanselmann
    return baserlib.GetClient().Query(self.items[0], fields, filter_).ToDict()
1297 208a6cff Michael Hanselmann
1298 208a6cff Michael Hanselmann
  def GET(self):
1299 208a6cff Michael Hanselmann
    """Returns resource information.
1300 208a6cff Michael Hanselmann

1301 208a6cff Michael Hanselmann
    @return: Query result, see L{objects.QueryResponse}
1302 208a6cff Michael Hanselmann

1303 208a6cff Michael Hanselmann
    """
1304 208a6cff Michael Hanselmann
    return self._Query(_GetQueryFields(self.queryargs), None)
1305 208a6cff Michael Hanselmann
1306 208a6cff Michael Hanselmann
  def PUT(self):
1307 208a6cff Michael Hanselmann
    """Submits job querying for resources.
1308 208a6cff Michael Hanselmann

1309 208a6cff Michael Hanselmann
    @return: Query result, see L{objects.QueryResponse}
1310 208a6cff Michael Hanselmann

1311 208a6cff Michael Hanselmann
    """
1312 208a6cff Michael Hanselmann
    body = self.request_body
1313 208a6cff Michael Hanselmann
1314 208a6cff Michael Hanselmann
    baserlib.CheckType(body, dict, "Body contents")
1315 208a6cff Michael Hanselmann
1316 208a6cff Michael Hanselmann
    try:
1317 208a6cff Michael Hanselmann
      fields = body["fields"]
1318 208a6cff Michael Hanselmann
    except KeyError:
1319 208a6cff Michael Hanselmann
      fields = _GetQueryFields(self.queryargs)
1320 208a6cff Michael Hanselmann
1321 208a6cff Michael Hanselmann
    return self._Query(fields, self.request_body.get("filter", None))
1322 208a6cff Michael Hanselmann
1323 208a6cff Michael Hanselmann
1324 208a6cff Michael Hanselmann
class R_2_query_fields(baserlib.R_Generic):
1325 208a6cff Michael Hanselmann
  """/2/query/[resource]/fields resource.
1326 208a6cff Michael Hanselmann

1327 208a6cff Michael Hanselmann
  """
1328 208a6cff Michael Hanselmann
  def GET(self):
1329 208a6cff Michael Hanselmann
    """Retrieves list of available fields for a resource.
1330 208a6cff Michael Hanselmann

1331 208a6cff Michael Hanselmann
    @return: List of serialized L{objects.QueryFieldDefinition}
1332 208a6cff Michael Hanselmann

1333 208a6cff Michael Hanselmann
    """
1334 208a6cff Michael Hanselmann
    try:
1335 208a6cff Michael Hanselmann
      raw_fields = self.queryargs["fields"]
1336 208a6cff Michael Hanselmann
    except KeyError:
1337 208a6cff Michael Hanselmann
      fields = None
1338 208a6cff Michael Hanselmann
    else:
1339 208a6cff Michael Hanselmann
      fields = _SplitQueryFields(raw_fields[0])
1340 208a6cff Michael Hanselmann
1341 208a6cff Michael Hanselmann
    return baserlib.GetClient().QueryFields(self.items[0], fields).ToDict()
1342 208a6cff Michael Hanselmann
1343 208a6cff Michael Hanselmann
1344 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
1345 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
1346 441e7cfd Oleksiy Mishchenko

1347 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
1348 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
1349 441e7cfd Oleksiy Mishchenko

1350 441e7cfd Oleksiy Mishchenko
  """
1351 7a6b9510 Iustin Pop
  TAG_LEVEL = None
1352 18cb43a2 Oleksiy Mishchenko
1353 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
1354 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
1355 18cb43a2 Oleksiy Mishchenko

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

1358 18cb43a2 Oleksiy Mishchenko
    """
1359 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
1360 18cb43a2 Oleksiy Mishchenko
1361 5313eed7 Michael Hanselmann
    if self.TAG_LEVEL == constants.TAG_CLUSTER:
1362 5313eed7 Michael Hanselmann
      self.name = None
1363 18cb43a2 Oleksiy Mishchenko
    else:
1364 5313eed7 Michael Hanselmann
      self.name = items[0]
1365 441e7cfd Oleksiy Mishchenko
1366 441e7cfd Oleksiy Mishchenko
  def GET(self):
1367 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
1368 441e7cfd Oleksiy Mishchenko

1369 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
1370 441e7cfd Oleksiy Mishchenko

1371 441e7cfd Oleksiy Mishchenko
    """
1372 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1373 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
1374 441e7cfd Oleksiy Mishchenko
1375 21f04e5e Oleksiy Mishchenko
  def PUT(self):
1376 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
1377 441e7cfd Oleksiy Mishchenko

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

1381 441e7cfd Oleksiy Mishchenko
    """
1382 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1383 d0c8c01d Iustin Pop
    if "tag" not in self.queryargs:
1384 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
1385 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
1386 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
1387 d0c8c01d Iustin Pop
                              self.queryargs["tag"], name=self.name,
1388 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
1389 15fd9fd5 Oleksiy Mishchenko
1390 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
1391 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
1392 15fd9fd5 Oleksiy Mishchenko

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

1397 15fd9fd5 Oleksiy Mishchenko
    """
1398 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1399 d0c8c01d Iustin Pop
    if "tag" not in self.queryargs:
1400 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
1401 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
1402 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
1403 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
1404 d0c8c01d Iustin Pop
                                 self.queryargs["tag"],
1405 6f59b964 Iustin Pop
                                 name=self.name,
1406 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
1407 18cb43a2 Oleksiy Mishchenko
1408 18cb43a2 Oleksiy Mishchenko
1409 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
1410 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
1411 18cb43a2 Oleksiy Mishchenko

1412 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
1413 18cb43a2 Oleksiy Mishchenko

1414 18cb43a2 Oleksiy Mishchenko
  """
1415 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
1416 18cb43a2 Oleksiy Mishchenko
1417 18cb43a2 Oleksiy Mishchenko
1418 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
1419 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
1420 18cb43a2 Oleksiy Mishchenko

1421 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
1422 18cb43a2 Oleksiy Mishchenko

1423 18cb43a2 Oleksiy Mishchenko
  """
1424 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
1425 18cb43a2 Oleksiy Mishchenko
1426 18cb43a2 Oleksiy Mishchenko
1427 414ebaf1 Michael Hanselmann
class R_2_groups_name_tags(_R_Tags):
1428 414ebaf1 Michael Hanselmann
  """ /2/groups/[group_name]/tags resource.
1429 414ebaf1 Michael Hanselmann

1430 414ebaf1 Michael Hanselmann
  Manages per-nodegroup tags.
1431 414ebaf1 Michael Hanselmann

1432 414ebaf1 Michael Hanselmann
  """
1433 414ebaf1 Michael Hanselmann
  TAG_LEVEL = constants.TAG_NODEGROUP
1434 414ebaf1 Michael Hanselmann
1435 414ebaf1 Michael Hanselmann
1436 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
1437 b58a4d16 Michael Hanselmann
  """ /2/tags resource.
1438 18cb43a2 Oleksiy Mishchenko

1439 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
1440 18cb43a2 Oleksiy Mishchenko

1441 18cb43a2 Oleksiy Mishchenko
  """
1442 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER