Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 7056a05b

History | View | Annotate | Download (41.6 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 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 b58a4d16 Michael Hanselmann
  """/2/info resource.
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 da2d02e7 Iustin Pop
    op = opcodes.OpOsDiagnose(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 d1240007 Iustin Pop
    return baserlib.SubmitJob([opcodes.OpClusterRedistConf()])
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 a6682fdc Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpClusterSetParams, 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 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name] resource.
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 f13973c4 Iustin Pop
    op = opcodes.OpNodeSetParams(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 0ae89533 Iustin Pop
    op = opcodes.OpNodeEvacStrategy(nodes=[node_name],
424 0ae89533 Iustin Pop
                                    iallocator=iallocator,
425 0ae89533 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 63ea9789 Iustin Pop
    for iname, node in result[0]:
433 941b9309 Iustin Pop
      if dry_run:
434 941b9309 Iustin Pop
        jid = None
435 941b9309 Iustin Pop
      else:
436 668f755d Iustin Pop
        op = opcodes.OpInstanceReplaceDisks(instance_name=iname,
437 668f755d Iustin Pop
                                            remote_node=node, disks=[],
438 668f755d Iustin Pop
                                            mode=constants.REPLACE_DISK_CHG,
439 668f755d 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 5b14a488 Iustin Pop
    op = opcodes.OpNodeMigrate(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 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage resource.
474 7a95a954 Michael Hanselmann

475 7a95a954 Michael Hanselmann
  """
476 ad8d0595 Iustin Pop
  # LUNodeQueryStorage 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 ad8d0595 Iustin Pop
    op = opcodes.OpNodeQueryStorage(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 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify resource.
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 2cee4077 Iustin Pop
    op = opcodes.OpNodeModifyStorage(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 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair resource.
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 fabf1731 Iustin Pop
  @rtype: L{opcodes.OpGroupAdd}
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 fabf1731 Iustin Pop
  return opcodes.OpGroupAdd(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 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name] resource.
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 4d1baa51 Iustin Pop
    op = opcodes.OpGroupRemove(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 7cbf74f0 Iustin Pop
  @rtype: L{opcodes.OpGroupSetParams}
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 7cbf74f0 Iustin Pop
  return opcodes.OpGroupSetParams(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 a8173e82 Iustin Pop
  @rtype: L{opcodes.OpGroupRename}
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 a8173e82 Iustin Pop
  return opcodes.OpGroupRename(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 b58a4d16 Michael Hanselmann
  """/2/groups/[group_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 4245446f Adeodato Simo
class R_2_groups_name_assign_nodes(baserlib.R_Generic):
689 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name]/assign-nodes resource.
690 4245446f Adeodato Simo

691 4245446f Adeodato Simo
  """
692 4245446f Adeodato Simo
  def PUT(self):
693 4245446f Adeodato Simo
    """Assigns nodes to a group.
694 4245446f Adeodato Simo

695 4245446f Adeodato Simo
    @return: a job id
696 4245446f Adeodato Simo

697 4245446f Adeodato Simo
    """
698 934704ae Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpGroupAssignNodes, self.request_body, {
699 4245446f Adeodato Simo
      "group_name": self.items[0],
700 4245446f Adeodato Simo
      "dry_run": self.dryRun(),
701 4245446f Adeodato Simo
      "force": self.useForce(),
702 4245446f Adeodato Simo
      })
703 4245446f Adeodato Simo
704 4245446f Adeodato Simo
    return baserlib.SubmitJob([op])
705 4245446f Adeodato Simo
706 4245446f Adeodato Simo
707 6395cebb Michael Hanselmann
def _ParseInstanceCreateRequestVersion1(data, dry_run):
708 6395cebb Michael Hanselmann
  """Parses an instance creation request version 1.
709 6395cebb Michael Hanselmann

710 e1530b10 Iustin Pop
  @rtype: L{opcodes.OpInstanceCreate}
711 6395cebb Michael Hanselmann
  @return: Instance creation opcode
712 6395cebb Michael Hanselmann

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

813 441e7cfd Oleksiy Mishchenko
  """
814 441e7cfd Oleksiy Mishchenko
  def GET(self):
815 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
816 441e7cfd Oleksiy Mishchenko

817 441e7cfd Oleksiy Mishchenko
    """
818 59b4eeef Iustin Pop
    client = baserlib.GetClient()
819 441e7cfd Oleksiy Mishchenko
820 3d103742 Iustin Pop
    use_locking = self.useLocking()
821 3d103742 Iustin Pop
    if self.useBulk():
822 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
823 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
824 441e7cfd Oleksiy Mishchenko
    else:
825 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
826 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
827 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
828 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
829 441e7cfd Oleksiy Mishchenko
830 d975f482 Michael Hanselmann
  def _ParseVersion0CreateRequest(self):
831 d975f482 Michael Hanselmann
    """Parses an instance creation request version 0.
832 2f7635f4 Oleksiy Mishchenko

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

835 e1530b10 Iustin Pop
    @rtype: L{opcodes.OpInstanceCreate}
836 d975f482 Michael Hanselmann
    @return: Instance creation opcode
837 6e99c5a0 Iustin Pop

838 2f7635f4 Oleksiy Mishchenko
    """
839 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
840 627ad739 Michael Hanselmann
    beparams = baserlib.MakeParamsDict(self.request_body,
841 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
842 627ad739 Michael Hanselmann
    hvparams = baserlib.MakeParamsDict(self.request_body,
843 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
844 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
845 6e99c5a0 Iustin Pop
846 6e99c5a0 Iustin Pop
    # disk processing
847 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
848 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
849 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
850 6e99c5a0 Iustin Pop
    disks = []
851 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
852 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
853 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
854 69b99987 Michael Hanselmann
                                  " be an integer" % idx)
855 6e99c5a0 Iustin Pop
      disks.append({"size": d})
856 d975f482 Michael Hanselmann
857 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
858 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
859 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
860 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
861 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
862 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
863 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
864 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
865 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
866 69b99987 Michael Hanselmann
      nics[0]["bridge"] = fn("bridge")
867 2f7635f4 Oleksiy Mishchenko
868 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
869 e1530b10 Iustin Pop
    return opcodes.OpInstanceCreate(
870 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
871 59b4eeef Iustin Pop
      instance_name=fn('name'),
872 59b4eeef Iustin Pop
      disks=disks,
873 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
874 59b4eeef Iustin Pop
      os_type=fn('os'),
875 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
876 59b4eeef Iustin Pop
      snode=fn('snode', None),
877 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
878 59b4eeef Iustin Pop
      nics=nics,
879 59b4eeef Iustin Pop
      start=fn('start', True),
880 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
881 460d22be Iustin Pop
      name_check=fn('name_check', True),
882 59b4eeef Iustin Pop
      wait_for_sync=True,
883 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
884 59b4eeef Iustin Pop
      hvparams=hvparams,
885 59b4eeef Iustin Pop
      beparams=beparams,
886 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
887 6395cebb Michael Hanselmann
      file_driver=fn('file_driver', constants.FD_LOOP),
888 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
889 59b4eeef Iustin Pop
      )
890 59b4eeef Iustin Pop
891 d975f482 Michael Hanselmann
  def POST(self):
892 d975f482 Michael Hanselmann
    """Create an instance.
893 d975f482 Michael Hanselmann

894 d975f482 Michael Hanselmann
    @return: a job id
895 d975f482 Michael Hanselmann

896 d975f482 Michael Hanselmann
    """
897 1c54156d Luca Bigliardi
    if not isinstance(self.request_body, dict):
898 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
899 d975f482 Michael Hanselmann
900 d975f482 Michael Hanselmann
    # Default to request data version 0
901 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
902 d975f482 Michael Hanselmann
903 d975f482 Michael Hanselmann
    if data_version == 0:
904 d975f482 Michael Hanselmann
      op = self._ParseVersion0CreateRequest()
905 6395cebb Michael Hanselmann
    elif data_version == 1:
906 1c54156d Luca Bigliardi
      op = _ParseInstanceCreateRequestVersion1(self.request_body,
907 6395cebb Michael Hanselmann
                                               self.dryRun())
908 d975f482 Michael Hanselmann
    else:
909 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
910 12eff9b9 Michael Hanselmann
                                data_version)
911 d975f482 Michael Hanselmann
912 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
913 2f7635f4 Oleksiy Mishchenko
914 441e7cfd Oleksiy Mishchenko
915 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
916 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name] resource.
917 028c6b76 Oleksiy Mishchenko

918 028c6b76 Oleksiy Mishchenko
  """
919 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
920 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
921 4e5a68f8 Oleksiy Mishchenko

922 4e5a68f8 Oleksiy Mishchenko
    """
923 59b4eeef Iustin Pop
    client = baserlib.GetClient()
924 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
925 e8ebbd2b Michael Hanselmann
926 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryInstances,
927 e8ebbd2b Michael Hanselmann
                                            names=[instance_name],
928 e8ebbd2b Michael Hanselmann
                                            fields=I_FIELDS,
929 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
930 4e5a68f8 Oleksiy Mishchenko
931 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
932 028c6b76 Oleksiy Mishchenko
933 6e99c5a0 Iustin Pop
  def DELETE(self):
934 6e99c5a0 Iustin Pop
    """Delete an instance.
935 6e99c5a0 Iustin Pop

936 6e99c5a0 Iustin Pop
    """
937 3cd2d4b1 Iustin Pop
    op = opcodes.OpInstanceRemove(instance_name=self.items[0],
938 6f59b964 Iustin Pop
                                  ignore_failures=False,
939 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
940 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
941 6e99c5a0 Iustin Pop
942 028c6b76 Oleksiy Mishchenko
943 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
944 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
945 d8260842 Michael Hanselmann

946 d8260842 Michael Hanselmann
  """
947 d8260842 Michael Hanselmann
  def GET(self):
948 d8260842 Michael Hanselmann
    """Request detailed instance information.
949 d8260842 Michael Hanselmann

950 d8260842 Michael Hanselmann
    """
951 d8260842 Michael Hanselmann
    instance_name = self.items[0]
952 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
953 d8260842 Michael Hanselmann
954 dc28c4e4 Iustin Pop
    op = opcodes.OpInstanceQueryData(instances=[instance_name],
955 d8260842 Michael Hanselmann
                                     static=static)
956 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
957 d8260842 Michael Hanselmann
958 d8260842 Michael Hanselmann
959 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
960 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
961 2276aa29 Oleksiy Mishchenko

962 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
963 2276aa29 Oleksiy Mishchenko

964 2276aa29 Oleksiy Mishchenko
  """
965 21f04e5e Oleksiy Mishchenko
  def POST(self):
966 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
967 2276aa29 Oleksiy Mishchenko

968 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
969 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
970 0c55c24b Oleksiy Mishchenko

971 2276aa29 Oleksiy Mishchenko
    """
972 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
973 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
974 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
975 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
976 90ab1a95 Iustin Pop
    op = opcodes.OpInstanceReboot(instance_name=instance_name,
977 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
978 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
979 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
980 2276aa29 Oleksiy Mishchenko
981 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
982 2276aa29 Oleksiy Mishchenko
983 2276aa29 Oleksiy Mishchenko
984 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
985 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
986 0c55c24b Oleksiy Mishchenko

987 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
988 0c55c24b Oleksiy Mishchenko

989 0c55c24b Oleksiy Mishchenko
  """
990 21f04e5e Oleksiy Mishchenko
  def PUT(self):
991 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
992 0c55c24b Oleksiy Mishchenko

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

996 0c55c24b Oleksiy Mishchenko
    """
997 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
998 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
999 c873d91c Iustin Pop
    op = opcodes.OpInstanceStartup(instance_name=instance_name,
1000 6f59b964 Iustin Pop
                                   force=force_startup,
1001 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
1002 0c55c24b Oleksiy Mishchenko
1003 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
1004 0c55c24b Oleksiy Mishchenko
1005 0c55c24b Oleksiy Mishchenko
1006 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
1007 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
1008 0c55c24b Oleksiy Mishchenko

1009 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
1010 0c55c24b Oleksiy Mishchenko

1011 0c55c24b Oleksiy Mishchenko
  """
1012 21f04e5e Oleksiy Mishchenko
  def PUT(self):
1013 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
1014 0c55c24b Oleksiy Mishchenko

1015 0c55c24b Oleksiy Mishchenko
    """
1016 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
1017 ee3e37a7 Iustin Pop
    op = opcodes.OpInstanceShutdown(instance_name=instance_name,
1018 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
1019 0c55c24b Oleksiy Mishchenko
1020 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
1021 0c55c24b Oleksiy Mishchenko
1022 0c55c24b Oleksiy Mishchenko
1023 c744425f Michael Hanselmann
def _ParseInstanceReinstallRequest(name, data):
1024 c744425f Michael Hanselmann
  """Parses a request for reinstalling an instance.
1025 c744425f Michael Hanselmann

1026 c744425f Michael Hanselmann
  """
1027 c744425f Michael Hanselmann
  if not isinstance(data, dict):
1028 c744425f Michael Hanselmann
    raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1029 c744425f Michael Hanselmann
1030 bd0807fe Guido Trotter
  ostype = baserlib.CheckParameter(data, "os", default=None)
1031 c744425f Michael Hanselmann
  start = baserlib.CheckParameter(data, "start", exptype=bool,
1032 c744425f Michael Hanselmann
                                  default=True)
1033 c744425f Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default=None)
1034 c744425f Michael Hanselmann
1035 c744425f Michael Hanselmann
  ops = [
1036 ee3e37a7 Iustin Pop
    opcodes.OpInstanceShutdown(instance_name=name),
1037 5073fd8f Iustin Pop
    opcodes.OpInstanceReinstall(instance_name=name, os_type=ostype,
1038 c744425f Michael Hanselmann
                                osparams=osparams),
1039 c744425f Michael Hanselmann
    ]
1040 c744425f Michael Hanselmann
1041 c744425f Michael Hanselmann
  if start:
1042 c873d91c Iustin Pop
    ops.append(opcodes.OpInstanceStartup(instance_name=name, force=False))
1043 c744425f Michael Hanselmann
1044 c744425f Michael Hanselmann
  return ops
1045 c744425f Michael Hanselmann
1046 c744425f Michael Hanselmann
1047 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
1048 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
1049 e5b7c4ca Iustin Pop

1050 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
1051 e5b7c4ca Iustin Pop

1052 e5b7c4ca Iustin Pop
  """
1053 e5b7c4ca Iustin Pop
  def POST(self):
1054 e5b7c4ca Iustin Pop
    """Reinstall an instance.
1055 e5b7c4ca Iustin Pop

1056 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
1057 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
1058 e5b7c4ca Iustin Pop
    automatically.
1059 e5b7c4ca Iustin Pop

1060 e5b7c4ca Iustin Pop
    """
1061 c744425f Michael Hanselmann
    if self.request_body:
1062 c744425f Michael Hanselmann
      if self.queryargs:
1063 c744425f Michael Hanselmann
        raise http.HttpBadRequest("Can't combine query and body parameters")
1064 c744425f Michael Hanselmann
1065 c744425f Michael Hanselmann
      body = self.request_body
1066 bd0807fe Guido Trotter
    elif self.queryargs:
1067 c744425f Michael Hanselmann
      # Legacy interface, do not modify/extend
1068 c744425f Michael Hanselmann
      body = {
1069 c744425f Michael Hanselmann
        "os": self._checkStringVariable("os"),
1070 c744425f Michael Hanselmann
        "start": not self._checkIntVariable("nostartup"),
1071 c744425f Michael Hanselmann
        }
1072 bd0807fe Guido Trotter
    else:
1073 bd0807fe Guido Trotter
      body = {}
1074 c744425f Michael Hanselmann
1075 c744425f Michael Hanselmann
    ops = _ParseInstanceReinstallRequest(self.items[0], body)
1076 c744425f Michael Hanselmann
1077 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
1078 e5b7c4ca Iustin Pop
1079 e5b7c4ca Iustin Pop
1080 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
1081 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
1082 4c98b915 Michael Hanselmann

1083 4c98b915 Michael Hanselmann
  """
1084 4c98b915 Michael Hanselmann
  def POST(self):
1085 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
1086 4c98b915 Michael Hanselmann

1087 4c98b915 Michael Hanselmann
    """
1088 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
1089 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
1090 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
1091 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
1092 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
1093 4c98b915 Michael Hanselmann
1094 4c98b915 Michael Hanselmann
    if raw_disks:
1095 4c98b915 Michael Hanselmann
      try:
1096 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
1097 4c98b915 Michael Hanselmann
      except ValueError, err:
1098 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
1099 4c98b915 Michael Hanselmann
    else:
1100 4c98b915 Michael Hanselmann
      disks = []
1101 4c98b915 Michael Hanselmann
1102 668f755d Iustin Pop
    op = opcodes.OpInstanceReplaceDisks(instance_name=instance_name,
1103 668f755d Iustin Pop
                                        remote_node=remote_node,
1104 668f755d Iustin Pop
                                        mode=mode,
1105 668f755d Iustin Pop
                                        disks=disks,
1106 668f755d Iustin Pop
                                        iallocator=iallocator)
1107 4c98b915 Michael Hanselmann
1108 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
1109 4c98b915 Michael Hanselmann
1110 4c98b915 Michael Hanselmann
1111 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
1112 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
1113 2197b66f René Nussbaumer

1114 2197b66f René Nussbaumer
  """
1115 2197b66f René Nussbaumer
  def PUT(self):
1116 2197b66f René Nussbaumer
    """Activate disks for an instance.
1117 2197b66f René Nussbaumer

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

1120 2197b66f René Nussbaumer
    """
1121 2197b66f René Nussbaumer
    instance_name = self.items[0]
1122 2197b66f René Nussbaumer
    ignore_size = bool(self._checkIntVariable('ignore_size'))
1123 2197b66f René Nussbaumer
1124 83f5d475 Iustin Pop
    op = opcodes.OpInstanceActivateDisks(instance_name=instance_name,
1125 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
1126 2197b66f René Nussbaumer
1127 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
1128 2197b66f René Nussbaumer
1129 2197b66f René Nussbaumer
1130 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
1131 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
1132 0a37de5f René Nussbaumer

1133 0a37de5f René Nussbaumer
  """
1134 0a37de5f René Nussbaumer
  def PUT(self):
1135 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
1136 0a37de5f René Nussbaumer

1137 0a37de5f René Nussbaumer
    """
1138 0a37de5f René Nussbaumer
    instance_name = self.items[0]
1139 0a37de5f René Nussbaumer
1140 e176281f Iustin Pop
    op = opcodes.OpInstanceDeactivateDisks(instance_name=instance_name)
1141 0a37de5f René Nussbaumer
1142 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
1143 0a37de5f René Nussbaumer
1144 0a37de5f René Nussbaumer
1145 ebeb600f Michael Hanselmann
class R_2_instances_name_prepare_export(baserlib.R_Generic):
1146 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/prepare-export resource.
1147 ebeb600f Michael Hanselmann

1148 ebeb600f Michael Hanselmann
  """
1149 ebeb600f Michael Hanselmann
  def PUT(self):
1150 ebeb600f Michael Hanselmann
    """Prepares an export for an instance.
1151 ebeb600f Michael Hanselmann

1152 ebeb600f Michael Hanselmann
    @return: a job id
1153 ebeb600f Michael Hanselmann

1154 ebeb600f Michael Hanselmann
    """
1155 ebeb600f Michael Hanselmann
    instance_name = self.items[0]
1156 ebeb600f Michael Hanselmann
    mode = self._checkStringVariable("mode")
1157 ebeb600f Michael Hanselmann
1158 71910715 Iustin Pop
    op = opcodes.OpBackupPrepare(instance_name=instance_name,
1159 ebeb600f Michael Hanselmann
                                 mode=mode)
1160 ebeb600f Michael Hanselmann
1161 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1162 ebeb600f Michael Hanselmann
1163 ebeb600f Michael Hanselmann
1164 ebeb600f Michael Hanselmann
def _ParseExportInstanceRequest(name, data):
1165 ebeb600f Michael Hanselmann
  """Parses a request for an instance export.
1166 ebeb600f Michael Hanselmann

1167 4ff922a2 Iustin Pop
  @rtype: L{opcodes.OpBackupExport}
1168 ebeb600f Michael Hanselmann
  @return: Instance export opcode
1169 ebeb600f Michael Hanselmann

1170 ebeb600f Michael Hanselmann
  """
1171 ebeb600f Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode",
1172 ebeb600f Michael Hanselmann
                                 default=constants.EXPORT_MODE_LOCAL)
1173 ebeb600f Michael Hanselmann
  target_node = baserlib.CheckParameter(data, "destination")
1174 ebeb600f Michael Hanselmann
  shutdown = baserlib.CheckParameter(data, "shutdown", exptype=bool)
1175 ebeb600f Michael Hanselmann
  remove_instance = baserlib.CheckParameter(data, "remove_instance",
1176 ebeb600f Michael Hanselmann
                                            exptype=bool, default=False)
1177 ebeb600f Michael Hanselmann
  x509_key_name = baserlib.CheckParameter(data, "x509_key_name", default=None)
1178 ebeb600f Michael Hanselmann
  destination_x509_ca = baserlib.CheckParameter(data, "destination_x509_ca",
1179 ebeb600f Michael Hanselmann
                                                default=None)
1180 ebeb600f Michael Hanselmann
1181 4ff922a2 Iustin Pop
  return opcodes.OpBackupExport(instance_name=name,
1182 4ff922a2 Iustin Pop
                                mode=mode,
1183 4ff922a2 Iustin Pop
                                target_node=target_node,
1184 4ff922a2 Iustin Pop
                                shutdown=shutdown,
1185 4ff922a2 Iustin Pop
                                remove_instance=remove_instance,
1186 4ff922a2 Iustin Pop
                                x509_key_name=x509_key_name,
1187 4ff922a2 Iustin Pop
                                destination_x509_ca=destination_x509_ca)
1188 ebeb600f Michael Hanselmann
1189 ebeb600f Michael Hanselmann
1190 ebeb600f Michael Hanselmann
class R_2_instances_name_export(baserlib.R_Generic):
1191 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/export resource.
1192 ebeb600f Michael Hanselmann

1193 ebeb600f Michael Hanselmann
  """
1194 ebeb600f Michael Hanselmann
  def PUT(self):
1195 ebeb600f Michael Hanselmann
    """Exports an instance.
1196 ebeb600f Michael Hanselmann

1197 ebeb600f Michael Hanselmann
    @return: a job id
1198 ebeb600f Michael Hanselmann

1199 ebeb600f Michael Hanselmann
    """
1200 ebeb600f Michael Hanselmann
    if not isinstance(self.request_body, dict):
1201 ebeb600f Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1202 ebeb600f Michael Hanselmann
1203 ebeb600f Michael Hanselmann
    op = _ParseExportInstanceRequest(self.items[0], self.request_body)
1204 ebeb600f Michael Hanselmann
1205 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
1206 ebeb600f Michael Hanselmann
1207 ebeb600f Michael Hanselmann
1208 5823e0d2 Michael Hanselmann
def _ParseMigrateInstanceRequest(name, data):
1209 5823e0d2 Michael Hanselmann
  """Parses a request for an instance migration.
1210 5823e0d2 Michael Hanselmann

1211 75c866c2 Iustin Pop
  @rtype: L{opcodes.OpInstanceMigrate}
1212 5823e0d2 Michael Hanselmann
  @return: Instance migration opcode
1213 5823e0d2 Michael Hanselmann

1214 5823e0d2 Michael Hanselmann
  """
1215 5823e0d2 Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode", default=None)
1216 5823e0d2 Michael Hanselmann
  cleanup = baserlib.CheckParameter(data, "cleanup", exptype=bool,
1217 5823e0d2 Michael Hanselmann
                                    default=False)
1218 5823e0d2 Michael Hanselmann
1219 75c866c2 Iustin Pop
  return opcodes.OpInstanceMigrate(instance_name=name, mode=mode,
1220 5823e0d2 Michael Hanselmann
                                   cleanup=cleanup)
1221 5823e0d2 Michael Hanselmann
1222 5823e0d2 Michael Hanselmann
1223 5823e0d2 Michael Hanselmann
class R_2_instances_name_migrate(baserlib.R_Generic):
1224 5823e0d2 Michael Hanselmann
  """/2/instances/[instance_name]/migrate resource.
1225 5823e0d2 Michael Hanselmann

1226 5823e0d2 Michael Hanselmann
  """
1227 5823e0d2 Michael Hanselmann
  def PUT(self):
1228 5823e0d2 Michael Hanselmann
    """Migrates an instance.
1229 5823e0d2 Michael Hanselmann

1230 5823e0d2 Michael Hanselmann
    @return: a job id
1231 5823e0d2 Michael Hanselmann

1232 5823e0d2 Michael Hanselmann
    """
1233 5823e0d2 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1234 5823e0d2 Michael Hanselmann
1235 5823e0d2 Michael Hanselmann
    op = _ParseMigrateInstanceRequest(self.items[0], self.request_body)
1236 5823e0d2 Michael Hanselmann
1237 5823e0d2 Michael Hanselmann
    return baserlib.SubmitJob([op])
1238 5823e0d2 Michael Hanselmann
1239 5823e0d2 Michael Hanselmann
1240 d56e7dc7 Michael Hanselmann
def _ParseRenameInstanceRequest(name, data):
1241 d56e7dc7 Michael Hanselmann
  """Parses a request for renaming an instance.
1242 d56e7dc7 Michael Hanselmann

1243 5659e2e2 Iustin Pop
  @rtype: L{opcodes.OpInstanceRename}
1244 d56e7dc7 Michael Hanselmann
  @return: Instance rename opcode
1245 d56e7dc7 Michael Hanselmann

1246 d56e7dc7 Michael Hanselmann
  """
1247 d56e7dc7 Michael Hanselmann
  new_name = baserlib.CheckParameter(data, "new_name")
1248 d56e7dc7 Michael Hanselmann
  ip_check = baserlib.CheckParameter(data, "ip_check", default=True)
1249 d56e7dc7 Michael Hanselmann
  name_check = baserlib.CheckParameter(data, "name_check", default=True)
1250 d56e7dc7 Michael Hanselmann
1251 5659e2e2 Iustin Pop
  return opcodes.OpInstanceRename(instance_name=name, new_name=new_name,
1252 d56e7dc7 Michael Hanselmann
                                  name_check=name_check, ip_check=ip_check)
1253 d56e7dc7 Michael Hanselmann
1254 d56e7dc7 Michael Hanselmann
1255 d56e7dc7 Michael Hanselmann
class R_2_instances_name_rename(baserlib.R_Generic):
1256 d56e7dc7 Michael Hanselmann
  """/2/instances/[instance_name]/rename resource.
1257 d56e7dc7 Michael Hanselmann

1258 d56e7dc7 Michael Hanselmann
  """
1259 d56e7dc7 Michael Hanselmann
  def PUT(self):
1260 d56e7dc7 Michael Hanselmann
    """Changes the name of an instance.
1261 d56e7dc7 Michael Hanselmann

1262 d56e7dc7 Michael Hanselmann
    @return: a job id
1263 d56e7dc7 Michael Hanselmann

1264 d56e7dc7 Michael Hanselmann
    """
1265 d56e7dc7 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1266 d56e7dc7 Michael Hanselmann
1267 d56e7dc7 Michael Hanselmann
    op = _ParseRenameInstanceRequest(self.items[0], self.request_body)
1268 d56e7dc7 Michael Hanselmann
1269 d56e7dc7 Michael Hanselmann
    return baserlib.SubmitJob([op])
1270 d56e7dc7 Michael Hanselmann
1271 d56e7dc7 Michael Hanselmann
1272 3882937a Michael Hanselmann
def _ParseModifyInstanceRequest(name, data):
1273 3882937a Michael Hanselmann
  """Parses a request for modifying an instance.
1274 3882937a Michael Hanselmann

1275 9a3cc7ae Iustin Pop
  @rtype: L{opcodes.OpInstanceSetParams}
1276 3882937a Michael Hanselmann
  @return: Instance modify opcode
1277 3882937a Michael Hanselmann

1278 3882937a Michael Hanselmann
  """
1279 3882937a Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default={})
1280 3882937a Michael Hanselmann
  force = baserlib.CheckParameter(data, "force", default=False)
1281 3882937a Michael Hanselmann
  nics = baserlib.CheckParameter(data, "nics", default=[])
1282 3882937a Michael Hanselmann
  disks = baserlib.CheckParameter(data, "disks", default=[])
1283 3882937a Michael Hanselmann
  disk_template = baserlib.CheckParameter(data, "disk_template", default=None)
1284 3882937a Michael Hanselmann
  remote_node = baserlib.CheckParameter(data, "remote_node", default=None)
1285 3882937a Michael Hanselmann
  os_name = baserlib.CheckParameter(data, "os_name", default=None)
1286 3882937a Michael Hanselmann
  force_variant = baserlib.CheckParameter(data, "force_variant", default=False)
1287 3882937a Michael Hanselmann
1288 3882937a Michael Hanselmann
  # HV/BE parameters
1289 3882937a Michael Hanselmann
  hvparams = baserlib.CheckParameter(data, "hvparams", default={})
1290 3882937a Michael Hanselmann
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES,
1291 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1292 3882937a Michael Hanselmann
1293 3882937a Michael Hanselmann
  beparams = baserlib.CheckParameter(data, "beparams", default={})
1294 3882937a Michael Hanselmann
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES,
1295 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1296 3882937a Michael Hanselmann
1297 9a3cc7ae Iustin Pop
  return opcodes.OpInstanceSetParams(instance_name=name, hvparams=hvparams,
1298 3882937a Michael Hanselmann
                                     beparams=beparams, osparams=osparams,
1299 3882937a Michael Hanselmann
                                     force=force, nics=nics, disks=disks,
1300 3882937a Michael Hanselmann
                                     disk_template=disk_template,
1301 3882937a Michael Hanselmann
                                     remote_node=remote_node, os_name=os_name,
1302 3882937a Michael Hanselmann
                                     force_variant=force_variant)
1303 3882937a Michael Hanselmann
1304 3882937a Michael Hanselmann
1305 3882937a Michael Hanselmann
class R_2_instances_name_modify(baserlib.R_Generic):
1306 3882937a Michael Hanselmann
  """/2/instances/[instance_name]/modify resource.
1307 3882937a Michael Hanselmann

1308 3882937a Michael Hanselmann
  """
1309 3882937a Michael Hanselmann
  def PUT(self):
1310 3882937a Michael Hanselmann
    """Changes some parameters of an instance.
1311 3882937a Michael Hanselmann

1312 3882937a Michael Hanselmann
    @return: a job id
1313 3882937a Michael Hanselmann

1314 3882937a Michael Hanselmann
    """
1315 3882937a Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1316 3882937a Michael Hanselmann
1317 3882937a Michael Hanselmann
    op = _ParseModifyInstanceRequest(self.items[0], self.request_body)
1318 3882937a Michael Hanselmann
1319 3882937a Michael Hanselmann
    return baserlib.SubmitJob([op])
1320 3882937a Michael Hanselmann
1321 3882937a Michael Hanselmann
1322 e23881ed Michael Hanselmann
class R_2_instances_name_disk_grow(baserlib.R_Generic):
1323 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name]/disk/[disk_index]/grow resource.
1324 e23881ed Michael Hanselmann

1325 e23881ed Michael Hanselmann
  """
1326 e23881ed Michael Hanselmann
  def POST(self):
1327 e23881ed Michael Hanselmann
    """Increases the size of an instance disk.
1328 e23881ed Michael Hanselmann

1329 e23881ed Michael Hanselmann
    @return: a job id
1330 e23881ed Michael Hanselmann

1331 e23881ed Michael Hanselmann
    """
1332 60472d29 Iustin Pop
    op = baserlib.FillOpcode(opcodes.OpInstanceGrowDisk, self.request_body, {
1333 e23881ed Michael Hanselmann
      "instance_name": self.items[0],
1334 e23881ed Michael Hanselmann
      "disk": int(self.items[1]),
1335 e23881ed Michael Hanselmann
      })
1336 e23881ed Michael Hanselmann
1337 e23881ed Michael Hanselmann
    return baserlib.SubmitJob([op])
1338 e23881ed Michael Hanselmann
1339 e23881ed Michael Hanselmann
1340 b82d4c5e Michael Hanselmann
class R_2_instances_name_console(baserlib.R_Generic):
1341 b82d4c5e Michael Hanselmann
  """/2/instances/[instance_name]/console resource.
1342 b82d4c5e Michael Hanselmann

1343 b82d4c5e Michael Hanselmann
  """
1344 b82d4c5e Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
1345 b82d4c5e Michael Hanselmann
1346 b82d4c5e Michael Hanselmann
  def GET(self):
1347 b82d4c5e Michael Hanselmann
    """Request information for connecting to instance's console.
1348 b82d4c5e Michael Hanselmann

1349 b82d4c5e Michael Hanselmann
    @return: Serialized instance console description, see
1350 b82d4c5e Michael Hanselmann
             L{objects.InstanceConsole}
1351 b82d4c5e Michael Hanselmann

1352 b82d4c5e Michael Hanselmann
    """
1353 b82d4c5e Michael Hanselmann
    client = baserlib.GetClient()
1354 b82d4c5e Michael Hanselmann
1355 b82d4c5e Michael Hanselmann
    ((console, ), ) = client.QueryInstances([self.items[0]], ["console"], False)
1356 b82d4c5e Michael Hanselmann
1357 b82d4c5e Michael Hanselmann
    if console is None:
1358 b82d4c5e Michael Hanselmann
      raise http.HttpServiceUnavailable("Instance console unavailable")
1359 b82d4c5e Michael Hanselmann
1360 b82d4c5e Michael Hanselmann
    assert isinstance(console, dict)
1361 b82d4c5e Michael Hanselmann
    return console
1362 b82d4c5e Michael Hanselmann
1363 b82d4c5e Michael Hanselmann
1364 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
1365 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
1366 441e7cfd Oleksiy Mishchenko

1367 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
1368 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
1369 441e7cfd Oleksiy Mishchenko

1370 441e7cfd Oleksiy Mishchenko
  """
1371 7a6b9510 Iustin Pop
  TAG_LEVEL = None
1372 18cb43a2 Oleksiy Mishchenko
1373 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
1374 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
1375 18cb43a2 Oleksiy Mishchenko

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

1378 18cb43a2 Oleksiy Mishchenko
    """
1379 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
1380 18cb43a2 Oleksiy Mishchenko
1381 5313eed7 Michael Hanselmann
    if self.TAG_LEVEL == constants.TAG_CLUSTER:
1382 5313eed7 Michael Hanselmann
      self.name = None
1383 18cb43a2 Oleksiy Mishchenko
    else:
1384 5313eed7 Michael Hanselmann
      self.name = items[0]
1385 441e7cfd Oleksiy Mishchenko
1386 441e7cfd Oleksiy Mishchenko
  def GET(self):
1387 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
1388 441e7cfd Oleksiy Mishchenko

1389 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
1390 441e7cfd Oleksiy Mishchenko

1391 441e7cfd Oleksiy Mishchenko
    """
1392 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1393 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
1394 441e7cfd Oleksiy Mishchenko
1395 21f04e5e Oleksiy Mishchenko
  def PUT(self):
1396 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
1397 441e7cfd Oleksiy Mishchenko

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

1401 441e7cfd Oleksiy Mishchenko
    """
1402 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1403 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
1404 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
1405 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
1406 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
1407 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
1408 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
1409 15fd9fd5 Oleksiy Mishchenko
1410 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
1411 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
1412 15fd9fd5 Oleksiy Mishchenko

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

1417 15fd9fd5 Oleksiy Mishchenko
    """
1418 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1419 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
1420 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
1421 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
1422 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
1423 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
1424 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
1425 6f59b964 Iustin Pop
                                 name=self.name,
1426 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
1427 18cb43a2 Oleksiy Mishchenko
1428 18cb43a2 Oleksiy Mishchenko
1429 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
1430 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
1431 18cb43a2 Oleksiy Mishchenko

1432 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
1433 18cb43a2 Oleksiy Mishchenko

1434 18cb43a2 Oleksiy Mishchenko
  """
1435 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
1436 18cb43a2 Oleksiy Mishchenko
1437 18cb43a2 Oleksiy Mishchenko
1438 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
1439 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
1440 18cb43a2 Oleksiy Mishchenko

1441 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
1442 18cb43a2 Oleksiy Mishchenko

1443 18cb43a2 Oleksiy Mishchenko
  """
1444 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
1445 18cb43a2 Oleksiy Mishchenko
1446 18cb43a2 Oleksiy Mishchenko
1447 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
1448 b58a4d16 Michael Hanselmann
  """ /2/tags resource.
1449 18cb43a2 Oleksiy Mishchenko

1450 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
1451 18cb43a2 Oleksiy Mishchenko

1452 18cb43a2 Oleksiy Mishchenko
  """
1453 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER