Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 12eff9b9

History | View | Annotate | Download (23.9 kB)

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

24 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 8381fa2d Michael Hanselmann
from ganeti import rapi
49 38206f3c Iustin Pop
from ganeti.rapi import baserlib
50 10b207d4 Oleksiy Mishchenko
51 4e5a68f8 Oleksiy Mishchenko
52 7118a0df Iustin Pop
_COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
53 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
54 9031ee8e Iustin Pop
            "pnode", "snodes",
55 9031ee8e Iustin Pop
            "disk_template",
56 82e186f8 Michael Hanselmann
            "nic.ips", "nic.macs", "nic.modes", "nic.links", "nic.bridges",
57 a8b16c4e Tim Boring
            "network_port",
58 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
59 a5b9d725 Iustin Pop
            "beparams", "hvparams",
60 9031ee8e Iustin Pop
            "oper_state", "oper_ram", "status",
61 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
62 9031ee8e Iustin Pop
63 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
64 9031ee8e Iustin Pop
            "dtotal", "dfree",
65 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
66 7118a0df Iustin Pop
            "pinst_cnt", "sinst_cnt",
67 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
68 7118a0df Iustin Pop
            "pip", "sip", "role",
69 93962b80 Iustin Pop
            "pinst_list", "sinst_list",
70 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
71 4e5a68f8 Oleksiy Mishchenko
72 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
73 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
74 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
75 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
76 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
77 64dae8fc Michael Hanselmann
78 64dae8fc Michael Hanselmann
_NR_MAP = {
79 64dae8fc Michael Hanselmann
  "M": _NR_MASTER,
80 64dae8fc Michael Hanselmann
  "C": _NR_MASTER_CANDIATE,
81 64dae8fc Michael Hanselmann
  "D": _NR_DRAINED,
82 64dae8fc Michael Hanselmann
  "O": _NR_OFFLINE,
83 64dae8fc Michael Hanselmann
  "R": _NR_REGULAR,
84 64dae8fc Michael Hanselmann
  }
85 64dae8fc Michael Hanselmann
86 d975f482 Michael Hanselmann
# Request data version field
87 d975f482 Michael Hanselmann
_REQ_DATA_VERSION = "__version__"
88 d975f482 Michael Hanselmann
89 793a8f7c Michael Hanselmann
# Timeout for /2/jobs/[job_id]/wait. Gives job up to 10 seconds to change.
90 793a8f7c Michael Hanselmann
_WFJC_TIMEOUT = 10
91 793a8f7c Michael Hanselmann
92 4e5a68f8 Oleksiy Mishchenko
93 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
94 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
95 4e5a68f8 Oleksiy Mishchenko

96 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
97 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
98 4e5a68f8 Oleksiy Mishchenko

99 4e5a68f8 Oleksiy Mishchenko
  """
100 7e950d31 Iustin Pop
  @staticmethod
101 7e950d31 Iustin Pop
  def GET():
102 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
103 4e5a68f8 Oleksiy Mishchenko

104 4e5a68f8 Oleksiy Mishchenko
    """
105 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
106 4e5a68f8 Oleksiy Mishchenko
107 4e5a68f8 Oleksiy Mishchenko
108 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
109 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
110 4e5a68f8 Oleksiy Mishchenko

111 4e5a68f8 Oleksiy Mishchenko
  """
112 7e950d31 Iustin Pop
  @staticmethod
113 7e950d31 Iustin Pop
  def GET():
114 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
115 4e5a68f8 Oleksiy Mishchenko

116 4e5a68f8 Oleksiy Mishchenko
    """
117 59b4eeef Iustin Pop
    client = baserlib.GetClient()
118 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
119 4e5a68f8 Oleksiy Mishchenko
120 4e5a68f8 Oleksiy Mishchenko
121 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
122 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
123 4e5a68f8 Oleksiy Mishchenko

124 4e5a68f8 Oleksiy Mishchenko
  """
125 7e950d31 Iustin Pop
  @staticmethod
126 7e950d31 Iustin Pop
  def GET():
127 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
128 4e5a68f8 Oleksiy Mishchenko

129 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
130 4e5a68f8 Oleksiy Mishchenko

131 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
132 4e5a68f8 Oleksiy Mishchenko

133 4e5a68f8 Oleksiy Mishchenko
    """
134 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
135 e3ac208c Guido Trotter
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid", "variants"],
136 e3ac208c Guido Trotter
                              names=[])
137 59b4eeef Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
138 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
139 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
140 59b4eeef Iustin Pop
    diagnose_data = result[0]
141 4e5a68f8 Oleksiy Mishchenko
142 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
143 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
144 4e5a68f8 Oleksiy Mishchenko
145 e3ac208c Guido Trotter
    os_names = []
146 e3ac208c Guido Trotter
    for (name, valid, variants) in diagnose_data:
147 e3ac208c Guido Trotter
      if valid:
148 e3ac208c Guido Trotter
        os_names.extend(cli.CalculateOSNames(name, variants))
149 e3ac208c Guido Trotter
150 e3ac208c Guido Trotter
    return os_names
151 51ee2f49 Oleksiy Mishchenko
152 10b207d4 Oleksiy Mishchenko
153 508e9b20 Michael Hanselmann
class R_2_redist_config(baserlib.R_Generic):
154 508e9b20 Michael Hanselmann
  """/2/redistribute-config resource.
155 508e9b20 Michael Hanselmann

156 508e9b20 Michael Hanselmann
  """
157 7e950d31 Iustin Pop
  @staticmethod
158 7e950d31 Iustin Pop
  def PUT():
159 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
160 508e9b20 Michael Hanselmann

161 508e9b20 Michael Hanselmann
    """
162 508e9b20 Michael Hanselmann
    return baserlib.SubmitJob([opcodes.OpRedistributeConfig()])
163 508e9b20 Michael Hanselmann
164 508e9b20 Michael Hanselmann
165 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
166 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
167 10b207d4 Oleksiy Mishchenko

168 10b207d4 Oleksiy Mishchenko
  """
169 7e950d31 Iustin Pop
  @staticmethod
170 7e950d31 Iustin Pop
  def GET():
171 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
172 10b207d4 Oleksiy Mishchenko

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

175 10b207d4 Oleksiy Mishchenko
    """
176 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
177 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
178 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
179 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
180 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
181 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
182 10b207d4 Oleksiy Mishchenko
183 10b207d4 Oleksiy Mishchenko
184 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
185 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
186 10b207d4 Oleksiy Mishchenko

187 10b207d4 Oleksiy Mishchenko
  """
188 10b207d4 Oleksiy Mishchenko
  def GET(self):
189 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
190 10b207d4 Oleksiy Mishchenko

191 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
192 c41eea6e Iustin Pop
        The result includes:
193 c41eea6e Iustin Pop
            - id: job ID as a number
194 c41eea6e Iustin Pop
            - status: current job status as a string
195 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
196 c41eea6e Iustin Pop
              opcodes in the job
197 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
198 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
199 38206f3c Iustin Pop

200 10b207d4 Oleksiy Mishchenko
    """
201 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
202 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
203 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
204 ee69c97f Iustin Pop
              ]
205 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
206 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
207 ee69c97f Iustin Pop
    if result is None:
208 ee69c97f Iustin Pop
      raise http.HttpNotFound()
209 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
210 10b207d4 Oleksiy Mishchenko
211 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
212 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
213 c7f5f338 Oleksiy Mishchenko

214 c7f5f338 Oleksiy Mishchenko
    """
215 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
216 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
217 c7f5f338 Oleksiy Mishchenko
    return result
218 c7f5f338 Oleksiy Mishchenko
219 10b207d4 Oleksiy Mishchenko
220 793a8f7c Michael Hanselmann
class R_2_jobs_id_wait(baserlib.R_Generic):
221 793a8f7c Michael Hanselmann
  """/2/jobs/[job_id]/wait resource.
222 793a8f7c Michael Hanselmann

223 793a8f7c Michael Hanselmann
  """
224 793a8f7c Michael Hanselmann
  # WaitForJobChange provides access to sensitive information and blocks
225 793a8f7c Michael Hanselmann
  # machine resources (it's a blocking RAPI call), hence restricting access.
226 793a8f7c Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
227 793a8f7c Michael Hanselmann
228 793a8f7c Michael Hanselmann
  def GET(self):
229 793a8f7c Michael Hanselmann
    """Waits for job changes.
230 793a8f7c Michael Hanselmann

231 793a8f7c Michael Hanselmann
    """
232 793a8f7c Michael Hanselmann
    job_id = self.items[0]
233 793a8f7c Michael Hanselmann
234 793a8f7c Michael Hanselmann
    fields = self.getBodyParameter("fields")
235 793a8f7c Michael Hanselmann
    prev_job_info = self.getBodyParameter("previous_job_info", None)
236 793a8f7c Michael Hanselmann
    prev_log_serial = self.getBodyParameter("previous_log_serial", None)
237 793a8f7c Michael Hanselmann
238 793a8f7c Michael Hanselmann
    if not isinstance(fields, list):
239 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'fields' parameter should be a list")
240 793a8f7c Michael Hanselmann
241 793a8f7c Michael Hanselmann
    if not (prev_job_info is None or isinstance(prev_job_info, list)):
242 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_job_info' parameter should"
243 793a8f7c Michael Hanselmann
                                " be a list")
244 793a8f7c Michael Hanselmann
245 793a8f7c Michael Hanselmann
    if not (prev_log_serial is None or
246 793a8f7c Michael Hanselmann
            isinstance(prev_log_serial, (int, long))):
247 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_log_serial' parameter should"
248 793a8f7c Michael Hanselmann
                                " be a number")
249 793a8f7c Michael Hanselmann
250 793a8f7c Michael Hanselmann
    client = baserlib.GetClient()
251 793a8f7c Michael Hanselmann
    result = client.WaitForJobChangeOnce(job_id, fields,
252 793a8f7c Michael Hanselmann
                                         prev_job_info, prev_log_serial,
253 793a8f7c Michael Hanselmann
                                         timeout=_WFJC_TIMEOUT)
254 793a8f7c Michael Hanselmann
    if not result:
255 793a8f7c Michael Hanselmann
      raise http.HttpNotFound()
256 793a8f7c Michael Hanselmann
257 793a8f7c Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
258 793a8f7c Michael Hanselmann
      # No changes
259 793a8f7c Michael Hanselmann
      return None
260 793a8f7c Michael Hanselmann
261 793a8f7c Michael Hanselmann
    (job_info, log_entries) = result
262 793a8f7c Michael Hanselmann
263 793a8f7c Michael Hanselmann
    return {
264 793a8f7c Michael Hanselmann
      "job_info": job_info,
265 793a8f7c Michael Hanselmann
      "log_entries": log_entries,
266 793a8f7c Michael Hanselmann
      }
267 793a8f7c Michael Hanselmann
268 793a8f7c Michael Hanselmann
269 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
270 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
271 10b207d4 Oleksiy Mishchenko

272 10b207d4 Oleksiy Mishchenko
  """
273 10b207d4 Oleksiy Mishchenko
  def GET(self):
274 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
275 38206f3c Iustin Pop

276 10b207d4 Oleksiy Mishchenko
    """
277 59b4eeef Iustin Pop
    client = baserlib.GetClient()
278 38206f3c Iustin Pop
279 3d103742 Iustin Pop
    if self.useBulk():
280 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
281 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
282 9031ee8e Iustin Pop
    else:
283 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
284 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
285 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
286 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
287 441e7cfd Oleksiy Mishchenko
288 441e7cfd Oleksiy Mishchenko
289 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
290 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
291 028c6b76 Oleksiy Mishchenko

292 028c6b76 Oleksiy Mishchenko
  """
293 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
294 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
295 4e5a68f8 Oleksiy Mishchenko

296 4e5a68f8 Oleksiy Mishchenko
    """
297 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
298 59b4eeef Iustin Pop
    client = baserlib.GetClient()
299 9031ee8e Iustin Pop
    result = client.QueryNodes(names=[node_name], fields=N_FIELDS,
300 3d103742 Iustin Pop
                               use_locking=self.useLocking())
301 4e5a68f8 Oleksiy Mishchenko
302 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
303 028c6b76 Oleksiy Mishchenko
304 028c6b76 Oleksiy Mishchenko
305 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
306 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
307 64dae8fc Michael Hanselmann

308 64dae8fc Michael Hanselmann
  """
309 64dae8fc Michael Hanselmann
  def GET(self):
310 64dae8fc Michael Hanselmann
    """Returns the current node role.
311 64dae8fc Michael Hanselmann

312 64dae8fc Michael Hanselmann
    @return: Node role
313 64dae8fc Michael Hanselmann

314 64dae8fc Michael Hanselmann
    """
315 64dae8fc Michael Hanselmann
    node_name = self.items[0]
316 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
317 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
318 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
319 64dae8fc Michael Hanselmann
320 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
321 64dae8fc Michael Hanselmann
322 64dae8fc Michael Hanselmann
  def PUT(self):
323 64dae8fc Michael Hanselmann
    """Sets the node role.
324 64dae8fc Michael Hanselmann

325 64dae8fc Michael Hanselmann
    @return: a job id
326 64dae8fc Michael Hanselmann

327 64dae8fc Michael Hanselmann
    """
328 64dae8fc Michael Hanselmann
    if not isinstance(self.req.request_body, basestring):
329 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
330 64dae8fc Michael Hanselmann
331 64dae8fc Michael Hanselmann
    node_name = self.items[0]
332 64dae8fc Michael Hanselmann
    role = self.req.request_body
333 64dae8fc Michael Hanselmann
334 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
335 64dae8fc Michael Hanselmann
      candidate = False
336 64dae8fc Michael Hanselmann
      offline = False
337 64dae8fc Michael Hanselmann
      drained = False
338 64dae8fc Michael Hanselmann
339 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
340 64dae8fc Michael Hanselmann
      candidate = True
341 64dae8fc Michael Hanselmann
      offline = drained = None
342 64dae8fc Michael Hanselmann
343 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
344 64dae8fc Michael Hanselmann
      drained = True
345 64dae8fc Michael Hanselmann
      candidate = offline = None
346 64dae8fc Michael Hanselmann
347 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
348 64dae8fc Michael Hanselmann
      offline = True
349 64dae8fc Michael Hanselmann
      candidate = drained = None
350 64dae8fc Michael Hanselmann
351 64dae8fc Michael Hanselmann
    else:
352 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
353 64dae8fc Michael Hanselmann
354 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
355 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
356 64dae8fc Michael Hanselmann
                                 offline=offline,
357 64dae8fc Michael Hanselmann
                                 drained=drained,
358 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
359 64dae8fc Michael Hanselmann
360 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
361 64dae8fc Michael Hanselmann
362 64dae8fc Michael Hanselmann
363 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
364 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
365 73452f12 Michael Hanselmann

366 73452f12 Michael Hanselmann
  """
367 73452f12 Michael Hanselmann
  def POST(self):
368 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
369 73452f12 Michael Hanselmann

370 73452f12 Michael Hanselmann
    """
371 73452f12 Michael Hanselmann
    node_name = self.items[0]
372 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
373 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
374 73452f12 Michael Hanselmann
375 73452f12 Michael Hanselmann
    op = opcodes.OpEvacuateNode(node_name=node_name,
376 73452f12 Michael Hanselmann
                                remote_node=remote_node,
377 73452f12 Michael Hanselmann
                                iallocator=iallocator)
378 73452f12 Michael Hanselmann
379 73452f12 Michael Hanselmann
    return baserlib.SubmitJob([op])
380 73452f12 Michael Hanselmann
381 73452f12 Michael Hanselmann
382 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
383 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
384 1c482bab Michael Hanselmann

385 1c482bab Michael Hanselmann
  """
386 1c482bab Michael Hanselmann
  def POST(self):
387 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
388 1c482bab Michael Hanselmann

389 1c482bab Michael Hanselmann
    """
390 1c482bab Michael Hanselmann
    node_name = self.items[0]
391 1c482bab Michael Hanselmann
    live = bool(self._checkIntVariable("live", default=1))
392 1c482bab Michael Hanselmann
393 1c482bab Michael Hanselmann
    op = opcodes.OpMigrateNode(node_name=node_name, live=live)
394 1c482bab Michael Hanselmann
395 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
396 1c482bab Michael Hanselmann
397 1c482bab Michael Hanselmann
398 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
399 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
400 7a95a954 Michael Hanselmann

401 7a95a954 Michael Hanselmann
  """
402 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
403 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
404 7a95a954 Michael Hanselmann
405 7a95a954 Michael Hanselmann
  def GET(self):
406 7a95a954 Michael Hanselmann
    node_name = self.items[0]
407 7a95a954 Michael Hanselmann
408 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
409 7a95a954 Michael Hanselmann
    if not storage_type:
410 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
411 7a95a954 Michael Hanselmann
                                " parameter")
412 7a95a954 Michael Hanselmann
413 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
414 7a95a954 Michael Hanselmann
    if not output_fields:
415 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
416 7a95a954 Michael Hanselmann
                                " parameter")
417 7a95a954 Michael Hanselmann
418 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
419 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
420 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
421 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
422 7a95a954 Michael Hanselmann
423 7a95a954 Michael Hanselmann
424 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
425 1e82bc80 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify ressource.
426 1e82bc80 Michael Hanselmann

427 1e82bc80 Michael Hanselmann
  """
428 1e82bc80 Michael Hanselmann
  def PUT(self):
429 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
430 1e82bc80 Michael Hanselmann
431 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
432 1e82bc80 Michael Hanselmann
    if not storage_type:
433 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
434 1e82bc80 Michael Hanselmann
                                " parameter")
435 1e82bc80 Michael Hanselmann
436 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
437 1e82bc80 Michael Hanselmann
    if not name:
438 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
439 1e82bc80 Michael Hanselmann
                                " parameter")
440 1e82bc80 Michael Hanselmann
441 1e82bc80 Michael Hanselmann
    changes = {}
442 1e82bc80 Michael Hanselmann
443 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
444 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
445 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
446 1e82bc80 Michael Hanselmann
447 1e82bc80 Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
448 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
449 1e82bc80 Michael Hanselmann
                                     name=name,
450 1e82bc80 Michael Hanselmann
                                     changes=changes)
451 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
452 1e82bc80 Michael Hanselmann
453 1e82bc80 Michael Hanselmann
454 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
455 723f4565 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair ressource.
456 723f4565 Michael Hanselmann

457 723f4565 Michael Hanselmann
  """
458 723f4565 Michael Hanselmann
  def PUT(self):
459 723f4565 Michael Hanselmann
    node_name = self.items[0]
460 723f4565 Michael Hanselmann
461 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
462 723f4565 Michael Hanselmann
    if not storage_type:
463 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
464 723f4565 Michael Hanselmann
                                " parameter")
465 723f4565 Michael Hanselmann
466 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
467 723f4565 Michael Hanselmann
    if not name:
468 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
469 723f4565 Michael Hanselmann
                                " parameter")
470 723f4565 Michael Hanselmann
471 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
472 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
473 723f4565 Michael Hanselmann
                                     name=name)
474 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
475 723f4565 Michael Hanselmann
476 723f4565 Michael Hanselmann
477 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
478 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
479 441e7cfd Oleksiy Mishchenko

480 441e7cfd Oleksiy Mishchenko
  """
481 441e7cfd Oleksiy Mishchenko
  def GET(self):
482 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
483 441e7cfd Oleksiy Mishchenko

484 441e7cfd Oleksiy Mishchenko
    """
485 59b4eeef Iustin Pop
    client = baserlib.GetClient()
486 441e7cfd Oleksiy Mishchenko
487 3d103742 Iustin Pop
    use_locking = self.useLocking()
488 3d103742 Iustin Pop
    if self.useBulk():
489 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
490 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
491 441e7cfd Oleksiy Mishchenko
    else:
492 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
493 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
494 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
495 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
496 441e7cfd Oleksiy Mishchenko
497 d975f482 Michael Hanselmann
  def _ParseVersion0CreateRequest(self):
498 d975f482 Michael Hanselmann
    """Parses an instance creation request version 0.
499 2f7635f4 Oleksiy Mishchenko

500 d975f482 Michael Hanselmann
    @rtype: L{opcodes.OpCreateInstance}
501 d975f482 Michael Hanselmann
    @return: Instance creation opcode
502 2f7635f4 Oleksiy Mishchenko

503 2f7635f4 Oleksiy Mishchenko
    """
504 6e99c5a0 Iustin Pop
    beparams = baserlib.MakeParamsDict(self.req.request_body,
505 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
506 6e99c5a0 Iustin Pop
    hvparams = baserlib.MakeParamsDict(self.req.request_body,
507 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
508 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
509 6e99c5a0 Iustin Pop
510 6e99c5a0 Iustin Pop
    # disk processing
511 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
512 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
513 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
514 6e99c5a0 Iustin Pop
    disks = []
515 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
516 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
517 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
518 69b99987 Michael Hanselmann
                                  " be an integer" % idx)
519 6e99c5a0 Iustin Pop
      disks.append({"size": d})
520 d975f482 Michael Hanselmann
521 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
522 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
523 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
524 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
525 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
526 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
527 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
528 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
529 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
530 69b99987 Michael Hanselmann
      nics[0]["bridge"] = fn("bridge")
531 2f7635f4 Oleksiy Mishchenko
532 d975f482 Michael Hanselmann
    return opcodes.OpCreateInstance(
533 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
534 59b4eeef Iustin Pop
      instance_name=fn('name'),
535 59b4eeef Iustin Pop
      disks=disks,
536 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
537 59b4eeef Iustin Pop
      os_type=fn('os'),
538 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
539 59b4eeef Iustin Pop
      snode=fn('snode', None),
540 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
541 59b4eeef Iustin Pop
      nics=nics,
542 59b4eeef Iustin Pop
      start=fn('start', True),
543 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
544 460d22be Iustin Pop
      name_check=fn('name_check', True),
545 59b4eeef Iustin Pop
      wait_for_sync=True,
546 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
547 59b4eeef Iustin Pop
      hvparams=hvparams,
548 59b4eeef Iustin Pop
      beparams=beparams,
549 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
550 59b4eeef Iustin Pop
      file_driver=fn('file_driver', 'loop'),
551 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
552 59b4eeef Iustin Pop
      )
553 59b4eeef Iustin Pop
554 d975f482 Michael Hanselmann
  def POST(self):
555 d975f482 Michael Hanselmann
    """Create an instance.
556 d975f482 Michael Hanselmann

557 d975f482 Michael Hanselmann
    @return: a job id
558 d975f482 Michael Hanselmann

559 d975f482 Michael Hanselmann
    """
560 d975f482 Michael Hanselmann
    if not isinstance(self.req.request_body, dict):
561 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
562 d975f482 Michael Hanselmann
563 d975f482 Michael Hanselmann
    # Default to request data version 0
564 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
565 d975f482 Michael Hanselmann
566 d975f482 Michael Hanselmann
    if data_version == 0:
567 d975f482 Michael Hanselmann
      op = self._ParseVersion0CreateRequest()
568 d975f482 Michael Hanselmann
    else:
569 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
570 12eff9b9 Michael Hanselmann
                                data_version)
571 d975f482 Michael Hanselmann
572 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
573 2f7635f4 Oleksiy Mishchenko
574 441e7cfd Oleksiy Mishchenko
575 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
576 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
577 028c6b76 Oleksiy Mishchenko

578 028c6b76 Oleksiy Mishchenko
  """
579 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
580 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
581 4e5a68f8 Oleksiy Mishchenko

582 4e5a68f8 Oleksiy Mishchenko
    """
583 59b4eeef Iustin Pop
    client = baserlib.GetClient()
584 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
585 9031ee8e Iustin Pop
    result = client.QueryInstances(names=[instance_name], fields=I_FIELDS,
586 3d103742 Iustin Pop
                                   use_locking=self.useLocking())
587 4e5a68f8 Oleksiy Mishchenko
588 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
589 028c6b76 Oleksiy Mishchenko
590 6e99c5a0 Iustin Pop
  def DELETE(self):
591 6e99c5a0 Iustin Pop
    """Delete an instance.
592 6e99c5a0 Iustin Pop

593 6e99c5a0 Iustin Pop
    """
594 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
595 6f59b964 Iustin Pop
                                  ignore_failures=False,
596 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
597 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
598 6e99c5a0 Iustin Pop
599 028c6b76 Oleksiy Mishchenko
600 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
601 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
602 d8260842 Michael Hanselmann

603 d8260842 Michael Hanselmann
  """
604 d8260842 Michael Hanselmann
  def GET(self):
605 d8260842 Michael Hanselmann
    """Request detailed instance information.
606 d8260842 Michael Hanselmann

607 d8260842 Michael Hanselmann
    """
608 d8260842 Michael Hanselmann
    instance_name = self.items[0]
609 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
610 d8260842 Michael Hanselmann
611 d8260842 Michael Hanselmann
    op = opcodes.OpQueryInstanceData(instances=[instance_name],
612 d8260842 Michael Hanselmann
                                     static=static)
613 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
614 d8260842 Michael Hanselmann
615 d8260842 Michael Hanselmann
616 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
617 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
618 2276aa29 Oleksiy Mishchenko

619 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
620 2276aa29 Oleksiy Mishchenko

621 2276aa29 Oleksiy Mishchenko
  """
622 21f04e5e Oleksiy Mishchenko
  def POST(self):
623 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
624 2276aa29 Oleksiy Mishchenko

625 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
626 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
627 0c55c24b Oleksiy Mishchenko

628 2276aa29 Oleksiy Mishchenko
    """
629 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
630 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
631 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
632 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
633 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
634 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
635 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
636 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
637 2276aa29 Oleksiy Mishchenko
638 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
639 2276aa29 Oleksiy Mishchenko
640 2276aa29 Oleksiy Mishchenko
641 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
642 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
643 0c55c24b Oleksiy Mishchenko

644 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
645 0c55c24b Oleksiy Mishchenko

646 0c55c24b Oleksiy Mishchenko
  """
647 21f04e5e Oleksiy Mishchenko
  def PUT(self):
648 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
649 0c55c24b Oleksiy Mishchenko

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

653 0c55c24b Oleksiy Mishchenko
    """
654 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
655 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
656 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
657 6f59b964 Iustin Pop
                                   force=force_startup,
658 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
659 0c55c24b Oleksiy Mishchenko
660 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
661 0c55c24b Oleksiy Mishchenko
662 0c55c24b Oleksiy Mishchenko
663 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
664 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
665 0c55c24b Oleksiy Mishchenko

666 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
667 0c55c24b Oleksiy Mishchenko

668 0c55c24b Oleksiy Mishchenko
  """
669 21f04e5e Oleksiy Mishchenko
  def PUT(self):
670 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
671 0c55c24b Oleksiy Mishchenko

672 0c55c24b Oleksiy Mishchenko
    """
673 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
674 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
675 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
676 0c55c24b Oleksiy Mishchenko
677 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
678 0c55c24b Oleksiy Mishchenko
679 0c55c24b Oleksiy Mishchenko
680 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
681 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
682 e5b7c4ca Iustin Pop

683 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
684 e5b7c4ca Iustin Pop

685 e5b7c4ca Iustin Pop
  """
686 e5b7c4ca Iustin Pop
  def POST(self):
687 e5b7c4ca Iustin Pop
    """Reinstall an instance.
688 e5b7c4ca Iustin Pop

689 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
690 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
691 e5b7c4ca Iustin Pop
    automatically.
692 e5b7c4ca Iustin Pop

693 e5b7c4ca Iustin Pop
    """
694 e5b7c4ca Iustin Pop
    instance_name = self.items[0]
695 e5b7c4ca Iustin Pop
    ostype = self._checkStringVariable('os')
696 e5b7c4ca Iustin Pop
    nostartup = self._checkIntVariable('nostartup')
697 e5b7c4ca Iustin Pop
    ops = [
698 e5b7c4ca Iustin Pop
      opcodes.OpShutdownInstance(instance_name=instance_name),
699 e5b7c4ca Iustin Pop
      opcodes.OpReinstallInstance(instance_name=instance_name, os_type=ostype),
700 e5b7c4ca Iustin Pop
      ]
701 e5b7c4ca Iustin Pop
    if not nostartup:
702 e5b7c4ca Iustin Pop
      ops.append(opcodes.OpStartupInstance(instance_name=instance_name,
703 e5b7c4ca Iustin Pop
                                           force=False))
704 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
705 e5b7c4ca Iustin Pop
706 e5b7c4ca Iustin Pop
707 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
708 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
709 4c98b915 Michael Hanselmann

710 4c98b915 Michael Hanselmann
  """
711 4c98b915 Michael Hanselmann
  def POST(self):
712 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
713 4c98b915 Michael Hanselmann

714 4c98b915 Michael Hanselmann
    """
715 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
716 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
717 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
718 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
719 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
720 4c98b915 Michael Hanselmann
721 4c98b915 Michael Hanselmann
    if raw_disks:
722 4c98b915 Michael Hanselmann
      try:
723 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
724 4c98b915 Michael Hanselmann
      except ValueError, err:
725 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
726 4c98b915 Michael Hanselmann
    else:
727 4c98b915 Michael Hanselmann
      disks = []
728 4c98b915 Michael Hanselmann
729 4c98b915 Michael Hanselmann
    op = opcodes.OpReplaceDisks(instance_name=instance_name,
730 4c98b915 Michael Hanselmann
                                remote_node=remote_node,
731 4c98b915 Michael Hanselmann
                                mode=mode,
732 4c98b915 Michael Hanselmann
                                disks=disks,
733 4c98b915 Michael Hanselmann
                                iallocator=iallocator)
734 4c98b915 Michael Hanselmann
735 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
736 4c98b915 Michael Hanselmann
737 4c98b915 Michael Hanselmann
738 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
739 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
740 2197b66f René Nussbaumer

741 2197b66f René Nussbaumer
  """
742 2197b66f René Nussbaumer
  def PUT(self):
743 2197b66f René Nussbaumer
    """Activate disks for an instance.
744 2197b66f René Nussbaumer

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

747 2197b66f René Nussbaumer
    """
748 2197b66f René Nussbaumer
    instance_name = self.items[0]
749 2197b66f René Nussbaumer
    ignore_size = bool(self._checkIntVariable('ignore_size'))
750 2197b66f René Nussbaumer
751 2197b66f René Nussbaumer
    op = opcodes.OpActivateInstanceDisks(instance_name=instance_name,
752 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
753 2197b66f René Nussbaumer
754 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
755 2197b66f René Nussbaumer
756 2197b66f René Nussbaumer
757 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
758 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
759 0a37de5f René Nussbaumer

760 0a37de5f René Nussbaumer
  """
761 0a37de5f René Nussbaumer
  def PUT(self):
762 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
763 0a37de5f René Nussbaumer

764 0a37de5f René Nussbaumer
    """
765 0a37de5f René Nussbaumer
    instance_name = self.items[0]
766 0a37de5f René Nussbaumer
767 2263aec2 René Nussbaumer
    op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
768 0a37de5f René Nussbaumer
769 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
770 0a37de5f René Nussbaumer
771 0a37de5f René Nussbaumer
772 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
773 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
774 441e7cfd Oleksiy Mishchenko

775 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
776 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
777 441e7cfd Oleksiy Mishchenko

778 441e7cfd Oleksiy Mishchenko
  """
779 7a6b9510 Iustin Pop
  TAG_LEVEL = None
780 18cb43a2 Oleksiy Mishchenko
781 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
782 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
783 18cb43a2 Oleksiy Mishchenko

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

786 18cb43a2 Oleksiy Mishchenko
    """
787 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
788 18cb43a2 Oleksiy Mishchenko
789 18cb43a2 Oleksiy Mishchenko
    if self.TAG_LEVEL != constants.TAG_CLUSTER:
790 18cb43a2 Oleksiy Mishchenko
      self.name = items[0]
791 18cb43a2 Oleksiy Mishchenko
    else:
792 18cb43a2 Oleksiy Mishchenko
      self.name = ""
793 441e7cfd Oleksiy Mishchenko
794 441e7cfd Oleksiy Mishchenko
  def GET(self):
795 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
796 441e7cfd Oleksiy Mishchenko

797 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
798 441e7cfd Oleksiy Mishchenko

799 441e7cfd Oleksiy Mishchenko
    """
800 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
801 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
802 441e7cfd Oleksiy Mishchenko
803 21f04e5e Oleksiy Mishchenko
  def PUT(self):
804 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
805 441e7cfd Oleksiy Mishchenko

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

809 441e7cfd Oleksiy Mishchenko
    """
810 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
811 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
812 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
813 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
814 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
815 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
816 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
817 15fd9fd5 Oleksiy Mishchenko
818 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
819 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
820 15fd9fd5 Oleksiy Mishchenko

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

825 15fd9fd5 Oleksiy Mishchenko
    """
826 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
827 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
828 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
829 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
830 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
831 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
832 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
833 6f59b964 Iustin Pop
                                 name=self.name,
834 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
835 18cb43a2 Oleksiy Mishchenko
836 18cb43a2 Oleksiy Mishchenko
837 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
838 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
839 18cb43a2 Oleksiy Mishchenko

840 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
841 18cb43a2 Oleksiy Mishchenko

842 18cb43a2 Oleksiy Mishchenko
  """
843 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
844 18cb43a2 Oleksiy Mishchenko
845 18cb43a2 Oleksiy Mishchenko
846 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
847 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
848 18cb43a2 Oleksiy Mishchenko

849 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
850 18cb43a2 Oleksiy Mishchenko

851 18cb43a2 Oleksiy Mishchenko
  """
852 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
853 18cb43a2 Oleksiy Mishchenko
854 18cb43a2 Oleksiy Mishchenko
855 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
856 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
857 18cb43a2 Oleksiy Mishchenko

858 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
859 18cb43a2 Oleksiy Mishchenko

860 18cb43a2 Oleksiy Mishchenko
  """
861 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER