Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 62e999a5

History | View | Annotate | Download (40.1 kB)

1 10b207d4 Oleksiy Mishchenko
#
2 10b207d4 Oleksiy Mishchenko
#
3 10b207d4 Oleksiy Mishchenko
4 52194140 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 88394aa7 René Nussbaumer
  PUT or POST?
25 bb579a7d René Nussbaumer
  ============
26 88394aa7 René Nussbaumer

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

31 88394aa7 René Nussbaumer
  To be in context of this module for instance creation POST on
32 88394aa7 René Nussbaumer
  /2/instances is legitim while PUT would be not, due to it does create a
33 88394aa7 René Nussbaumer
  new entity and not just replace /2/instances with it.
34 88394aa7 René Nussbaumer

35 88394aa7 René Nussbaumer
  So when adding new methods, if they are operating on the URI entity itself,
36 88394aa7 René Nussbaumer
  PUT should be prefered over POST.
37 88394aa7 René Nussbaumer

38 10b207d4 Oleksiy Mishchenko
"""
39 10b207d4 Oleksiy Mishchenko
40 fe267188 Iustin Pop
# pylint: disable-msg=C0103
41 fe267188 Iustin Pop
42 fe267188 Iustin Pop
# C0103: Invalid name, since the R_* names are not conforming
43 fe267188 Iustin Pop
44 59b4eeef Iustin Pop
from ganeti import opcodes
45 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
46 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
47 59b4eeef Iustin Pop
from ganeti import cli
48 6395cebb Michael Hanselmann
from ganeti import utils
49 8381fa2d Michael Hanselmann
from ganeti import rapi
50 38206f3c Iustin Pop
from ganeti.rapi import baserlib
51 10b207d4 Oleksiy Mishchenko
52 4e5a68f8 Oleksiy Mishchenko
53 7118a0df Iustin Pop
_COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
54 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
55 9031ee8e Iustin Pop
            "pnode", "snodes",
56 9031ee8e Iustin Pop
            "disk_template",
57 82e186f8 Michael Hanselmann
            "nic.ips", "nic.macs", "nic.modes", "nic.links", "nic.bridges",
58 a8b16c4e Tim Boring
            "network_port",
59 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
60 a5b9d725 Iustin Pop
            "beparams", "hvparams",
61 4ea3de4e Balazs Lecz
            "oper_state", "oper_ram", "oper_vcpus", "status",
62 90224407 Iustin Pop
            "custom_hvparams", "custom_beparams", "custom_nicparams",
63 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
64 9031ee8e Iustin Pop
65 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
66 9031ee8e Iustin Pop
            "dtotal", "dfree",
67 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
68 7118a0df Iustin Pop
            "pinst_cnt", "sinst_cnt",
69 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
70 7118a0df Iustin Pop
            "pip", "sip", "role",
71 93962b80 Iustin Pop
            "pinst_list", "sinst_list",
72 c190e817 Iustin Pop
            "master_capable", "vm_capable",
73 fd254195 Iustin Pop
            "group.uuid",
74 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
75 4e5a68f8 Oleksiy Mishchenko
76 0897dc97 Adeodato Simo
G_FIELDS = ["name", "uuid",
77 90e99856 Adeodato Simo
            "alloc_policy",
78 0897dc97 Adeodato Simo
            "node_cnt", "node_list",
79 4edc512c Adeodato Simo
            "ctime", "mtime", "serial_no",
80 4edc512c Adeodato Simo
            ]  # "tags" is missing to be able to use _COMMON_FIELDS here.
81 0897dc97 Adeodato Simo
82 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
83 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
84 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
85 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
86 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
87 64dae8fc Michael Hanselmann
88 64dae8fc Michael Hanselmann
_NR_MAP = {
89 64dae8fc Michael Hanselmann
  "M": _NR_MASTER,
90 64dae8fc Michael Hanselmann
  "C": _NR_MASTER_CANDIATE,
91 64dae8fc Michael Hanselmann
  "D": _NR_DRAINED,
92 64dae8fc Michael Hanselmann
  "O": _NR_OFFLINE,
93 64dae8fc Michael Hanselmann
  "R": _NR_REGULAR,
94 64dae8fc Michael Hanselmann
  }
95 64dae8fc Michael Hanselmann
96 d975f482 Michael Hanselmann
# Request data version field
97 d975f482 Michael Hanselmann
_REQ_DATA_VERSION = "__version__"
98 d975f482 Michael Hanselmann
99 6395cebb Michael Hanselmann
# Feature string for instance creation request data version 1
100 6395cebb Michael Hanselmann
_INST_CREATE_REQV1 = "instance-create-reqv1"
101 6395cebb Michael Hanselmann
102 c744425f Michael Hanselmann
# Feature string for instance reinstall request version 1
103 c744425f Michael Hanselmann
_INST_REINSTALL_REQV1 = "instance-reinstall-reqv1"
104 c744425f Michael Hanselmann
105 793a8f7c Michael Hanselmann
# Timeout for /2/jobs/[job_id]/wait. Gives job up to 10 seconds to change.
106 793a8f7c Michael Hanselmann
_WFJC_TIMEOUT = 10
107 793a8f7c Michael Hanselmann
108 4e5a68f8 Oleksiy Mishchenko
109 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
110 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
111 4e5a68f8 Oleksiy Mishchenko

112 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
113 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
114 4e5a68f8 Oleksiy Mishchenko

115 4e5a68f8 Oleksiy Mishchenko
  """
116 7e950d31 Iustin Pop
  @staticmethod
117 7e950d31 Iustin Pop
  def GET():
118 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
119 4e5a68f8 Oleksiy Mishchenko

120 4e5a68f8 Oleksiy Mishchenko
    """
121 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
122 4e5a68f8 Oleksiy Mishchenko
123 4e5a68f8 Oleksiy Mishchenko
124 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
125 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
126 4e5a68f8 Oleksiy Mishchenko

127 4e5a68f8 Oleksiy Mishchenko
  """
128 7e950d31 Iustin Pop
  @staticmethod
129 7e950d31 Iustin Pop
  def GET():
130 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
131 4e5a68f8 Oleksiy Mishchenko

132 4e5a68f8 Oleksiy Mishchenko
    """
133 59b4eeef Iustin Pop
    client = baserlib.GetClient()
134 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
135 4e5a68f8 Oleksiy Mishchenko
136 4e5a68f8 Oleksiy Mishchenko
137 7eac4a4d Michael Hanselmann
class R_2_features(baserlib.R_Generic):
138 7eac4a4d Michael Hanselmann
  """/2/features resource.
139 7eac4a4d Michael Hanselmann

140 7eac4a4d Michael Hanselmann
  """
141 7eac4a4d Michael Hanselmann
  @staticmethod
142 7eac4a4d Michael Hanselmann
  def GET():
143 7eac4a4d Michael Hanselmann
    """Returns list of optional RAPI features implemented.
144 7eac4a4d Michael Hanselmann

145 7eac4a4d Michael Hanselmann
    """
146 c744425f Michael Hanselmann
    return [_INST_CREATE_REQV1, _INST_REINSTALL_REQV1]
147 7eac4a4d Michael Hanselmann
148 7eac4a4d Michael Hanselmann
149 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
150 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
151 4e5a68f8 Oleksiy Mishchenko

152 4e5a68f8 Oleksiy Mishchenko
  """
153 7e950d31 Iustin Pop
  @staticmethod
154 7e950d31 Iustin Pop
  def GET():
155 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
156 4e5a68f8 Oleksiy Mishchenko

157 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
158 4e5a68f8 Oleksiy Mishchenko

159 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
160 4e5a68f8 Oleksiy Mishchenko

161 4e5a68f8 Oleksiy Mishchenko
    """
162 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
163 d22dfef7 Iustin Pop
    op = opcodes.OpDiagnoseOS(output_fields=["name", "variants"], names=[])
164 59b4eeef Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
165 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
166 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
167 59b4eeef Iustin Pop
    diagnose_data = result[0]
168 4e5a68f8 Oleksiy Mishchenko
169 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
170 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
171 4e5a68f8 Oleksiy Mishchenko
172 e3ac208c Guido Trotter
    os_names = []
173 d22dfef7 Iustin Pop
    for (name, variants) in diagnose_data:
174 d22dfef7 Iustin Pop
      os_names.extend(cli.CalculateOSNames(name, variants))
175 e3ac208c Guido Trotter
176 e3ac208c Guido Trotter
    return os_names
177 51ee2f49 Oleksiy Mishchenko
178 10b207d4 Oleksiy Mishchenko
179 508e9b20 Michael Hanselmann
class R_2_redist_config(baserlib.R_Generic):
180 508e9b20 Michael Hanselmann
  """/2/redistribute-config resource.
181 508e9b20 Michael Hanselmann

182 508e9b20 Michael Hanselmann
  """
183 7e950d31 Iustin Pop
  @staticmethod
184 7e950d31 Iustin Pop
  def PUT():
185 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
186 508e9b20 Michael Hanselmann

187 508e9b20 Michael Hanselmann
    """
188 508e9b20 Michael Hanselmann
    return baserlib.SubmitJob([opcodes.OpRedistributeConfig()])
189 508e9b20 Michael Hanselmann
190 508e9b20 Michael Hanselmann
191 62e999a5 Michael Hanselmann
class R_2_cluster_modify(baserlib.R_Generic):
192 62e999a5 Michael Hanselmann
  """/2/modify resource.
193 62e999a5 Michael Hanselmann

194 62e999a5 Michael Hanselmann
  """
195 62e999a5 Michael Hanselmann
  def PUT(self):
196 62e999a5 Michael Hanselmann
    """Modifies cluster parameters.
197 62e999a5 Michael Hanselmann

198 62e999a5 Michael Hanselmann
    @return: a job id
199 62e999a5 Michael Hanselmann

200 62e999a5 Michael Hanselmann
    """
201 62e999a5 Michael Hanselmann
    op = baserlib.FillOpcode(opcodes.OpSetClusterParams, self.request_body,
202 62e999a5 Michael Hanselmann
                             None)
203 62e999a5 Michael Hanselmann
204 62e999a5 Michael Hanselmann
    return baserlib.SubmitJob([op])
205 62e999a5 Michael Hanselmann
206 62e999a5 Michael Hanselmann
207 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
208 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
209 10b207d4 Oleksiy Mishchenko

210 10b207d4 Oleksiy Mishchenko
  """
211 7e950d31 Iustin Pop
  @staticmethod
212 7e950d31 Iustin Pop
  def GET():
213 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
214 10b207d4 Oleksiy Mishchenko

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

217 10b207d4 Oleksiy Mishchenko
    """
218 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
219 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
220 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
221 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
222 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
223 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
224 10b207d4 Oleksiy Mishchenko
225 10b207d4 Oleksiy Mishchenko
226 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
227 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
228 10b207d4 Oleksiy Mishchenko

229 10b207d4 Oleksiy Mishchenko
  """
230 10b207d4 Oleksiy Mishchenko
  def GET(self):
231 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
232 10b207d4 Oleksiy Mishchenko

233 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
234 c41eea6e Iustin Pop
        The result includes:
235 c41eea6e Iustin Pop
            - id: job ID as a number
236 c41eea6e Iustin Pop
            - status: current job status as a string
237 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
238 c41eea6e Iustin Pop
              opcodes in the job
239 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
240 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
241 38206f3c Iustin Pop

242 10b207d4 Oleksiy Mishchenko
    """
243 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
244 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
245 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
246 ee69c97f Iustin Pop
              ]
247 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
248 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
249 ee69c97f Iustin Pop
    if result is None:
250 ee69c97f Iustin Pop
      raise http.HttpNotFound()
251 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
252 10b207d4 Oleksiy Mishchenko
253 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
254 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
255 c7f5f338 Oleksiy Mishchenko

256 c7f5f338 Oleksiy Mishchenko
    """
257 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
258 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
259 c7f5f338 Oleksiy Mishchenko
    return result
260 c7f5f338 Oleksiy Mishchenko
261 10b207d4 Oleksiy Mishchenko
262 793a8f7c Michael Hanselmann
class R_2_jobs_id_wait(baserlib.R_Generic):
263 793a8f7c Michael Hanselmann
  """/2/jobs/[job_id]/wait resource.
264 793a8f7c Michael Hanselmann

265 793a8f7c Michael Hanselmann
  """
266 793a8f7c Michael Hanselmann
  # WaitForJobChange provides access to sensitive information and blocks
267 793a8f7c Michael Hanselmann
  # machine resources (it's a blocking RAPI call), hence restricting access.
268 793a8f7c Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
269 793a8f7c Michael Hanselmann
270 793a8f7c Michael Hanselmann
  def GET(self):
271 793a8f7c Michael Hanselmann
    """Waits for job changes.
272 793a8f7c Michael Hanselmann

273 793a8f7c Michael Hanselmann
    """
274 793a8f7c Michael Hanselmann
    job_id = self.items[0]
275 793a8f7c Michael Hanselmann
276 793a8f7c Michael Hanselmann
    fields = self.getBodyParameter("fields")
277 793a8f7c Michael Hanselmann
    prev_job_info = self.getBodyParameter("previous_job_info", None)
278 793a8f7c Michael Hanselmann
    prev_log_serial = self.getBodyParameter("previous_log_serial", None)
279 793a8f7c Michael Hanselmann
280 793a8f7c Michael Hanselmann
    if not isinstance(fields, list):
281 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'fields' parameter should be a list")
282 793a8f7c Michael Hanselmann
283 793a8f7c Michael Hanselmann
    if not (prev_job_info is None or isinstance(prev_job_info, list)):
284 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_job_info' parameter should"
285 793a8f7c Michael Hanselmann
                                " be a list")
286 793a8f7c Michael Hanselmann
287 793a8f7c Michael Hanselmann
    if not (prev_log_serial is None or
288 793a8f7c Michael Hanselmann
            isinstance(prev_log_serial, (int, long))):
289 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_log_serial' parameter should"
290 793a8f7c Michael Hanselmann
                                " be a number")
291 793a8f7c Michael Hanselmann
292 793a8f7c Michael Hanselmann
    client = baserlib.GetClient()
293 793a8f7c Michael Hanselmann
    result = client.WaitForJobChangeOnce(job_id, fields,
294 793a8f7c Michael Hanselmann
                                         prev_job_info, prev_log_serial,
295 793a8f7c Michael Hanselmann
                                         timeout=_WFJC_TIMEOUT)
296 793a8f7c Michael Hanselmann
    if not result:
297 793a8f7c Michael Hanselmann
      raise http.HttpNotFound()
298 793a8f7c Michael Hanselmann
299 793a8f7c Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
300 793a8f7c Michael Hanselmann
      # No changes
301 793a8f7c Michael Hanselmann
      return None
302 793a8f7c Michael Hanselmann
303 793a8f7c Michael Hanselmann
    (job_info, log_entries) = result
304 793a8f7c Michael Hanselmann
305 793a8f7c Michael Hanselmann
    return {
306 793a8f7c Michael Hanselmann
      "job_info": job_info,
307 793a8f7c Michael Hanselmann
      "log_entries": log_entries,
308 793a8f7c Michael Hanselmann
      }
309 793a8f7c Michael Hanselmann
310 793a8f7c Michael Hanselmann
311 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
312 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
313 10b207d4 Oleksiy Mishchenko

314 10b207d4 Oleksiy Mishchenko
  """
315 10b207d4 Oleksiy Mishchenko
  def GET(self):
316 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
317 38206f3c Iustin Pop

318 10b207d4 Oleksiy Mishchenko
    """
319 59b4eeef Iustin Pop
    client = baserlib.GetClient()
320 38206f3c Iustin Pop
321 3d103742 Iustin Pop
    if self.useBulk():
322 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
323 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
324 9031ee8e Iustin Pop
    else:
325 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
326 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
327 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
328 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
329 441e7cfd Oleksiy Mishchenko
330 441e7cfd Oleksiy Mishchenko
331 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
332 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
333 028c6b76 Oleksiy Mishchenko

334 028c6b76 Oleksiy Mishchenko
  """
335 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
336 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
337 4e5a68f8 Oleksiy Mishchenko

338 4e5a68f8 Oleksiy Mishchenko
    """
339 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
340 59b4eeef Iustin Pop
    client = baserlib.GetClient()
341 e8ebbd2b Michael Hanselmann
342 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryNodes,
343 e8ebbd2b Michael Hanselmann
                                            names=[node_name], fields=N_FIELDS,
344 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
345 4e5a68f8 Oleksiy Mishchenko
346 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
347 028c6b76 Oleksiy Mishchenko
348 028c6b76 Oleksiy Mishchenko
349 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
350 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
351 64dae8fc Michael Hanselmann

352 64dae8fc Michael Hanselmann
  """
353 64dae8fc Michael Hanselmann
  def GET(self):
354 64dae8fc Michael Hanselmann
    """Returns the current node role.
355 64dae8fc Michael Hanselmann

356 64dae8fc Michael Hanselmann
    @return: Node role
357 64dae8fc Michael Hanselmann

358 64dae8fc Michael Hanselmann
    """
359 64dae8fc Michael Hanselmann
    node_name = self.items[0]
360 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
361 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
362 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
363 64dae8fc Michael Hanselmann
364 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
365 64dae8fc Michael Hanselmann
366 64dae8fc Michael Hanselmann
  def PUT(self):
367 64dae8fc Michael Hanselmann
    """Sets the node role.
368 64dae8fc Michael Hanselmann

369 64dae8fc Michael Hanselmann
    @return: a job id
370 64dae8fc Michael Hanselmann

371 64dae8fc Michael Hanselmann
    """
372 627ad739 Michael Hanselmann
    if not isinstance(self.request_body, basestring):
373 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
374 64dae8fc Michael Hanselmann
375 64dae8fc Michael Hanselmann
    node_name = self.items[0]
376 627ad739 Michael Hanselmann
    role = self.request_body
377 64dae8fc Michael Hanselmann
378 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
379 64dae8fc Michael Hanselmann
      candidate = False
380 64dae8fc Michael Hanselmann
      offline = False
381 64dae8fc Michael Hanselmann
      drained = False
382 64dae8fc Michael Hanselmann
383 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
384 64dae8fc Michael Hanselmann
      candidate = True
385 64dae8fc Michael Hanselmann
      offline = drained = None
386 64dae8fc Michael Hanselmann
387 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
388 64dae8fc Michael Hanselmann
      drained = True
389 64dae8fc Michael Hanselmann
      candidate = offline = None
390 64dae8fc Michael Hanselmann
391 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
392 64dae8fc Michael Hanselmann
      offline = True
393 64dae8fc Michael Hanselmann
      candidate = drained = None
394 64dae8fc Michael Hanselmann
395 64dae8fc Michael Hanselmann
    else:
396 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
397 64dae8fc Michael Hanselmann
398 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
399 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
400 64dae8fc Michael Hanselmann
                                 offline=offline,
401 64dae8fc Michael Hanselmann
                                 drained=drained,
402 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
403 64dae8fc Michael Hanselmann
404 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
405 64dae8fc Michael Hanselmann
406 64dae8fc Michael Hanselmann
407 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
408 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
409 73452f12 Michael Hanselmann

410 73452f12 Michael Hanselmann
  """
411 73452f12 Michael Hanselmann
  def POST(self):
412 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
413 73452f12 Michael Hanselmann

414 73452f12 Michael Hanselmann
    """
415 73452f12 Michael Hanselmann
    node_name = self.items[0]
416 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
417 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
418 941b9309 Iustin Pop
    early_r = bool(self._checkIntVariable("early_release", default=0))
419 941b9309 Iustin Pop
    dry_run = bool(self.dryRun())
420 73452f12 Michael Hanselmann
421 941b9309 Iustin Pop
    cl = baserlib.GetClient()
422 73452f12 Michael Hanselmann
423 941b9309 Iustin Pop
    op = opcodes.OpNodeEvacuationStrategy(nodes=[node_name],
424 941b9309 Iustin Pop
                                          iallocator=iallocator,
425 941b9309 Iustin Pop
                                          remote_node=remote_node)
426 941b9309 Iustin Pop
427 941b9309 Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
428 941b9309 Iustin Pop
    # we use custom feedback function, instead of print we log the status
429 941b9309 Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
430 941b9309 Iustin Pop
431 941b9309 Iustin Pop
    jobs = []
432 941b9309 Iustin Pop
    for iname, node in result:
433 941b9309 Iustin Pop
      if dry_run:
434 941b9309 Iustin Pop
        jid = None
435 941b9309 Iustin Pop
      else:
436 941b9309 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=iname,
437 941b9309 Iustin Pop
                                    remote_node=node, disks=[],
438 941b9309 Iustin Pop
                                    mode=constants.REPLACE_DISK_CHG,
439 941b9309 Iustin Pop
                                    early_release=early_r)
440 941b9309 Iustin Pop
        jid = baserlib.SubmitJob([op])
441 941b9309 Iustin Pop
      jobs.append((jid, iname, node))
442 941b9309 Iustin Pop
443 941b9309 Iustin Pop
    return jobs
444 73452f12 Michael Hanselmann
445 73452f12 Michael Hanselmann
446 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
447 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
448 1c482bab Michael Hanselmann

449 1c482bab Michael Hanselmann
  """
450 1c482bab Michael Hanselmann
  def POST(self):
451 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
452 1c482bab Michael Hanselmann

453 1c482bab Michael Hanselmann
    """
454 1c482bab Michael Hanselmann
    node_name = self.items[0]
455 1c482bab Michael Hanselmann
456 52194140 Iustin Pop
    if "live" in self.queryargs and "mode" in self.queryargs:
457 52194140 Iustin Pop
      raise http.HttpBadRequest("Only one of 'live' and 'mode' should"
458 52194140 Iustin Pop
                                " be passed")
459 52194140 Iustin Pop
    elif "live" in self.queryargs:
460 52194140 Iustin Pop
      if self._checkIntVariable("live", default=1):
461 52194140 Iustin Pop
        mode = constants.HT_MIGRATION_LIVE
462 52194140 Iustin Pop
      else:
463 52194140 Iustin Pop
        mode = constants.HT_MIGRATION_NONLIVE
464 52194140 Iustin Pop
    else:
465 52194140 Iustin Pop
      mode = self._checkStringVariable("mode", default=None)
466 52194140 Iustin Pop
467 52194140 Iustin Pop
    op = opcodes.OpMigrateNode(node_name=node_name, mode=mode)
468 1c482bab Michael Hanselmann
469 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
470 1c482bab Michael Hanselmann
471 1c482bab Michael Hanselmann
472 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
473 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
474 7a95a954 Michael Hanselmann

475 7a95a954 Michael Hanselmann
  """
476 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
477 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
478 7a95a954 Michael Hanselmann
479 7a95a954 Michael Hanselmann
  def GET(self):
480 7a95a954 Michael Hanselmann
    node_name = self.items[0]
481 7a95a954 Michael Hanselmann
482 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
483 7a95a954 Michael Hanselmann
    if not storage_type:
484 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
485 7a95a954 Michael Hanselmann
                                " parameter")
486 7a95a954 Michael Hanselmann
487 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
488 7a95a954 Michael Hanselmann
    if not output_fields:
489 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
490 7a95a954 Michael Hanselmann
                                " parameter")
491 7a95a954 Michael Hanselmann
492 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
493 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
494 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
495 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
496 7a95a954 Michael Hanselmann
497 7a95a954 Michael Hanselmann
498 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
499 1e82bc80 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify ressource.
500 1e82bc80 Michael Hanselmann

501 1e82bc80 Michael Hanselmann
  """
502 1e82bc80 Michael Hanselmann
  def PUT(self):
503 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
504 1e82bc80 Michael Hanselmann
505 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
506 1e82bc80 Michael Hanselmann
    if not storage_type:
507 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
508 1e82bc80 Michael Hanselmann
                                " parameter")
509 1e82bc80 Michael Hanselmann
510 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
511 1e82bc80 Michael Hanselmann
    if not name:
512 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
513 1e82bc80 Michael Hanselmann
                                " parameter")
514 1e82bc80 Michael Hanselmann
515 1e82bc80 Michael Hanselmann
    changes = {}
516 1e82bc80 Michael Hanselmann
517 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
518 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
519 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
520 1e82bc80 Michael Hanselmann
521 1e82bc80 Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
522 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
523 1e82bc80 Michael Hanselmann
                                     name=name,
524 1e82bc80 Michael Hanselmann
                                     changes=changes)
525 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
526 1e82bc80 Michael Hanselmann
527 1e82bc80 Michael Hanselmann
528 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
529 723f4565 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair ressource.
530 723f4565 Michael Hanselmann

531 723f4565 Michael Hanselmann
  """
532 723f4565 Michael Hanselmann
  def PUT(self):
533 723f4565 Michael Hanselmann
    node_name = self.items[0]
534 723f4565 Michael Hanselmann
535 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
536 723f4565 Michael Hanselmann
    if not storage_type:
537 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
538 723f4565 Michael Hanselmann
                                " parameter")
539 723f4565 Michael Hanselmann
540 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
541 723f4565 Michael Hanselmann
    if not name:
542 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
543 723f4565 Michael Hanselmann
                                " parameter")
544 723f4565 Michael Hanselmann
545 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
546 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
547 723f4565 Michael Hanselmann
                                     name=name)
548 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
549 723f4565 Michael Hanselmann
550 723f4565 Michael Hanselmann
551 90e99856 Adeodato Simo
def _ParseCreateGroupRequest(data, dry_run):
552 90e99856 Adeodato Simo
  """Parses a request for creating a node group.
553 90e99856 Adeodato Simo

554 90e99856 Adeodato Simo
  @rtype: L{opcodes.OpAddGroup}
555 90e99856 Adeodato Simo
  @return: Group creation opcode
556 90e99856 Adeodato Simo

557 90e99856 Adeodato Simo
  """
558 90e99856 Adeodato Simo
  group_name = baserlib.CheckParameter(data, "name")
559 90e99856 Adeodato Simo
  alloc_policy = baserlib.CheckParameter(data, "alloc_policy", default=None)
560 90e99856 Adeodato Simo
561 90e99856 Adeodato Simo
  return opcodes.OpAddGroup(group_name=group_name,
562 90e99856 Adeodato Simo
                            alloc_policy=alloc_policy,
563 90e99856 Adeodato Simo
                            dry_run=dry_run)
564 90e99856 Adeodato Simo
565 90e99856 Adeodato Simo
566 0897dc97 Adeodato Simo
class R_2_groups(baserlib.R_Generic):
567 0897dc97 Adeodato Simo
  """/2/groups resource.
568 0897dc97 Adeodato Simo

569 0897dc97 Adeodato Simo
  """
570 0897dc97 Adeodato Simo
  def GET(self):
571 0897dc97 Adeodato Simo
    """Returns a list of all node groups.
572 0897dc97 Adeodato Simo

573 0897dc97 Adeodato Simo
    """
574 0897dc97 Adeodato Simo
    client = baserlib.GetClient()
575 0897dc97 Adeodato Simo
576 0897dc97 Adeodato Simo
    if self.useBulk():
577 0897dc97 Adeodato Simo
      bulkdata = client.QueryGroups([], G_FIELDS, False)
578 0897dc97 Adeodato Simo
      return baserlib.MapBulkFields(bulkdata, G_FIELDS)
579 0897dc97 Adeodato Simo
    else:
580 0897dc97 Adeodato Simo
      data = client.QueryGroups([], ["name"], False)
581 0897dc97 Adeodato Simo
      groupnames = [row[0] for row in data]
582 0897dc97 Adeodato Simo
      return baserlib.BuildUriList(groupnames, "/2/groups/%s",
583 0897dc97 Adeodato Simo
                                   uri_fields=("name", "uri"))
584 0897dc97 Adeodato Simo
585 0dbaa9ca Adeodato Simo
  def POST(self):
586 0dbaa9ca Adeodato Simo
    """Create a node group.
587 0dbaa9ca Adeodato Simo

588 0dbaa9ca Adeodato Simo
    @return: a job id
589 0dbaa9ca Adeodato Simo

590 0dbaa9ca Adeodato Simo
    """
591 0dbaa9ca Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
592 90e99856 Adeodato Simo
    op = _ParseCreateGroupRequest(self.request_body, self.dryRun())
593 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
594 0dbaa9ca Adeodato Simo
595 0897dc97 Adeodato Simo
596 0897dc97 Adeodato Simo
class R_2_groups_name(baserlib.R_Generic):
597 0897dc97 Adeodato Simo
  """/2/groups/[group_name] resources.
598 0897dc97 Adeodato Simo

599 0897dc97 Adeodato Simo
  """
600 0897dc97 Adeodato Simo
  def GET(self):
601 0897dc97 Adeodato Simo
    """Send information about a node group.
602 0897dc97 Adeodato Simo

603 0897dc97 Adeodato Simo
    """
604 0897dc97 Adeodato Simo
    group_name = self.items[0]
605 0897dc97 Adeodato Simo
    client = baserlib.GetClient()
606 0897dc97 Adeodato Simo
607 0897dc97 Adeodato Simo
    result = baserlib.HandleItemQueryErrors(client.QueryGroups,
608 0897dc97 Adeodato Simo
                                            names=[group_name], fields=G_FIELDS,
609 0897dc97 Adeodato Simo
                                            use_locking=self.useLocking())
610 0897dc97 Adeodato Simo
611 0897dc97 Adeodato Simo
    return baserlib.MapFields(G_FIELDS, result[0])
612 0897dc97 Adeodato Simo
613 0dbaa9ca Adeodato Simo
  def DELETE(self):
614 0dbaa9ca Adeodato Simo
    """Delete a node group.
615 0dbaa9ca Adeodato Simo

616 0dbaa9ca Adeodato Simo
    """
617 0dbaa9ca Adeodato Simo
    op = opcodes.OpRemoveGroup(group_name=self.items[0],
618 0dbaa9ca Adeodato Simo
                               dry_run=bool(self.dryRun()))
619 0dbaa9ca Adeodato Simo
620 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
621 0dbaa9ca Adeodato Simo
622 0dbaa9ca Adeodato Simo
623 f18fab7d Adeodato Simo
def _ParseModifyGroupRequest(name, data):
624 f18fab7d Adeodato Simo
  """Parses a request for modifying a node group.
625 f18fab7d Adeodato Simo

626 f18fab7d Adeodato Simo
  @rtype: L{opcodes.OpSetGroupParams}
627 f18fab7d Adeodato Simo
  @return: Group modify opcode
628 f18fab7d Adeodato Simo

629 f18fab7d Adeodato Simo
  """
630 f18fab7d Adeodato Simo
  alloc_policy = baserlib.CheckParameter(data, "alloc_policy", default=None)
631 f18fab7d Adeodato Simo
  return opcodes.OpSetGroupParams(group_name=name, alloc_policy=alloc_policy)
632 f18fab7d Adeodato Simo
633 f18fab7d Adeodato Simo
634 f18fab7d Adeodato Simo
class R_2_groups_name_modify(baserlib.R_Generic):
635 f18fab7d Adeodato Simo
  """/2/groups/[group_name]/modify resource.
636 f18fab7d Adeodato Simo

637 f18fab7d Adeodato Simo
  """
638 f18fab7d Adeodato Simo
  def PUT(self):
639 f18fab7d Adeodato Simo
    """Changes some parameters of node group.
640 f18fab7d Adeodato Simo

641 f18fab7d Adeodato Simo
    @return: a job id
642 f18fab7d Adeodato Simo

643 f18fab7d Adeodato Simo
    """
644 f18fab7d Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
645 f18fab7d Adeodato Simo
646 f18fab7d Adeodato Simo
    op = _ParseModifyGroupRequest(self.items[0], self.request_body)
647 f18fab7d Adeodato Simo
648 f18fab7d Adeodato Simo
    return baserlib.SubmitJob([op])
649 f18fab7d Adeodato Simo
650 f18fab7d Adeodato Simo
651 0dbaa9ca Adeodato Simo
def _ParseRenameGroupRequest(name, data, dry_run):
652 0dbaa9ca Adeodato Simo
  """Parses a request for renaming a node group.
653 0dbaa9ca Adeodato Simo

654 0dbaa9ca Adeodato Simo
  @type name: string
655 0dbaa9ca Adeodato Simo
  @param name: name of the node group to rename
656 0dbaa9ca Adeodato Simo
  @type data: dict
657 0dbaa9ca Adeodato Simo
  @param data: the body received by the rename request
658 0dbaa9ca Adeodato Simo
  @type dry_run: bool
659 0dbaa9ca Adeodato Simo
  @param dry_run: whether to perform a dry run
660 0dbaa9ca Adeodato Simo

661 0dbaa9ca Adeodato Simo
  @rtype: L{opcodes.OpRenameGroup}
662 0dbaa9ca Adeodato Simo
  @return: Node group rename opcode
663 0dbaa9ca Adeodato Simo

664 0dbaa9ca Adeodato Simo
  """
665 0dbaa9ca Adeodato Simo
  old_name = name
666 0dbaa9ca Adeodato Simo
  new_name = baserlib.CheckParameter(data, "new_name")
667 0dbaa9ca Adeodato Simo
668 0dbaa9ca Adeodato Simo
  return opcodes.OpRenameGroup(old_name=old_name, new_name=new_name,
669 0dbaa9ca Adeodato Simo
                               dry_run=dry_run)
670 0dbaa9ca Adeodato Simo
671 0dbaa9ca Adeodato Simo
672 0dbaa9ca Adeodato Simo
class R_2_groups_name_rename(baserlib.R_Generic):
673 0dbaa9ca Adeodato Simo
  """/2/groups/[groupe_name]/rename resource.
674 0dbaa9ca Adeodato Simo

675 0dbaa9ca Adeodato Simo
  """
676 0dbaa9ca Adeodato Simo
  def PUT(self):
677 0dbaa9ca Adeodato Simo
    """Changes the name of a node group.
678 0dbaa9ca Adeodato Simo

679 0dbaa9ca Adeodato Simo
    @return: a job id
680 0dbaa9ca Adeodato Simo

681 0dbaa9ca Adeodato Simo
    """
682 0dbaa9ca Adeodato Simo
    baserlib.CheckType(self.request_body, dict, "Body contents")
683 0dbaa9ca Adeodato Simo
    op = _ParseRenameGroupRequest(self.items[0], self.request_body,
684 0dbaa9ca Adeodato Simo
                                  self.dryRun())
685 0dbaa9ca Adeodato Simo
    return baserlib.SubmitJob([op])
686 0897dc97 Adeodato Simo
687 0897dc97 Adeodato Simo
688 6395cebb Michael Hanselmann
def _ParseInstanceCreateRequestVersion1(data, dry_run):
689 6395cebb Michael Hanselmann
  """Parses an instance creation request version 1.
690 6395cebb Michael Hanselmann

691 6395cebb Michael Hanselmann
  @rtype: L{opcodes.OpCreateInstance}
692 6395cebb Michael Hanselmann
  @return: Instance creation opcode
693 6395cebb Michael Hanselmann

694 6395cebb Michael Hanselmann
  """
695 6395cebb Michael Hanselmann
  # Disks
696 6395cebb Michael Hanselmann
  disks_input = baserlib.CheckParameter(data, "disks", exptype=list)
697 6395cebb Michael Hanselmann
698 6395cebb Michael Hanselmann
  disks = []
699 6395cebb Michael Hanselmann
  for idx, i in enumerate(disks_input):
700 6395cebb Michael Hanselmann
    baserlib.CheckType(i, dict, "Disk %d specification" % idx)
701 6395cebb Michael Hanselmann
702 6395cebb Michael Hanselmann
    # Size is mandatory
703 6395cebb Michael Hanselmann
    try:
704 7be048f0 Michael Hanselmann
      size = i[constants.IDISK_SIZE]
705 6395cebb Michael Hanselmann
    except KeyError:
706 6395cebb Michael Hanselmann
      raise http.HttpBadRequest("Disk %d specification wrong: missing disk"
707 6395cebb Michael Hanselmann
                                " size" % idx)
708 6395cebb Michael Hanselmann
709 6395cebb Michael Hanselmann
    disk = {
710 7be048f0 Michael Hanselmann
      constants.IDISK_SIZE: size,
711 6395cebb Michael Hanselmann
      }
712 6395cebb Michael Hanselmann
713 6395cebb Michael Hanselmann
    # Optional disk access mode
714 6395cebb Michael Hanselmann
    try:
715 7be048f0 Michael Hanselmann
      disk_access = i[constants.IDISK_MODE]
716 6395cebb Michael Hanselmann
    except KeyError:
717 6395cebb Michael Hanselmann
      pass
718 6395cebb Michael Hanselmann
    else:
719 7be048f0 Michael Hanselmann
      disk[constants.IDISK_MODE] = disk_access
720 6395cebb Michael Hanselmann
721 6395cebb Michael Hanselmann
    disks.append(disk)
722 6395cebb Michael Hanselmann
723 6395cebb Michael Hanselmann
  assert len(disks_input) == len(disks)
724 6395cebb Michael Hanselmann
725 6395cebb Michael Hanselmann
  # Network interfaces
726 6395cebb Michael Hanselmann
  nics_input = baserlib.CheckParameter(data, "nics", exptype=list)
727 6395cebb Michael Hanselmann
728 6395cebb Michael Hanselmann
  nics = []
729 6395cebb Michael Hanselmann
  for idx, i in enumerate(nics_input):
730 6395cebb Michael Hanselmann
    baserlib.CheckType(i, dict, "NIC %d specification" % idx)
731 6395cebb Michael Hanselmann
732 6395cebb Michael Hanselmann
    nic = {}
733 6395cebb Michael Hanselmann
734 7be048f0 Michael Hanselmann
    for field in constants.INIC_PARAMS:
735 6395cebb Michael Hanselmann
      try:
736 6395cebb Michael Hanselmann
        value = i[field]
737 6395cebb Michael Hanselmann
      except KeyError:
738 6395cebb Michael Hanselmann
        continue
739 6395cebb Michael Hanselmann
740 6395cebb Michael Hanselmann
      nic[field] = value
741 6395cebb Michael Hanselmann
742 6395cebb Michael Hanselmann
    nics.append(nic)
743 6395cebb Michael Hanselmann
744 6395cebb Michael Hanselmann
  assert len(nics_input) == len(nics)
745 6395cebb Michael Hanselmann
746 6395cebb Michael Hanselmann
  # HV/BE parameters
747 6395cebb Michael Hanselmann
  hvparams = baserlib.CheckParameter(data, "hvparams", default={})
748 6395cebb Michael Hanselmann
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
749 6395cebb Michael Hanselmann
750 6395cebb Michael Hanselmann
  beparams = baserlib.CheckParameter(data, "beparams", default={})
751 6395cebb Michael Hanselmann
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
752 6395cebb Michael Hanselmann
753 6395cebb Michael Hanselmann
  return opcodes.OpCreateInstance(
754 6395cebb Michael Hanselmann
    mode=baserlib.CheckParameter(data, "mode"),
755 6395cebb Michael Hanselmann
    instance_name=baserlib.CheckParameter(data, "name"),
756 130f0966 Iustin Pop
    os_type=baserlib.CheckParameter(data, "os"),
757 130f0966 Iustin Pop
    osparams=baserlib.CheckParameter(data, "osparams", default={}),
758 6395cebb Michael Hanselmann
    force_variant=baserlib.CheckParameter(data, "force_variant",
759 6395cebb Michael Hanselmann
                                          default=False),
760 04a8865b Lance Albertson
    no_install=baserlib.CheckParameter(data, "no_install", default=False),
761 6395cebb Michael Hanselmann
    pnode=baserlib.CheckParameter(data, "pnode", default=None),
762 6395cebb Michael Hanselmann
    snode=baserlib.CheckParameter(data, "snode", default=None),
763 6395cebb Michael Hanselmann
    disk_template=baserlib.CheckParameter(data, "disk_template"),
764 6395cebb Michael Hanselmann
    disks=disks,
765 6395cebb Michael Hanselmann
    nics=nics,
766 6395cebb Michael Hanselmann
    src_node=baserlib.CheckParameter(data, "src_node", default=None),
767 6395cebb Michael Hanselmann
    src_path=baserlib.CheckParameter(data, "src_path", default=None),
768 6395cebb Michael Hanselmann
    start=baserlib.CheckParameter(data, "start", default=True),
769 6395cebb Michael Hanselmann
    wait_for_sync=True,
770 6395cebb Michael Hanselmann
    ip_check=baserlib.CheckParameter(data, "ip_check", default=True),
771 6395cebb Michael Hanselmann
    name_check=baserlib.CheckParameter(data, "name_check", default=True),
772 6395cebb Michael Hanselmann
    file_storage_dir=baserlib.CheckParameter(data, "file_storage_dir",
773 6395cebb Michael Hanselmann
                                             default=None),
774 6395cebb Michael Hanselmann
    file_driver=baserlib.CheckParameter(data, "file_driver",
775 6395cebb Michael Hanselmann
                                        default=constants.FD_LOOP),
776 ebeb600f Michael Hanselmann
    source_handshake=baserlib.CheckParameter(data, "source_handshake",
777 ebeb600f Michael Hanselmann
                                             default=None),
778 ebeb600f Michael Hanselmann
    source_x509_ca=baserlib.CheckParameter(data, "source_x509_ca",
779 ebeb600f Michael Hanselmann
                                           default=None),
780 ebeb600f Michael Hanselmann
    source_instance_name=baserlib.CheckParameter(data, "source_instance_name",
781 ebeb600f Michael Hanselmann
                                                 default=None),
782 6395cebb Michael Hanselmann
    iallocator=baserlib.CheckParameter(data, "iallocator", default=None),
783 6395cebb Michael Hanselmann
    hypervisor=baserlib.CheckParameter(data, "hypervisor", default=None),
784 6395cebb Michael Hanselmann
    hvparams=hvparams,
785 6395cebb Michael Hanselmann
    beparams=beparams,
786 6395cebb Michael Hanselmann
    dry_run=dry_run,
787 6395cebb Michael Hanselmann
    )
788 6395cebb Michael Hanselmann
789 6395cebb Michael Hanselmann
790 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
791 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
792 441e7cfd Oleksiy Mishchenko

793 441e7cfd Oleksiy Mishchenko
  """
794 441e7cfd Oleksiy Mishchenko
  def GET(self):
795 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
796 441e7cfd Oleksiy Mishchenko

797 441e7cfd Oleksiy Mishchenko
    """
798 59b4eeef Iustin Pop
    client = baserlib.GetClient()
799 441e7cfd Oleksiy Mishchenko
800 3d103742 Iustin Pop
    use_locking = self.useLocking()
801 3d103742 Iustin Pop
    if self.useBulk():
802 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
803 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
804 441e7cfd Oleksiy Mishchenko
    else:
805 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
806 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
807 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
808 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
809 441e7cfd Oleksiy Mishchenko
810 d975f482 Michael Hanselmann
  def _ParseVersion0CreateRequest(self):
811 d975f482 Michael Hanselmann
    """Parses an instance creation request version 0.
812 2f7635f4 Oleksiy Mishchenko

813 6395cebb Michael Hanselmann
    Request data version 0 is deprecated and should not be used anymore.
814 2f7635f4 Oleksiy Mishchenko

815 d975f482 Michael Hanselmann
    @rtype: L{opcodes.OpCreateInstance}
816 d975f482 Michael Hanselmann
    @return: Instance creation opcode
817 6e99c5a0 Iustin Pop

818 2f7635f4 Oleksiy Mishchenko
    """
819 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
820 627ad739 Michael Hanselmann
    beparams = baserlib.MakeParamsDict(self.request_body,
821 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
822 627ad739 Michael Hanselmann
    hvparams = baserlib.MakeParamsDict(self.request_body,
823 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
824 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
825 6e99c5a0 Iustin Pop
826 6e99c5a0 Iustin Pop
    # disk processing
827 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
828 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
829 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
830 6e99c5a0 Iustin Pop
    disks = []
831 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
832 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
833 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
834 69b99987 Michael Hanselmann
                                  " be an integer" % idx)
835 6e99c5a0 Iustin Pop
      disks.append({"size": d})
836 d975f482 Michael Hanselmann
837 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
838 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
839 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
840 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
841 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
842 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
843 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
844 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
845 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
846 69b99987 Michael Hanselmann
      nics[0]["bridge"] = fn("bridge")
847 2f7635f4 Oleksiy Mishchenko
848 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
849 d975f482 Michael Hanselmann
    return opcodes.OpCreateInstance(
850 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
851 59b4eeef Iustin Pop
      instance_name=fn('name'),
852 59b4eeef Iustin Pop
      disks=disks,
853 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
854 59b4eeef Iustin Pop
      os_type=fn('os'),
855 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
856 59b4eeef Iustin Pop
      snode=fn('snode', None),
857 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
858 59b4eeef Iustin Pop
      nics=nics,
859 59b4eeef Iustin Pop
      start=fn('start', True),
860 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
861 460d22be Iustin Pop
      name_check=fn('name_check', True),
862 59b4eeef Iustin Pop
      wait_for_sync=True,
863 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
864 59b4eeef Iustin Pop
      hvparams=hvparams,
865 59b4eeef Iustin Pop
      beparams=beparams,
866 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
867 6395cebb Michael Hanselmann
      file_driver=fn('file_driver', constants.FD_LOOP),
868 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
869 59b4eeef Iustin Pop
      )
870 59b4eeef Iustin Pop
871 d975f482 Michael Hanselmann
  def POST(self):
872 d975f482 Michael Hanselmann
    """Create an instance.
873 d975f482 Michael Hanselmann

874 d975f482 Michael Hanselmann
    @return: a job id
875 d975f482 Michael Hanselmann

876 d975f482 Michael Hanselmann
    """
877 1c54156d Luca Bigliardi
    if not isinstance(self.request_body, dict):
878 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
879 d975f482 Michael Hanselmann
880 d975f482 Michael Hanselmann
    # Default to request data version 0
881 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
882 d975f482 Michael Hanselmann
883 d975f482 Michael Hanselmann
    if data_version == 0:
884 d975f482 Michael Hanselmann
      op = self._ParseVersion0CreateRequest()
885 6395cebb Michael Hanselmann
    elif data_version == 1:
886 1c54156d Luca Bigliardi
      op = _ParseInstanceCreateRequestVersion1(self.request_body,
887 6395cebb Michael Hanselmann
                                               self.dryRun())
888 d975f482 Michael Hanselmann
    else:
889 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
890 12eff9b9 Michael Hanselmann
                                data_version)
891 d975f482 Michael Hanselmann
892 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
893 2f7635f4 Oleksiy Mishchenko
894 441e7cfd Oleksiy Mishchenko
895 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
896 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
897 028c6b76 Oleksiy Mishchenko

898 028c6b76 Oleksiy Mishchenko
  """
899 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
900 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
901 4e5a68f8 Oleksiy Mishchenko

902 4e5a68f8 Oleksiy Mishchenko
    """
903 59b4eeef Iustin Pop
    client = baserlib.GetClient()
904 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
905 e8ebbd2b Michael Hanselmann
906 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryInstances,
907 e8ebbd2b Michael Hanselmann
                                            names=[instance_name],
908 e8ebbd2b Michael Hanselmann
                                            fields=I_FIELDS,
909 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
910 4e5a68f8 Oleksiy Mishchenko
911 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
912 028c6b76 Oleksiy Mishchenko
913 6e99c5a0 Iustin Pop
  def DELETE(self):
914 6e99c5a0 Iustin Pop
    """Delete an instance.
915 6e99c5a0 Iustin Pop

916 6e99c5a0 Iustin Pop
    """
917 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
918 6f59b964 Iustin Pop
                                  ignore_failures=False,
919 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
920 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
921 6e99c5a0 Iustin Pop
922 028c6b76 Oleksiy Mishchenko
923 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
924 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
925 d8260842 Michael Hanselmann

926 d8260842 Michael Hanselmann
  """
927 d8260842 Michael Hanselmann
  def GET(self):
928 d8260842 Michael Hanselmann
    """Request detailed instance information.
929 d8260842 Michael Hanselmann

930 d8260842 Michael Hanselmann
    """
931 d8260842 Michael Hanselmann
    instance_name = self.items[0]
932 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
933 d8260842 Michael Hanselmann
934 d8260842 Michael Hanselmann
    op = opcodes.OpQueryInstanceData(instances=[instance_name],
935 d8260842 Michael Hanselmann
                                     static=static)
936 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
937 d8260842 Michael Hanselmann
938 d8260842 Michael Hanselmann
939 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
940 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
941 2276aa29 Oleksiy Mishchenko

942 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
943 2276aa29 Oleksiy Mishchenko

944 2276aa29 Oleksiy Mishchenko
  """
945 21f04e5e Oleksiy Mishchenko
  def POST(self):
946 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
947 2276aa29 Oleksiy Mishchenko

948 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
949 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
950 0c55c24b Oleksiy Mishchenko

951 2276aa29 Oleksiy Mishchenko
    """
952 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
953 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
954 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
955 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
956 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
957 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
958 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
959 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
960 2276aa29 Oleksiy Mishchenko
961 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
962 2276aa29 Oleksiy Mishchenko
963 2276aa29 Oleksiy Mishchenko
964 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
965 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
966 0c55c24b Oleksiy Mishchenko

967 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
968 0c55c24b Oleksiy Mishchenko

969 0c55c24b Oleksiy Mishchenko
  """
970 21f04e5e Oleksiy Mishchenko
  def PUT(self):
971 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
972 0c55c24b Oleksiy Mishchenko

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

976 0c55c24b Oleksiy Mishchenko
    """
977 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
978 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
979 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
980 6f59b964 Iustin Pop
                                   force=force_startup,
981 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
982 0c55c24b Oleksiy Mishchenko
983 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
984 0c55c24b Oleksiy Mishchenko
985 0c55c24b Oleksiy Mishchenko
986 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
987 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
988 0c55c24b Oleksiy Mishchenko

989 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
990 0c55c24b Oleksiy Mishchenko

991 0c55c24b Oleksiy Mishchenko
  """
992 21f04e5e Oleksiy Mishchenko
  def PUT(self):
993 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
994 0c55c24b Oleksiy Mishchenko

995 0c55c24b Oleksiy Mishchenko
    """
996 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
997 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
998 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
999 0c55c24b Oleksiy Mishchenko
1000 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
1001 0c55c24b Oleksiy Mishchenko
1002 0c55c24b Oleksiy Mishchenko
1003 c744425f Michael Hanselmann
def _ParseInstanceReinstallRequest(name, data):
1004 c744425f Michael Hanselmann
  """Parses a request for reinstalling an instance.
1005 c744425f Michael Hanselmann

1006 c744425f Michael Hanselmann
  """
1007 c744425f Michael Hanselmann
  if not isinstance(data, dict):
1008 c744425f Michael Hanselmann
    raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1009 c744425f Michael Hanselmann
1010 c744425f Michael Hanselmann
  ostype = baserlib.CheckParameter(data, "os")
1011 c744425f Michael Hanselmann
  start = baserlib.CheckParameter(data, "start", exptype=bool,
1012 c744425f Michael Hanselmann
                                  default=True)
1013 c744425f Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default=None)
1014 c744425f Michael Hanselmann
1015 c744425f Michael Hanselmann
  ops = [
1016 c744425f Michael Hanselmann
    opcodes.OpShutdownInstance(instance_name=name),
1017 c744425f Michael Hanselmann
    opcodes.OpReinstallInstance(instance_name=name, os_type=ostype,
1018 c744425f Michael Hanselmann
                                osparams=osparams),
1019 c744425f Michael Hanselmann
    ]
1020 c744425f Michael Hanselmann
1021 c744425f Michael Hanselmann
  if start:
1022 c744425f Michael Hanselmann
    ops.append(opcodes.OpStartupInstance(instance_name=name, force=False))
1023 c744425f Michael Hanselmann
1024 c744425f Michael Hanselmann
  return ops
1025 c744425f Michael Hanselmann
1026 c744425f Michael Hanselmann
1027 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
1028 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
1029 e5b7c4ca Iustin Pop

1030 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
1031 e5b7c4ca Iustin Pop

1032 e5b7c4ca Iustin Pop
  """
1033 e5b7c4ca Iustin Pop
  def POST(self):
1034 e5b7c4ca Iustin Pop
    """Reinstall an instance.
1035 e5b7c4ca Iustin Pop

1036 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
1037 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
1038 e5b7c4ca Iustin Pop
    automatically.
1039 e5b7c4ca Iustin Pop

1040 e5b7c4ca Iustin Pop
    """
1041 c744425f Michael Hanselmann
    if self.request_body:
1042 c744425f Michael Hanselmann
      if self.queryargs:
1043 c744425f Michael Hanselmann
        raise http.HttpBadRequest("Can't combine query and body parameters")
1044 c744425f Michael Hanselmann
1045 c744425f Michael Hanselmann
      body = self.request_body
1046 c744425f Michael Hanselmann
    else:
1047 c744425f Michael Hanselmann
      if not self.queryargs:
1048 c744425f Michael Hanselmann
        raise http.HttpBadRequest("Missing query parameters")
1049 c744425f Michael Hanselmann
      # Legacy interface, do not modify/extend
1050 c744425f Michael Hanselmann
      body = {
1051 c744425f Michael Hanselmann
        "os": self._checkStringVariable("os"),
1052 c744425f Michael Hanselmann
        "start": not self._checkIntVariable("nostartup"),
1053 c744425f Michael Hanselmann
        }
1054 c744425f Michael Hanselmann
1055 c744425f Michael Hanselmann
    ops = _ParseInstanceReinstallRequest(self.items[0], body)
1056 c744425f Michael Hanselmann
1057 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
1058 e5b7c4ca Iustin Pop
1059 e5b7c4ca Iustin Pop
1060 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
1061 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
1062 4c98b915 Michael Hanselmann

1063 4c98b915 Michael Hanselmann
  """
1064 4c98b915 Michael Hanselmann
  def POST(self):
1065 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
1066 4c98b915 Michael Hanselmann

1067 4c98b915 Michael Hanselmann
    """
1068 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
1069 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
1070 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
1071 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
1072 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
1073 4c98b915 Michael Hanselmann
1074 4c98b915 Michael Hanselmann
    if raw_disks:
1075 4c98b915 Michael Hanselmann
      try:
1076 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
1077 4c98b915 Michael Hanselmann
      except ValueError, err:
1078 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
1079 4c98b915 Michael Hanselmann
    else:
1080 4c98b915 Michael Hanselmann
      disks = []
1081 4c98b915 Michael Hanselmann
1082 4c98b915 Michael Hanselmann
    op = opcodes.OpReplaceDisks(instance_name=instance_name,
1083 4c98b915 Michael Hanselmann
                                remote_node=remote_node,
1084 4c98b915 Michael Hanselmann
                                mode=mode,
1085 4c98b915 Michael Hanselmann
                                disks=disks,
1086 4c98b915 Michael Hanselmann
                                iallocator=iallocator)
1087 4c98b915 Michael Hanselmann
1088 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
1089 4c98b915 Michael Hanselmann
1090 4c98b915 Michael Hanselmann
1091 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
1092 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
1093 2197b66f René Nussbaumer

1094 2197b66f René Nussbaumer
  """
1095 2197b66f René Nussbaumer
  def PUT(self):
1096 2197b66f René Nussbaumer
    """Activate disks for an instance.
1097 2197b66f René Nussbaumer

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

1100 2197b66f René Nussbaumer
    """
1101 2197b66f René Nussbaumer
    instance_name = self.items[0]
1102 2197b66f René Nussbaumer
    ignore_size = bool(self._checkIntVariable('ignore_size'))
1103 2197b66f René Nussbaumer
1104 2197b66f René Nussbaumer
    op = opcodes.OpActivateInstanceDisks(instance_name=instance_name,
1105 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
1106 2197b66f René Nussbaumer
1107 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
1108 2197b66f René Nussbaumer
1109 2197b66f René Nussbaumer
1110 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
1111 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
1112 0a37de5f René Nussbaumer

1113 0a37de5f René Nussbaumer
  """
1114 0a37de5f René Nussbaumer
  def PUT(self):
1115 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
1116 0a37de5f René Nussbaumer

1117 0a37de5f René Nussbaumer
    """
1118 0a37de5f René Nussbaumer
    instance_name = self.items[0]
1119 0a37de5f René Nussbaumer
1120 2263aec2 René Nussbaumer
    op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
1121 0a37de5f René Nussbaumer
1122 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
1123 0a37de5f René Nussbaumer
1124 0a37de5f René Nussbaumer
1125 ebeb600f Michael Hanselmann
class R_2_instances_name_prepare_export(baserlib.R_Generic):
1126 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/prepare-export resource.
1127 ebeb600f Michael Hanselmann

1128 ebeb600f Michael Hanselmann
  """
1129 ebeb600f Michael Hanselmann
  def PUT(self):
1130 ebeb600f Michael Hanselmann
    """Prepares an export for an instance.
1131 ebeb600f Michael Hanselmann

1132 ebeb600f Michael Hanselmann
    @return: a job id
1133 ebeb600f Michael Hanselmann

1134 ebeb600f Michael Hanselmann
    """
1135 ebeb600f Michael Hanselmann
    instance_name = self.items[0]
1136 ebeb600f Michael Hanselmann
    mode = self._checkStringVariable("mode")
1137 ebeb600f Michael Hanselmann
1138 ebeb600f Michael Hanselmann
    op = opcodes.OpPrepareExport(instance_name=instance_name,
1139 ebeb600f Michael Hanselmann
                                 mode=mode)
1140 ebeb600f Michael Hanselmann
1141 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1142 ebeb600f Michael Hanselmann
1143 ebeb600f Michael Hanselmann
1144 ebeb600f Michael Hanselmann
def _ParseExportInstanceRequest(name, data):
1145 ebeb600f Michael Hanselmann
  """Parses a request for an instance export.
1146 ebeb600f Michael Hanselmann

1147 ebeb600f Michael Hanselmann
  @rtype: L{opcodes.OpExportInstance}
1148 ebeb600f Michael Hanselmann
  @return: Instance export opcode
1149 ebeb600f Michael Hanselmann

1150 ebeb600f Michael Hanselmann
  """
1151 ebeb600f Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode",
1152 ebeb600f Michael Hanselmann
                                 default=constants.EXPORT_MODE_LOCAL)
1153 ebeb600f Michael Hanselmann
  target_node = baserlib.CheckParameter(data, "destination")
1154 ebeb600f Michael Hanselmann
  shutdown = baserlib.CheckParameter(data, "shutdown", exptype=bool)
1155 ebeb600f Michael Hanselmann
  remove_instance = baserlib.CheckParameter(data, "remove_instance",
1156 ebeb600f Michael Hanselmann
                                            exptype=bool, default=False)
1157 ebeb600f Michael Hanselmann
  x509_key_name = baserlib.CheckParameter(data, "x509_key_name", default=None)
1158 ebeb600f Michael Hanselmann
  destination_x509_ca = baserlib.CheckParameter(data, "destination_x509_ca",
1159 ebeb600f Michael Hanselmann
                                                default=None)
1160 ebeb600f Michael Hanselmann
1161 ebeb600f Michael Hanselmann
  return opcodes.OpExportInstance(instance_name=name,
1162 ebeb600f Michael Hanselmann
                                  mode=mode,
1163 ebeb600f Michael Hanselmann
                                  target_node=target_node,
1164 ebeb600f Michael Hanselmann
                                  shutdown=shutdown,
1165 ebeb600f Michael Hanselmann
                                  remove_instance=remove_instance,
1166 ebeb600f Michael Hanselmann
                                  x509_key_name=x509_key_name,
1167 ebeb600f Michael Hanselmann
                                  destination_x509_ca=destination_x509_ca)
1168 ebeb600f Michael Hanselmann
1169 ebeb600f Michael Hanselmann
1170 ebeb600f Michael Hanselmann
class R_2_instances_name_export(baserlib.R_Generic):
1171 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/export resource.
1172 ebeb600f Michael Hanselmann

1173 ebeb600f Michael Hanselmann
  """
1174 ebeb600f Michael Hanselmann
  def PUT(self):
1175 ebeb600f Michael Hanselmann
    """Exports an instance.
1176 ebeb600f Michael Hanselmann

1177 ebeb600f Michael Hanselmann
    @return: a job id
1178 ebeb600f Michael Hanselmann

1179 ebeb600f Michael Hanselmann
    """
1180 ebeb600f Michael Hanselmann
    if not isinstance(self.request_body, dict):
1181 ebeb600f Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1182 ebeb600f Michael Hanselmann
1183 ebeb600f Michael Hanselmann
    op = _ParseExportInstanceRequest(self.items[0], self.request_body)
1184 ebeb600f Michael Hanselmann
1185 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1186 ebeb600f Michael Hanselmann
1187 ebeb600f Michael Hanselmann
1188 5823e0d2 Michael Hanselmann
def _ParseMigrateInstanceRequest(name, data):
1189 5823e0d2 Michael Hanselmann
  """Parses a request for an instance migration.
1190 5823e0d2 Michael Hanselmann

1191 5823e0d2 Michael Hanselmann
  @rtype: L{opcodes.OpMigrateInstance}
1192 5823e0d2 Michael Hanselmann
  @return: Instance migration opcode
1193 5823e0d2 Michael Hanselmann

1194 5823e0d2 Michael Hanselmann
  """
1195 5823e0d2 Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode", default=None)
1196 5823e0d2 Michael Hanselmann
  cleanup = baserlib.CheckParameter(data, "cleanup", exptype=bool,
1197 5823e0d2 Michael Hanselmann
                                    default=False)
1198 5823e0d2 Michael Hanselmann
1199 5823e0d2 Michael Hanselmann
  return opcodes.OpMigrateInstance(instance_name=name, mode=mode,
1200 5823e0d2 Michael Hanselmann
                                   cleanup=cleanup)
1201 5823e0d2 Michael Hanselmann
1202 5823e0d2 Michael Hanselmann
1203 5823e0d2 Michael Hanselmann
class R_2_instances_name_migrate(baserlib.R_Generic):
1204 5823e0d2 Michael Hanselmann
  """/2/instances/[instance_name]/migrate resource.
1205 5823e0d2 Michael Hanselmann

1206 5823e0d2 Michael Hanselmann
  """
1207 5823e0d2 Michael Hanselmann
  def PUT(self):
1208 5823e0d2 Michael Hanselmann
    """Migrates an instance.
1209 5823e0d2 Michael Hanselmann

1210 5823e0d2 Michael Hanselmann
    @return: a job id
1211 5823e0d2 Michael Hanselmann

1212 5823e0d2 Michael Hanselmann
    """
1213 5823e0d2 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1214 5823e0d2 Michael Hanselmann
1215 5823e0d2 Michael Hanselmann
    op = _ParseMigrateInstanceRequest(self.items[0], self.request_body)
1216 5823e0d2 Michael Hanselmann
1217 5823e0d2 Michael Hanselmann
    return baserlib.SubmitJob([op])
1218 5823e0d2 Michael Hanselmann
1219 5823e0d2 Michael Hanselmann
1220 d56e7dc7 Michael Hanselmann
def _ParseRenameInstanceRequest(name, data):
1221 d56e7dc7 Michael Hanselmann
  """Parses a request for renaming an instance.
1222 d56e7dc7 Michael Hanselmann

1223 d56e7dc7 Michael Hanselmann
  @rtype: L{opcodes.OpRenameInstance}
1224 d56e7dc7 Michael Hanselmann
  @return: Instance rename opcode
1225 d56e7dc7 Michael Hanselmann

1226 d56e7dc7 Michael Hanselmann
  """
1227 d56e7dc7 Michael Hanselmann
  new_name = baserlib.CheckParameter(data, "new_name")
1228 d56e7dc7 Michael Hanselmann
  ip_check = baserlib.CheckParameter(data, "ip_check", default=True)
1229 d56e7dc7 Michael Hanselmann
  name_check = baserlib.CheckParameter(data, "name_check", default=True)
1230 d56e7dc7 Michael Hanselmann
1231 d56e7dc7 Michael Hanselmann
  return opcodes.OpRenameInstance(instance_name=name, new_name=new_name,
1232 d56e7dc7 Michael Hanselmann
                                  name_check=name_check, ip_check=ip_check)
1233 d56e7dc7 Michael Hanselmann
1234 d56e7dc7 Michael Hanselmann
1235 d56e7dc7 Michael Hanselmann
class R_2_instances_name_rename(baserlib.R_Generic):
1236 d56e7dc7 Michael Hanselmann
  """/2/instances/[instance_name]/rename resource.
1237 d56e7dc7 Michael Hanselmann

1238 d56e7dc7 Michael Hanselmann
  """
1239 d56e7dc7 Michael Hanselmann
  def PUT(self):
1240 d56e7dc7 Michael Hanselmann
    """Changes the name of an instance.
1241 d56e7dc7 Michael Hanselmann

1242 d56e7dc7 Michael Hanselmann
    @return: a job id
1243 d56e7dc7 Michael Hanselmann

1244 d56e7dc7 Michael Hanselmann
    """
1245 d56e7dc7 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1246 d56e7dc7 Michael Hanselmann
1247 d56e7dc7 Michael Hanselmann
    op = _ParseRenameInstanceRequest(self.items[0], self.request_body)
1248 d56e7dc7 Michael Hanselmann
1249 d56e7dc7 Michael Hanselmann
    return baserlib.SubmitJob([op])
1250 d56e7dc7 Michael Hanselmann
1251 d56e7dc7 Michael Hanselmann
1252 3882937a Michael Hanselmann
def _ParseModifyInstanceRequest(name, data):
1253 3882937a Michael Hanselmann
  """Parses a request for modifying an instance.
1254 3882937a Michael Hanselmann

1255 3882937a Michael Hanselmann
  @rtype: L{opcodes.OpSetInstanceParams}
1256 3882937a Michael Hanselmann
  @return: Instance modify opcode
1257 3882937a Michael Hanselmann

1258 3882937a Michael Hanselmann
  """
1259 3882937a Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default={})
1260 3882937a Michael Hanselmann
  force = baserlib.CheckParameter(data, "force", default=False)
1261 3882937a Michael Hanselmann
  nics = baserlib.CheckParameter(data, "nics", default=[])
1262 3882937a Michael Hanselmann
  disks = baserlib.CheckParameter(data, "disks", default=[])
1263 3882937a Michael Hanselmann
  disk_template = baserlib.CheckParameter(data, "disk_template", default=None)
1264 3882937a Michael Hanselmann
  remote_node = baserlib.CheckParameter(data, "remote_node", default=None)
1265 3882937a Michael Hanselmann
  os_name = baserlib.CheckParameter(data, "os_name", default=None)
1266 3882937a Michael Hanselmann
  force_variant = baserlib.CheckParameter(data, "force_variant", default=False)
1267 3882937a Michael Hanselmann
1268 3882937a Michael Hanselmann
  # HV/BE parameters
1269 3882937a Michael Hanselmann
  hvparams = baserlib.CheckParameter(data, "hvparams", default={})
1270 3882937a Michael Hanselmann
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES,
1271 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1272 3882937a Michael Hanselmann
1273 3882937a Michael Hanselmann
  beparams = baserlib.CheckParameter(data, "beparams", default={})
1274 3882937a Michael Hanselmann
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES,
1275 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1276 3882937a Michael Hanselmann
1277 3882937a Michael Hanselmann
  return opcodes.OpSetInstanceParams(instance_name=name, hvparams=hvparams,
1278 3882937a Michael Hanselmann
                                     beparams=beparams, osparams=osparams,
1279 3882937a Michael Hanselmann
                                     force=force, nics=nics, disks=disks,
1280 3882937a Michael Hanselmann
                                     disk_template=disk_template,
1281 3882937a Michael Hanselmann
                                     remote_node=remote_node, os_name=os_name,
1282 3882937a Michael Hanselmann
                                     force_variant=force_variant)
1283 3882937a Michael Hanselmann
1284 3882937a Michael Hanselmann
1285 3882937a Michael Hanselmann
class R_2_instances_name_modify(baserlib.R_Generic):
1286 3882937a Michael Hanselmann
  """/2/instances/[instance_name]/modify resource.
1287 3882937a Michael Hanselmann

1288 3882937a Michael Hanselmann
  """
1289 3882937a Michael Hanselmann
  def PUT(self):
1290 3882937a Michael Hanselmann
    """Changes some parameters of an instance.
1291 3882937a Michael Hanselmann

1292 3882937a Michael Hanselmann
    @return: a job id
1293 3882937a Michael Hanselmann

1294 3882937a Michael Hanselmann
    """
1295 3882937a Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1296 3882937a Michael Hanselmann
1297 3882937a Michael Hanselmann
    op = _ParseModifyInstanceRequest(self.items[0], self.request_body)
1298 3882937a Michael Hanselmann
1299 3882937a Michael Hanselmann
    return baserlib.SubmitJob([op])
1300 3882937a Michael Hanselmann
1301 3882937a Michael Hanselmann
1302 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
1303 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
1304 441e7cfd Oleksiy Mishchenko

1305 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
1306 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
1307 441e7cfd Oleksiy Mishchenko

1308 441e7cfd Oleksiy Mishchenko
  """
1309 7a6b9510 Iustin Pop
  TAG_LEVEL = None
1310 18cb43a2 Oleksiy Mishchenko
1311 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
1312 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
1313 18cb43a2 Oleksiy Mishchenko

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

1316 18cb43a2 Oleksiy Mishchenko
    """
1317 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
1318 18cb43a2 Oleksiy Mishchenko
1319 5313eed7 Michael Hanselmann
    if self.TAG_LEVEL == constants.TAG_CLUSTER:
1320 5313eed7 Michael Hanselmann
      self.name = None
1321 18cb43a2 Oleksiy Mishchenko
    else:
1322 5313eed7 Michael Hanselmann
      self.name = items[0]
1323 441e7cfd Oleksiy Mishchenko
1324 441e7cfd Oleksiy Mishchenko
  def GET(self):
1325 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
1326 441e7cfd Oleksiy Mishchenko

1327 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
1328 441e7cfd Oleksiy Mishchenko

1329 441e7cfd Oleksiy Mishchenko
    """
1330 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1331 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
1332 441e7cfd Oleksiy Mishchenko
1333 21f04e5e Oleksiy Mishchenko
  def PUT(self):
1334 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
1335 441e7cfd Oleksiy Mishchenko

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

1339 441e7cfd Oleksiy Mishchenko
    """
1340 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1341 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
1342 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
1343 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
1344 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
1345 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
1346 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
1347 15fd9fd5 Oleksiy Mishchenko
1348 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
1349 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
1350 15fd9fd5 Oleksiy Mishchenko

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

1355 15fd9fd5 Oleksiy Mishchenko
    """
1356 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1357 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
1358 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
1359 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
1360 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
1361 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
1362 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
1363 6f59b964 Iustin Pop
                                 name=self.name,
1364 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
1365 18cb43a2 Oleksiy Mishchenko
1366 18cb43a2 Oleksiy Mishchenko
1367 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
1368 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
1369 18cb43a2 Oleksiy Mishchenko

1370 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
1371 18cb43a2 Oleksiy Mishchenko

1372 18cb43a2 Oleksiy Mishchenko
  """
1373 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
1374 18cb43a2 Oleksiy Mishchenko
1375 18cb43a2 Oleksiy Mishchenko
1376 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
1377 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
1378 18cb43a2 Oleksiy Mishchenko

1379 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
1380 18cb43a2 Oleksiy Mishchenko

1381 18cb43a2 Oleksiy Mishchenko
  """
1382 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
1383 18cb43a2 Oleksiy Mishchenko
1384 18cb43a2 Oleksiy Mishchenko
1385 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
1386 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
1387 18cb43a2 Oleksiy Mishchenko

1388 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
1389 18cb43a2 Oleksiy Mishchenko

1390 18cb43a2 Oleksiy Mishchenko
  """
1391 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER