Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 63ea9789

History | View | Annotate | Download (35 kB)

1 10b207d4 Oleksiy Mishchenko
#
2 10b207d4 Oleksiy Mishchenko
#
3 10b207d4 Oleksiy Mishchenko
4 63ea9789 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 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
74 4e5a68f8 Oleksiy Mishchenko
75 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
76 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
77 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
78 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
79 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
80 64dae8fc Michael Hanselmann
81 64dae8fc Michael Hanselmann
_NR_MAP = {
82 64dae8fc Michael Hanselmann
  "M": _NR_MASTER,
83 64dae8fc Michael Hanselmann
  "C": _NR_MASTER_CANDIATE,
84 64dae8fc Michael Hanselmann
  "D": _NR_DRAINED,
85 64dae8fc Michael Hanselmann
  "O": _NR_OFFLINE,
86 64dae8fc Michael Hanselmann
  "R": _NR_REGULAR,
87 64dae8fc Michael Hanselmann
  }
88 64dae8fc Michael Hanselmann
89 d975f482 Michael Hanselmann
# Request data version field
90 d975f482 Michael Hanselmann
_REQ_DATA_VERSION = "__version__"
91 d975f482 Michael Hanselmann
92 6395cebb Michael Hanselmann
# Feature string for instance creation request data version 1
93 6395cebb Michael Hanselmann
_INST_CREATE_REQV1 = "instance-create-reqv1"
94 6395cebb Michael Hanselmann
95 793a8f7c Michael Hanselmann
# Timeout for /2/jobs/[job_id]/wait. Gives job up to 10 seconds to change.
96 793a8f7c Michael Hanselmann
_WFJC_TIMEOUT = 10
97 793a8f7c Michael Hanselmann
98 4e5a68f8 Oleksiy Mishchenko
99 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
100 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
101 4e5a68f8 Oleksiy Mishchenko

102 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
103 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
104 4e5a68f8 Oleksiy Mishchenko

105 4e5a68f8 Oleksiy Mishchenko
  """
106 7e950d31 Iustin Pop
  @staticmethod
107 7e950d31 Iustin Pop
  def GET():
108 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
109 4e5a68f8 Oleksiy Mishchenko

110 4e5a68f8 Oleksiy Mishchenko
    """
111 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
112 4e5a68f8 Oleksiy Mishchenko
113 4e5a68f8 Oleksiy Mishchenko
114 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
115 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
116 4e5a68f8 Oleksiy Mishchenko

117 4e5a68f8 Oleksiy Mishchenko
  """
118 7e950d31 Iustin Pop
  @staticmethod
119 7e950d31 Iustin Pop
  def GET():
120 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
121 4e5a68f8 Oleksiy Mishchenko

122 4e5a68f8 Oleksiy Mishchenko
    """
123 59b4eeef Iustin Pop
    client = baserlib.GetClient()
124 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
125 4e5a68f8 Oleksiy Mishchenko
126 4e5a68f8 Oleksiy Mishchenko
127 7eac4a4d Michael Hanselmann
class R_2_features(baserlib.R_Generic):
128 7eac4a4d Michael Hanselmann
  """/2/features resource.
129 7eac4a4d Michael Hanselmann

130 7eac4a4d Michael Hanselmann
  """
131 7eac4a4d Michael Hanselmann
  @staticmethod
132 7eac4a4d Michael Hanselmann
  def GET():
133 7eac4a4d Michael Hanselmann
    """Returns list of optional RAPI features implemented.
134 7eac4a4d Michael Hanselmann

135 7eac4a4d Michael Hanselmann
    """
136 6395cebb Michael Hanselmann
    return [_INST_CREATE_REQV1]
137 7eac4a4d Michael Hanselmann
138 7eac4a4d Michael Hanselmann
139 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
140 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
141 4e5a68f8 Oleksiy Mishchenko

142 4e5a68f8 Oleksiy Mishchenko
  """
143 7e950d31 Iustin Pop
  @staticmethod
144 7e950d31 Iustin Pop
  def GET():
145 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
146 4e5a68f8 Oleksiy Mishchenko

147 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
148 4e5a68f8 Oleksiy Mishchenko

149 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
150 4e5a68f8 Oleksiy Mishchenko

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

172 508e9b20 Michael Hanselmann
  """
173 7e950d31 Iustin Pop
  @staticmethod
174 7e950d31 Iustin Pop
  def PUT():
175 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
176 508e9b20 Michael Hanselmann

177 508e9b20 Michael Hanselmann
    """
178 508e9b20 Michael Hanselmann
    return baserlib.SubmitJob([opcodes.OpRedistributeConfig()])
179 508e9b20 Michael Hanselmann
180 508e9b20 Michael Hanselmann
181 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
182 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
183 10b207d4 Oleksiy Mishchenko

184 10b207d4 Oleksiy Mishchenko
  """
185 7e950d31 Iustin Pop
  @staticmethod
186 7e950d31 Iustin Pop
  def GET():
187 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
188 10b207d4 Oleksiy Mishchenko

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

191 10b207d4 Oleksiy Mishchenko
    """
192 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
193 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
194 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
195 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
196 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
197 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
198 10b207d4 Oleksiy Mishchenko
199 10b207d4 Oleksiy Mishchenko
200 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
201 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
202 10b207d4 Oleksiy Mishchenko

203 10b207d4 Oleksiy Mishchenko
  """
204 10b207d4 Oleksiy Mishchenko
  def GET(self):
205 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
206 10b207d4 Oleksiy Mishchenko

207 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
208 c41eea6e Iustin Pop
        The result includes:
209 c41eea6e Iustin Pop
            - id: job ID as a number
210 c41eea6e Iustin Pop
            - status: current job status as a string
211 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
212 c41eea6e Iustin Pop
              opcodes in the job
213 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
214 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
215 38206f3c Iustin Pop

216 10b207d4 Oleksiy Mishchenko
    """
217 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
218 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
219 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
220 ee69c97f Iustin Pop
              ]
221 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
222 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
223 ee69c97f Iustin Pop
    if result is None:
224 ee69c97f Iustin Pop
      raise http.HttpNotFound()
225 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
226 10b207d4 Oleksiy Mishchenko
227 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
228 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
229 c7f5f338 Oleksiy Mishchenko

230 c7f5f338 Oleksiy Mishchenko
    """
231 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
232 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
233 c7f5f338 Oleksiy Mishchenko
    return result
234 c7f5f338 Oleksiy Mishchenko
235 10b207d4 Oleksiy Mishchenko
236 793a8f7c Michael Hanselmann
class R_2_jobs_id_wait(baserlib.R_Generic):
237 793a8f7c Michael Hanselmann
  """/2/jobs/[job_id]/wait resource.
238 793a8f7c Michael Hanselmann

239 793a8f7c Michael Hanselmann
  """
240 793a8f7c Michael Hanselmann
  # WaitForJobChange provides access to sensitive information and blocks
241 793a8f7c Michael Hanselmann
  # machine resources (it's a blocking RAPI call), hence restricting access.
242 793a8f7c Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
243 793a8f7c Michael Hanselmann
244 793a8f7c Michael Hanselmann
  def GET(self):
245 793a8f7c Michael Hanselmann
    """Waits for job changes.
246 793a8f7c Michael Hanselmann

247 793a8f7c Michael Hanselmann
    """
248 793a8f7c Michael Hanselmann
    job_id = self.items[0]
249 793a8f7c Michael Hanselmann
250 793a8f7c Michael Hanselmann
    fields = self.getBodyParameter("fields")
251 793a8f7c Michael Hanselmann
    prev_job_info = self.getBodyParameter("previous_job_info", None)
252 793a8f7c Michael Hanselmann
    prev_log_serial = self.getBodyParameter("previous_log_serial", None)
253 793a8f7c Michael Hanselmann
254 793a8f7c Michael Hanselmann
    if not isinstance(fields, list):
255 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'fields' parameter should be a list")
256 793a8f7c Michael Hanselmann
257 793a8f7c Michael Hanselmann
    if not (prev_job_info is None or isinstance(prev_job_info, list)):
258 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_job_info' parameter should"
259 793a8f7c Michael Hanselmann
                                " be a list")
260 793a8f7c Michael Hanselmann
261 793a8f7c Michael Hanselmann
    if not (prev_log_serial is None or
262 793a8f7c Michael Hanselmann
            isinstance(prev_log_serial, (int, long))):
263 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_log_serial' parameter should"
264 793a8f7c Michael Hanselmann
                                " be a number")
265 793a8f7c Michael Hanselmann
266 793a8f7c Michael Hanselmann
    client = baserlib.GetClient()
267 793a8f7c Michael Hanselmann
    result = client.WaitForJobChangeOnce(job_id, fields,
268 793a8f7c Michael Hanselmann
                                         prev_job_info, prev_log_serial,
269 793a8f7c Michael Hanselmann
                                         timeout=_WFJC_TIMEOUT)
270 793a8f7c Michael Hanselmann
    if not result:
271 793a8f7c Michael Hanselmann
      raise http.HttpNotFound()
272 793a8f7c Michael Hanselmann
273 793a8f7c Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
274 793a8f7c Michael Hanselmann
      # No changes
275 793a8f7c Michael Hanselmann
      return None
276 793a8f7c Michael Hanselmann
277 793a8f7c Michael Hanselmann
    (job_info, log_entries) = result
278 793a8f7c Michael Hanselmann
279 793a8f7c Michael Hanselmann
    return {
280 793a8f7c Michael Hanselmann
      "job_info": job_info,
281 793a8f7c Michael Hanselmann
      "log_entries": log_entries,
282 793a8f7c Michael Hanselmann
      }
283 793a8f7c Michael Hanselmann
284 793a8f7c Michael Hanselmann
285 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
286 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
287 10b207d4 Oleksiy Mishchenko

288 10b207d4 Oleksiy Mishchenko
  """
289 10b207d4 Oleksiy Mishchenko
  def GET(self):
290 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
291 38206f3c Iustin Pop

292 10b207d4 Oleksiy Mishchenko
    """
293 59b4eeef Iustin Pop
    client = baserlib.GetClient()
294 38206f3c Iustin Pop
295 3d103742 Iustin Pop
    if self.useBulk():
296 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
297 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
298 9031ee8e Iustin Pop
    else:
299 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
300 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
301 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
302 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
303 441e7cfd Oleksiy Mishchenko
304 441e7cfd Oleksiy Mishchenko
305 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
306 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
307 028c6b76 Oleksiy Mishchenko

308 028c6b76 Oleksiy Mishchenko
  """
309 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
310 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
311 4e5a68f8 Oleksiy Mishchenko

312 4e5a68f8 Oleksiy Mishchenko
    """
313 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
314 59b4eeef Iustin Pop
    client = baserlib.GetClient()
315 e8ebbd2b Michael Hanselmann
316 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryNodes,
317 e8ebbd2b Michael Hanselmann
                                            names=[node_name], fields=N_FIELDS,
318 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
319 4e5a68f8 Oleksiy Mishchenko
320 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
321 028c6b76 Oleksiy Mishchenko
322 028c6b76 Oleksiy Mishchenko
323 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
324 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
325 64dae8fc Michael Hanselmann

326 64dae8fc Michael Hanselmann
  """
327 64dae8fc Michael Hanselmann
  def GET(self):
328 64dae8fc Michael Hanselmann
    """Returns the current node role.
329 64dae8fc Michael Hanselmann

330 64dae8fc Michael Hanselmann
    @return: Node role
331 64dae8fc Michael Hanselmann

332 64dae8fc Michael Hanselmann
    """
333 64dae8fc Michael Hanselmann
    node_name = self.items[0]
334 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
335 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
336 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
337 64dae8fc Michael Hanselmann
338 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
339 64dae8fc Michael Hanselmann
340 64dae8fc Michael Hanselmann
  def PUT(self):
341 64dae8fc Michael Hanselmann
    """Sets the node role.
342 64dae8fc Michael Hanselmann

343 64dae8fc Michael Hanselmann
    @return: a job id
344 64dae8fc Michael Hanselmann

345 64dae8fc Michael Hanselmann
    """
346 627ad739 Michael Hanselmann
    if not isinstance(self.request_body, basestring):
347 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
348 64dae8fc Michael Hanselmann
349 64dae8fc Michael Hanselmann
    node_name = self.items[0]
350 627ad739 Michael Hanselmann
    role = self.request_body
351 64dae8fc Michael Hanselmann
352 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
353 64dae8fc Michael Hanselmann
      candidate = False
354 64dae8fc Michael Hanselmann
      offline = False
355 64dae8fc Michael Hanselmann
      drained = False
356 64dae8fc Michael Hanselmann
357 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
358 64dae8fc Michael Hanselmann
      candidate = True
359 64dae8fc Michael Hanselmann
      offline = drained = None
360 64dae8fc Michael Hanselmann
361 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
362 64dae8fc Michael Hanselmann
      drained = True
363 64dae8fc Michael Hanselmann
      candidate = offline = None
364 64dae8fc Michael Hanselmann
365 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
366 64dae8fc Michael Hanselmann
      offline = True
367 64dae8fc Michael Hanselmann
      candidate = drained = None
368 64dae8fc Michael Hanselmann
369 64dae8fc Michael Hanselmann
    else:
370 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
371 64dae8fc Michael Hanselmann
372 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
373 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
374 64dae8fc Michael Hanselmann
                                 offline=offline,
375 64dae8fc Michael Hanselmann
                                 drained=drained,
376 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
377 64dae8fc Michael Hanselmann
378 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
379 64dae8fc Michael Hanselmann
380 64dae8fc Michael Hanselmann
381 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
382 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
383 73452f12 Michael Hanselmann

384 73452f12 Michael Hanselmann
  """
385 73452f12 Michael Hanselmann
  def POST(self):
386 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
387 73452f12 Michael Hanselmann

388 73452f12 Michael Hanselmann
    """
389 73452f12 Michael Hanselmann
    node_name = self.items[0]
390 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
391 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
392 941b9309 Iustin Pop
    early_r = bool(self._checkIntVariable("early_release", default=0))
393 941b9309 Iustin Pop
    dry_run = bool(self.dryRun())
394 73452f12 Michael Hanselmann
395 941b9309 Iustin Pop
    cl = baserlib.GetClient()
396 73452f12 Michael Hanselmann
397 941b9309 Iustin Pop
    op = opcodes.OpNodeEvacuationStrategy(nodes=[node_name],
398 941b9309 Iustin Pop
                                          iallocator=iallocator,
399 941b9309 Iustin Pop
                                          remote_node=remote_node)
400 941b9309 Iustin Pop
401 941b9309 Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
402 941b9309 Iustin Pop
    # we use custom feedback function, instead of print we log the status
403 941b9309 Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
404 941b9309 Iustin Pop
405 941b9309 Iustin Pop
    jobs = []
406 63ea9789 Iustin Pop
    for iname, node in result[0]:
407 941b9309 Iustin Pop
      if dry_run:
408 941b9309 Iustin Pop
        jid = None
409 941b9309 Iustin Pop
      else:
410 941b9309 Iustin Pop
        op = opcodes.OpReplaceDisks(instance_name=iname,
411 941b9309 Iustin Pop
                                    remote_node=node, disks=[],
412 941b9309 Iustin Pop
                                    mode=constants.REPLACE_DISK_CHG,
413 941b9309 Iustin Pop
                                    early_release=early_r)
414 941b9309 Iustin Pop
        jid = baserlib.SubmitJob([op])
415 941b9309 Iustin Pop
      jobs.append((jid, iname, node))
416 941b9309 Iustin Pop
417 941b9309 Iustin Pop
    return jobs
418 73452f12 Michael Hanselmann
419 73452f12 Michael Hanselmann
420 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
421 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
422 1c482bab Michael Hanselmann

423 1c482bab Michael Hanselmann
  """
424 1c482bab Michael Hanselmann
  def POST(self):
425 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
426 1c482bab Michael Hanselmann

427 1c482bab Michael Hanselmann
    """
428 1c482bab Michael Hanselmann
    node_name = self.items[0]
429 1c482bab Michael Hanselmann
430 52194140 Iustin Pop
    if "live" in self.queryargs and "mode" in self.queryargs:
431 52194140 Iustin Pop
      raise http.HttpBadRequest("Only one of 'live' and 'mode' should"
432 52194140 Iustin Pop
                                " be passed")
433 52194140 Iustin Pop
    elif "live" in self.queryargs:
434 52194140 Iustin Pop
      if self._checkIntVariable("live", default=1):
435 52194140 Iustin Pop
        mode = constants.HT_MIGRATION_LIVE
436 52194140 Iustin Pop
      else:
437 52194140 Iustin Pop
        mode = constants.HT_MIGRATION_NONLIVE
438 52194140 Iustin Pop
    else:
439 52194140 Iustin Pop
      mode = self._checkStringVariable("mode", default=None)
440 52194140 Iustin Pop
441 52194140 Iustin Pop
    op = opcodes.OpMigrateNode(node_name=node_name, mode=mode)
442 1c482bab Michael Hanselmann
443 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
444 1c482bab Michael Hanselmann
445 1c482bab Michael Hanselmann
446 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
447 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
448 7a95a954 Michael Hanselmann

449 7a95a954 Michael Hanselmann
  """
450 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
451 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
452 7a95a954 Michael Hanselmann
453 7a95a954 Michael Hanselmann
  def GET(self):
454 7a95a954 Michael Hanselmann
    node_name = self.items[0]
455 7a95a954 Michael Hanselmann
456 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
457 7a95a954 Michael Hanselmann
    if not storage_type:
458 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
459 7a95a954 Michael Hanselmann
                                " parameter")
460 7a95a954 Michael Hanselmann
461 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
462 7a95a954 Michael Hanselmann
    if not output_fields:
463 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
464 7a95a954 Michael Hanselmann
                                " parameter")
465 7a95a954 Michael Hanselmann
466 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
467 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
468 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
469 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
470 7a95a954 Michael Hanselmann
471 7a95a954 Michael Hanselmann
472 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
473 1e82bc80 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify ressource.
474 1e82bc80 Michael Hanselmann

475 1e82bc80 Michael Hanselmann
  """
476 1e82bc80 Michael Hanselmann
  def PUT(self):
477 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
478 1e82bc80 Michael Hanselmann
479 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
480 1e82bc80 Michael Hanselmann
    if not storage_type:
481 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
482 1e82bc80 Michael Hanselmann
                                " parameter")
483 1e82bc80 Michael Hanselmann
484 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
485 1e82bc80 Michael Hanselmann
    if not name:
486 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
487 1e82bc80 Michael Hanselmann
                                " parameter")
488 1e82bc80 Michael Hanselmann
489 1e82bc80 Michael Hanselmann
    changes = {}
490 1e82bc80 Michael Hanselmann
491 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
492 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
493 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
494 1e82bc80 Michael Hanselmann
495 1e82bc80 Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
496 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
497 1e82bc80 Michael Hanselmann
                                     name=name,
498 1e82bc80 Michael Hanselmann
                                     changes=changes)
499 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
500 1e82bc80 Michael Hanselmann
501 1e82bc80 Michael Hanselmann
502 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
503 723f4565 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair ressource.
504 723f4565 Michael Hanselmann

505 723f4565 Michael Hanselmann
  """
506 723f4565 Michael Hanselmann
  def PUT(self):
507 723f4565 Michael Hanselmann
    node_name = self.items[0]
508 723f4565 Michael Hanselmann
509 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
510 723f4565 Michael Hanselmann
    if not storage_type:
511 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
512 723f4565 Michael Hanselmann
                                " parameter")
513 723f4565 Michael Hanselmann
514 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
515 723f4565 Michael Hanselmann
    if not name:
516 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
517 723f4565 Michael Hanselmann
                                " parameter")
518 723f4565 Michael Hanselmann
519 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
520 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
521 723f4565 Michael Hanselmann
                                     name=name)
522 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
523 723f4565 Michael Hanselmann
524 723f4565 Michael Hanselmann
525 6395cebb Michael Hanselmann
def _ParseInstanceCreateRequestVersion1(data, dry_run):
526 6395cebb Michael Hanselmann
  """Parses an instance creation request version 1.
527 6395cebb Michael Hanselmann

528 6395cebb Michael Hanselmann
  @rtype: L{opcodes.OpCreateInstance}
529 6395cebb Michael Hanselmann
  @return: Instance creation opcode
530 6395cebb Michael Hanselmann

531 6395cebb Michael Hanselmann
  """
532 6395cebb Michael Hanselmann
  # Disks
533 6395cebb Michael Hanselmann
  disks_input = baserlib.CheckParameter(data, "disks", exptype=list)
534 6395cebb Michael Hanselmann
535 6395cebb Michael Hanselmann
  disks = []
536 6395cebb Michael Hanselmann
  for idx, i in enumerate(disks_input):
537 6395cebb Michael Hanselmann
    baserlib.CheckType(i, dict, "Disk %d specification" % idx)
538 6395cebb Michael Hanselmann
539 6395cebb Michael Hanselmann
    # Size is mandatory
540 6395cebb Michael Hanselmann
    try:
541 7be048f0 Michael Hanselmann
      size = i[constants.IDISK_SIZE]
542 6395cebb Michael Hanselmann
    except KeyError:
543 6395cebb Michael Hanselmann
      raise http.HttpBadRequest("Disk %d specification wrong: missing disk"
544 6395cebb Michael Hanselmann
                                " size" % idx)
545 6395cebb Michael Hanselmann
546 6395cebb Michael Hanselmann
    disk = {
547 7be048f0 Michael Hanselmann
      constants.IDISK_SIZE: size,
548 6395cebb Michael Hanselmann
      }
549 6395cebb Michael Hanselmann
550 6395cebb Michael Hanselmann
    # Optional disk access mode
551 6395cebb Michael Hanselmann
    try:
552 7be048f0 Michael Hanselmann
      disk_access = i[constants.IDISK_MODE]
553 6395cebb Michael Hanselmann
    except KeyError:
554 6395cebb Michael Hanselmann
      pass
555 6395cebb Michael Hanselmann
    else:
556 7be048f0 Michael Hanselmann
      disk[constants.IDISK_MODE] = disk_access
557 6395cebb Michael Hanselmann
558 6395cebb Michael Hanselmann
    disks.append(disk)
559 6395cebb Michael Hanselmann
560 6395cebb Michael Hanselmann
  assert len(disks_input) == len(disks)
561 6395cebb Michael Hanselmann
562 6395cebb Michael Hanselmann
  # Network interfaces
563 6395cebb Michael Hanselmann
  nics_input = baserlib.CheckParameter(data, "nics", exptype=list)
564 6395cebb Michael Hanselmann
565 6395cebb Michael Hanselmann
  nics = []
566 6395cebb Michael Hanselmann
  for idx, i in enumerate(nics_input):
567 6395cebb Michael Hanselmann
    baserlib.CheckType(i, dict, "NIC %d specification" % idx)
568 6395cebb Michael Hanselmann
569 6395cebb Michael Hanselmann
    nic = {}
570 6395cebb Michael Hanselmann
571 7be048f0 Michael Hanselmann
    for field in constants.INIC_PARAMS:
572 6395cebb Michael Hanselmann
      try:
573 6395cebb Michael Hanselmann
        value = i[field]
574 6395cebb Michael Hanselmann
      except KeyError:
575 6395cebb Michael Hanselmann
        continue
576 6395cebb Michael Hanselmann
577 6395cebb Michael Hanselmann
      nic[field] = value
578 6395cebb Michael Hanselmann
579 6395cebb Michael Hanselmann
    nics.append(nic)
580 6395cebb Michael Hanselmann
581 6395cebb Michael Hanselmann
  assert len(nics_input) == len(nics)
582 6395cebb Michael Hanselmann
583 6395cebb Michael Hanselmann
  # HV/BE parameters
584 6395cebb Michael Hanselmann
  hvparams = baserlib.CheckParameter(data, "hvparams", default={})
585 6395cebb Michael Hanselmann
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES)
586 6395cebb Michael Hanselmann
587 6395cebb Michael Hanselmann
  beparams = baserlib.CheckParameter(data, "beparams", default={})
588 6395cebb Michael Hanselmann
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES)
589 6395cebb Michael Hanselmann
590 6395cebb Michael Hanselmann
  return opcodes.OpCreateInstance(
591 6395cebb Michael Hanselmann
    mode=baserlib.CheckParameter(data, "mode"),
592 6395cebb Michael Hanselmann
    instance_name=baserlib.CheckParameter(data, "name"),
593 130f0966 Iustin Pop
    os_type=baserlib.CheckParameter(data, "os"),
594 130f0966 Iustin Pop
    osparams=baserlib.CheckParameter(data, "osparams", default={}),
595 6395cebb Michael Hanselmann
    force_variant=baserlib.CheckParameter(data, "force_variant",
596 6395cebb Michael Hanselmann
                                          default=False),
597 6395cebb Michael Hanselmann
    pnode=baserlib.CheckParameter(data, "pnode", default=None),
598 6395cebb Michael Hanselmann
    snode=baserlib.CheckParameter(data, "snode", default=None),
599 6395cebb Michael Hanselmann
    disk_template=baserlib.CheckParameter(data, "disk_template"),
600 6395cebb Michael Hanselmann
    disks=disks,
601 6395cebb Michael Hanselmann
    nics=nics,
602 6395cebb Michael Hanselmann
    src_node=baserlib.CheckParameter(data, "src_node", default=None),
603 6395cebb Michael Hanselmann
    src_path=baserlib.CheckParameter(data, "src_path", default=None),
604 6395cebb Michael Hanselmann
    start=baserlib.CheckParameter(data, "start", default=True),
605 6395cebb Michael Hanselmann
    wait_for_sync=True,
606 6395cebb Michael Hanselmann
    ip_check=baserlib.CheckParameter(data, "ip_check", default=True),
607 6395cebb Michael Hanselmann
    name_check=baserlib.CheckParameter(data, "name_check", default=True),
608 6395cebb Michael Hanselmann
    file_storage_dir=baserlib.CheckParameter(data, "file_storage_dir",
609 6395cebb Michael Hanselmann
                                             default=None),
610 6395cebb Michael Hanselmann
    file_driver=baserlib.CheckParameter(data, "file_driver",
611 6395cebb Michael Hanselmann
                                        default=constants.FD_LOOP),
612 ebeb600f Michael Hanselmann
    source_handshake=baserlib.CheckParameter(data, "source_handshake",
613 ebeb600f Michael Hanselmann
                                             default=None),
614 ebeb600f Michael Hanselmann
    source_x509_ca=baserlib.CheckParameter(data, "source_x509_ca",
615 ebeb600f Michael Hanselmann
                                           default=None),
616 ebeb600f Michael Hanselmann
    source_instance_name=baserlib.CheckParameter(data, "source_instance_name",
617 ebeb600f Michael Hanselmann
                                                 default=None),
618 6395cebb Michael Hanselmann
    iallocator=baserlib.CheckParameter(data, "iallocator", default=None),
619 6395cebb Michael Hanselmann
    hypervisor=baserlib.CheckParameter(data, "hypervisor", default=None),
620 6395cebb Michael Hanselmann
    hvparams=hvparams,
621 6395cebb Michael Hanselmann
    beparams=beparams,
622 6395cebb Michael Hanselmann
    dry_run=dry_run,
623 6395cebb Michael Hanselmann
    )
624 6395cebb Michael Hanselmann
625 6395cebb Michael Hanselmann
626 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
627 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
628 441e7cfd Oleksiy Mishchenko

629 441e7cfd Oleksiy Mishchenko
  """
630 441e7cfd Oleksiy Mishchenko
  def GET(self):
631 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
632 441e7cfd Oleksiy Mishchenko

633 441e7cfd Oleksiy Mishchenko
    """
634 59b4eeef Iustin Pop
    client = baserlib.GetClient()
635 441e7cfd Oleksiy Mishchenko
636 3d103742 Iustin Pop
    use_locking = self.useLocking()
637 3d103742 Iustin Pop
    if self.useBulk():
638 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
639 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
640 441e7cfd Oleksiy Mishchenko
    else:
641 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
642 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
643 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
644 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
645 441e7cfd Oleksiy Mishchenko
646 d975f482 Michael Hanselmann
  def _ParseVersion0CreateRequest(self):
647 d975f482 Michael Hanselmann
    """Parses an instance creation request version 0.
648 2f7635f4 Oleksiy Mishchenko

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

651 d975f482 Michael Hanselmann
    @rtype: L{opcodes.OpCreateInstance}
652 d975f482 Michael Hanselmann
    @return: Instance creation opcode
653 6e99c5a0 Iustin Pop

654 2f7635f4 Oleksiy Mishchenko
    """
655 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
656 627ad739 Michael Hanselmann
    beparams = baserlib.MakeParamsDict(self.request_body,
657 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
658 627ad739 Michael Hanselmann
    hvparams = baserlib.MakeParamsDict(self.request_body,
659 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
660 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
661 6e99c5a0 Iustin Pop
662 6e99c5a0 Iustin Pop
    # disk processing
663 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
664 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
665 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
666 6e99c5a0 Iustin Pop
    disks = []
667 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
668 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
669 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
670 69b99987 Michael Hanselmann
                                  " be an integer" % idx)
671 6e99c5a0 Iustin Pop
      disks.append({"size": d})
672 d975f482 Michael Hanselmann
673 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
674 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
675 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
676 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
677 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
678 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
679 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
680 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
681 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
682 69b99987 Michael Hanselmann
      nics[0]["bridge"] = fn("bridge")
683 2f7635f4 Oleksiy Mishchenko
684 6395cebb Michael Hanselmann
    # Do not modify anymore, request data version 0 is deprecated
685 d975f482 Michael Hanselmann
    return opcodes.OpCreateInstance(
686 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
687 59b4eeef Iustin Pop
      instance_name=fn('name'),
688 59b4eeef Iustin Pop
      disks=disks,
689 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
690 59b4eeef Iustin Pop
      os_type=fn('os'),
691 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
692 59b4eeef Iustin Pop
      snode=fn('snode', None),
693 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
694 59b4eeef Iustin Pop
      nics=nics,
695 59b4eeef Iustin Pop
      start=fn('start', True),
696 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
697 460d22be Iustin Pop
      name_check=fn('name_check', True),
698 59b4eeef Iustin Pop
      wait_for_sync=True,
699 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
700 59b4eeef Iustin Pop
      hvparams=hvparams,
701 59b4eeef Iustin Pop
      beparams=beparams,
702 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
703 6395cebb Michael Hanselmann
      file_driver=fn('file_driver', constants.FD_LOOP),
704 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
705 59b4eeef Iustin Pop
      )
706 59b4eeef Iustin Pop
707 d975f482 Michael Hanselmann
  def POST(self):
708 d975f482 Michael Hanselmann
    """Create an instance.
709 d975f482 Michael Hanselmann

710 d975f482 Michael Hanselmann
    @return: a job id
711 d975f482 Michael Hanselmann

712 d975f482 Michael Hanselmann
    """
713 1c54156d Luca Bigliardi
    if not isinstance(self.request_body, dict):
714 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
715 d975f482 Michael Hanselmann
716 d975f482 Michael Hanselmann
    # Default to request data version 0
717 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
718 d975f482 Michael Hanselmann
719 d975f482 Michael Hanselmann
    if data_version == 0:
720 d975f482 Michael Hanselmann
      op = self._ParseVersion0CreateRequest()
721 6395cebb Michael Hanselmann
    elif data_version == 1:
722 1c54156d Luca Bigliardi
      op = _ParseInstanceCreateRequestVersion1(self.request_body,
723 6395cebb Michael Hanselmann
                                               self.dryRun())
724 d975f482 Michael Hanselmann
    else:
725 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
726 12eff9b9 Michael Hanselmann
                                data_version)
727 d975f482 Michael Hanselmann
728 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
729 2f7635f4 Oleksiy Mishchenko
730 441e7cfd Oleksiy Mishchenko
731 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
732 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
733 028c6b76 Oleksiy Mishchenko

734 028c6b76 Oleksiy Mishchenko
  """
735 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
736 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
737 4e5a68f8 Oleksiy Mishchenko

738 4e5a68f8 Oleksiy Mishchenko
    """
739 59b4eeef Iustin Pop
    client = baserlib.GetClient()
740 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
741 e8ebbd2b Michael Hanselmann
742 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryInstances,
743 e8ebbd2b Michael Hanselmann
                                            names=[instance_name],
744 e8ebbd2b Michael Hanselmann
                                            fields=I_FIELDS,
745 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
746 4e5a68f8 Oleksiy Mishchenko
747 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
748 028c6b76 Oleksiy Mishchenko
749 6e99c5a0 Iustin Pop
  def DELETE(self):
750 6e99c5a0 Iustin Pop
    """Delete an instance.
751 6e99c5a0 Iustin Pop

752 6e99c5a0 Iustin Pop
    """
753 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
754 6f59b964 Iustin Pop
                                  ignore_failures=False,
755 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
756 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
757 6e99c5a0 Iustin Pop
758 028c6b76 Oleksiy Mishchenko
759 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
760 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
761 d8260842 Michael Hanselmann

762 d8260842 Michael Hanselmann
  """
763 d8260842 Michael Hanselmann
  def GET(self):
764 d8260842 Michael Hanselmann
    """Request detailed instance information.
765 d8260842 Michael Hanselmann

766 d8260842 Michael Hanselmann
    """
767 d8260842 Michael Hanselmann
    instance_name = self.items[0]
768 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
769 d8260842 Michael Hanselmann
770 d8260842 Michael Hanselmann
    op = opcodes.OpQueryInstanceData(instances=[instance_name],
771 d8260842 Michael Hanselmann
                                     static=static)
772 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
773 d8260842 Michael Hanselmann
774 d8260842 Michael Hanselmann
775 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
776 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
777 2276aa29 Oleksiy Mishchenko

778 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
779 2276aa29 Oleksiy Mishchenko

780 2276aa29 Oleksiy Mishchenko
  """
781 21f04e5e Oleksiy Mishchenko
  def POST(self):
782 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
783 2276aa29 Oleksiy Mishchenko

784 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
785 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
786 0c55c24b Oleksiy Mishchenko

787 2276aa29 Oleksiy Mishchenko
    """
788 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
789 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
790 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
791 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
792 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
793 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
794 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
795 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
796 2276aa29 Oleksiy Mishchenko
797 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
798 2276aa29 Oleksiy Mishchenko
799 2276aa29 Oleksiy Mishchenko
800 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
801 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
802 0c55c24b Oleksiy Mishchenko

803 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
804 0c55c24b Oleksiy Mishchenko

805 0c55c24b Oleksiy Mishchenko
  """
806 21f04e5e Oleksiy Mishchenko
  def PUT(self):
807 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
808 0c55c24b Oleksiy Mishchenko

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

812 0c55c24b Oleksiy Mishchenko
    """
813 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
814 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
815 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
816 6f59b964 Iustin Pop
                                   force=force_startup,
817 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
818 0c55c24b Oleksiy Mishchenko
819 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
820 0c55c24b Oleksiy Mishchenko
821 0c55c24b Oleksiy Mishchenko
822 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
823 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
824 0c55c24b Oleksiy Mishchenko

825 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
826 0c55c24b Oleksiy Mishchenko

827 0c55c24b Oleksiy Mishchenko
  """
828 21f04e5e Oleksiy Mishchenko
  def PUT(self):
829 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
830 0c55c24b Oleksiy Mishchenko

831 0c55c24b Oleksiy Mishchenko
    """
832 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
833 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
834 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
835 0c55c24b Oleksiy Mishchenko
836 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
837 0c55c24b Oleksiy Mishchenko
838 0c55c24b Oleksiy Mishchenko
839 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
840 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
841 e5b7c4ca Iustin Pop

842 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
843 e5b7c4ca Iustin Pop

844 e5b7c4ca Iustin Pop
  """
845 e5b7c4ca Iustin Pop
  def POST(self):
846 e5b7c4ca Iustin Pop
    """Reinstall an instance.
847 e5b7c4ca Iustin Pop

848 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
849 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
850 e5b7c4ca Iustin Pop
    automatically.
851 e5b7c4ca Iustin Pop

852 e5b7c4ca Iustin Pop
    """
853 e5b7c4ca Iustin Pop
    instance_name = self.items[0]
854 e5b7c4ca Iustin Pop
    ostype = self._checkStringVariable('os')
855 e5b7c4ca Iustin Pop
    nostartup = self._checkIntVariable('nostartup')
856 e5b7c4ca Iustin Pop
    ops = [
857 e5b7c4ca Iustin Pop
      opcodes.OpShutdownInstance(instance_name=instance_name),
858 e5b7c4ca Iustin Pop
      opcodes.OpReinstallInstance(instance_name=instance_name, os_type=ostype),
859 e5b7c4ca Iustin Pop
      ]
860 e5b7c4ca Iustin Pop
    if not nostartup:
861 e5b7c4ca Iustin Pop
      ops.append(opcodes.OpStartupInstance(instance_name=instance_name,
862 e5b7c4ca Iustin Pop
                                           force=False))
863 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
864 e5b7c4ca Iustin Pop
865 e5b7c4ca Iustin Pop
866 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
867 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
868 4c98b915 Michael Hanselmann

869 4c98b915 Michael Hanselmann
  """
870 4c98b915 Michael Hanselmann
  def POST(self):
871 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
872 4c98b915 Michael Hanselmann

873 4c98b915 Michael Hanselmann
    """
874 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
875 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
876 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
877 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
878 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
879 4c98b915 Michael Hanselmann
880 4c98b915 Michael Hanselmann
    if raw_disks:
881 4c98b915 Michael Hanselmann
      try:
882 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
883 4c98b915 Michael Hanselmann
      except ValueError, err:
884 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
885 4c98b915 Michael Hanselmann
    else:
886 4c98b915 Michael Hanselmann
      disks = []
887 4c98b915 Michael Hanselmann
888 4c98b915 Michael Hanselmann
    op = opcodes.OpReplaceDisks(instance_name=instance_name,
889 4c98b915 Michael Hanselmann
                                remote_node=remote_node,
890 4c98b915 Michael Hanselmann
                                mode=mode,
891 4c98b915 Michael Hanselmann
                                disks=disks,
892 4c98b915 Michael Hanselmann
                                iallocator=iallocator)
893 4c98b915 Michael Hanselmann
894 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
895 4c98b915 Michael Hanselmann
896 4c98b915 Michael Hanselmann
897 2197b66f René Nussbaumer
class R_2_instances_name_activate_disks(baserlib.R_Generic):
898 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
899 2197b66f René Nussbaumer

900 2197b66f René Nussbaumer
  """
901 2197b66f René Nussbaumer
  def PUT(self):
902 2197b66f René Nussbaumer
    """Activate disks for an instance.
903 2197b66f René Nussbaumer

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

906 2197b66f René Nussbaumer
    """
907 2197b66f René Nussbaumer
    instance_name = self.items[0]
908 2197b66f René Nussbaumer
    ignore_size = bool(self._checkIntVariable('ignore_size'))
909 2197b66f René Nussbaumer
910 2197b66f René Nussbaumer
    op = opcodes.OpActivateInstanceDisks(instance_name=instance_name,
911 2197b66f René Nussbaumer
                                         ignore_size=ignore_size)
912 2197b66f René Nussbaumer
913 2197b66f René Nussbaumer
    return baserlib.SubmitJob([op])
914 2197b66f René Nussbaumer
915 2197b66f René Nussbaumer
916 0a37de5f René Nussbaumer
class R_2_instances_name_deactivate_disks(baserlib.R_Generic):
917 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
918 0a37de5f René Nussbaumer

919 0a37de5f René Nussbaumer
  """
920 0a37de5f René Nussbaumer
  def PUT(self):
921 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
922 0a37de5f René Nussbaumer

923 0a37de5f René Nussbaumer
    """
924 0a37de5f René Nussbaumer
    instance_name = self.items[0]
925 0a37de5f René Nussbaumer
926 2263aec2 René Nussbaumer
    op = opcodes.OpDeactivateInstanceDisks(instance_name=instance_name)
927 0a37de5f René Nussbaumer
928 0a37de5f René Nussbaumer
    return baserlib.SubmitJob([op])
929 0a37de5f René Nussbaumer
930 0a37de5f René Nussbaumer
931 ebeb600f Michael Hanselmann
class R_2_instances_name_prepare_export(baserlib.R_Generic):
932 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/prepare-export resource.
933 ebeb600f Michael Hanselmann

934 ebeb600f Michael Hanselmann
  """
935 ebeb600f Michael Hanselmann
  def PUT(self):
936 ebeb600f Michael Hanselmann
    """Prepares an export for an instance.
937 ebeb600f Michael Hanselmann

938 ebeb600f Michael Hanselmann
    @return: a job id
939 ebeb600f Michael Hanselmann

940 ebeb600f Michael Hanselmann
    """
941 ebeb600f Michael Hanselmann
    instance_name = self.items[0]
942 ebeb600f Michael Hanselmann
    mode = self._checkStringVariable("mode")
943 ebeb600f Michael Hanselmann
944 ebeb600f Michael Hanselmann
    op = opcodes.OpPrepareExport(instance_name=instance_name,
945 ebeb600f Michael Hanselmann
                                 mode=mode)
946 ebeb600f Michael Hanselmann
947 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
948 ebeb600f Michael Hanselmann
949 ebeb600f Michael Hanselmann
950 ebeb600f Michael Hanselmann
def _ParseExportInstanceRequest(name, data):
951 ebeb600f Michael Hanselmann
  """Parses a request for an instance export.
952 ebeb600f Michael Hanselmann

953 ebeb600f Michael Hanselmann
  @rtype: L{opcodes.OpExportInstance}
954 ebeb600f Michael Hanselmann
  @return: Instance export opcode
955 ebeb600f Michael Hanselmann

956 ebeb600f Michael Hanselmann
  """
957 ebeb600f Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode",
958 ebeb600f Michael Hanselmann
                                 default=constants.EXPORT_MODE_LOCAL)
959 ebeb600f Michael Hanselmann
  target_node = baserlib.CheckParameter(data, "destination")
960 ebeb600f Michael Hanselmann
  shutdown = baserlib.CheckParameter(data, "shutdown", exptype=bool)
961 ebeb600f Michael Hanselmann
  remove_instance = baserlib.CheckParameter(data, "remove_instance",
962 ebeb600f Michael Hanselmann
                                            exptype=bool, default=False)
963 ebeb600f Michael Hanselmann
  x509_key_name = baserlib.CheckParameter(data, "x509_key_name", default=None)
964 ebeb600f Michael Hanselmann
  destination_x509_ca = baserlib.CheckParameter(data, "destination_x509_ca",
965 ebeb600f Michael Hanselmann
                                                default=None)
966 ebeb600f Michael Hanselmann
967 ebeb600f Michael Hanselmann
  return opcodes.OpExportInstance(instance_name=name,
968 ebeb600f Michael Hanselmann
                                  mode=mode,
969 ebeb600f Michael Hanselmann
                                  target_node=target_node,
970 ebeb600f Michael Hanselmann
                                  shutdown=shutdown,
971 ebeb600f Michael Hanselmann
                                  remove_instance=remove_instance,
972 ebeb600f Michael Hanselmann
                                  x509_key_name=x509_key_name,
973 ebeb600f Michael Hanselmann
                                  destination_x509_ca=destination_x509_ca)
974 ebeb600f Michael Hanselmann
975 ebeb600f Michael Hanselmann
976 ebeb600f Michael Hanselmann
class R_2_instances_name_export(baserlib.R_Generic):
977 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/export resource.
978 ebeb600f Michael Hanselmann

979 ebeb600f Michael Hanselmann
  """
980 ebeb600f Michael Hanselmann
  def PUT(self):
981 ebeb600f Michael Hanselmann
    """Exports an instance.
982 ebeb600f Michael Hanselmann

983 ebeb600f Michael Hanselmann
    @return: a job id
984 ebeb600f Michael Hanselmann

985 ebeb600f Michael Hanselmann
    """
986 ebeb600f Michael Hanselmann
    if not isinstance(self.request_body, dict):
987 ebeb600f Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
988 ebeb600f Michael Hanselmann
989 ebeb600f Michael Hanselmann
    op = _ParseExportInstanceRequest(self.items[0], self.request_body)
990 ebeb600f Michael Hanselmann
991 ebeb600f Michael Hanselmann
    return baserlib.SubmitJob([op])
992 ebeb600f Michael Hanselmann
993 ebeb600f Michael Hanselmann
994 5823e0d2 Michael Hanselmann
def _ParseMigrateInstanceRequest(name, data):
995 5823e0d2 Michael Hanselmann
  """Parses a request for an instance migration.
996 5823e0d2 Michael Hanselmann

997 5823e0d2 Michael Hanselmann
  @rtype: L{opcodes.OpMigrateInstance}
998 5823e0d2 Michael Hanselmann
  @return: Instance migration opcode
999 5823e0d2 Michael Hanselmann

1000 5823e0d2 Michael Hanselmann
  """
1001 5823e0d2 Michael Hanselmann
  mode = baserlib.CheckParameter(data, "mode", default=None)
1002 5823e0d2 Michael Hanselmann
  cleanup = baserlib.CheckParameter(data, "cleanup", exptype=bool,
1003 5823e0d2 Michael Hanselmann
                                    default=False)
1004 5823e0d2 Michael Hanselmann
1005 5823e0d2 Michael Hanselmann
  return opcodes.OpMigrateInstance(instance_name=name, mode=mode,
1006 5823e0d2 Michael Hanselmann
                                   cleanup=cleanup)
1007 5823e0d2 Michael Hanselmann
1008 5823e0d2 Michael Hanselmann
1009 5823e0d2 Michael Hanselmann
class R_2_instances_name_migrate(baserlib.R_Generic):
1010 5823e0d2 Michael Hanselmann
  """/2/instances/[instance_name]/migrate resource.
1011 5823e0d2 Michael Hanselmann

1012 5823e0d2 Michael Hanselmann
  """
1013 5823e0d2 Michael Hanselmann
  def PUT(self):
1014 5823e0d2 Michael Hanselmann
    """Migrates an instance.
1015 5823e0d2 Michael Hanselmann

1016 5823e0d2 Michael Hanselmann
    @return: a job id
1017 5823e0d2 Michael Hanselmann

1018 5823e0d2 Michael Hanselmann
    """
1019 5823e0d2 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1020 5823e0d2 Michael Hanselmann
1021 5823e0d2 Michael Hanselmann
    op = _ParseMigrateInstanceRequest(self.items[0], self.request_body)
1022 5823e0d2 Michael Hanselmann
1023 5823e0d2 Michael Hanselmann
    return baserlib.SubmitJob([op])
1024 5823e0d2 Michael Hanselmann
1025 5823e0d2 Michael Hanselmann
1026 d56e7dc7 Michael Hanselmann
def _ParseRenameInstanceRequest(name, data):
1027 d56e7dc7 Michael Hanselmann
  """Parses a request for renaming an instance.
1028 d56e7dc7 Michael Hanselmann

1029 d56e7dc7 Michael Hanselmann
  @rtype: L{opcodes.OpRenameInstance}
1030 d56e7dc7 Michael Hanselmann
  @return: Instance rename opcode
1031 d56e7dc7 Michael Hanselmann

1032 d56e7dc7 Michael Hanselmann
  """
1033 d56e7dc7 Michael Hanselmann
  new_name = baserlib.CheckParameter(data, "new_name")
1034 d56e7dc7 Michael Hanselmann
  ip_check = baserlib.CheckParameter(data, "ip_check", default=True)
1035 d56e7dc7 Michael Hanselmann
  name_check = baserlib.CheckParameter(data, "name_check", default=True)
1036 d56e7dc7 Michael Hanselmann
1037 d56e7dc7 Michael Hanselmann
  return opcodes.OpRenameInstance(instance_name=name, new_name=new_name,
1038 d56e7dc7 Michael Hanselmann
                                  name_check=name_check, ip_check=ip_check)
1039 d56e7dc7 Michael Hanselmann
1040 d56e7dc7 Michael Hanselmann
1041 d56e7dc7 Michael Hanselmann
class R_2_instances_name_rename(baserlib.R_Generic):
1042 d56e7dc7 Michael Hanselmann
  """/2/instances/[instance_name]/rename resource.
1043 d56e7dc7 Michael Hanselmann

1044 d56e7dc7 Michael Hanselmann
  """
1045 d56e7dc7 Michael Hanselmann
  def PUT(self):
1046 d56e7dc7 Michael Hanselmann
    """Changes the name of an instance.
1047 d56e7dc7 Michael Hanselmann

1048 d56e7dc7 Michael Hanselmann
    @return: a job id
1049 d56e7dc7 Michael Hanselmann

1050 d56e7dc7 Michael Hanselmann
    """
1051 d56e7dc7 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1052 d56e7dc7 Michael Hanselmann
1053 d56e7dc7 Michael Hanselmann
    op = _ParseRenameInstanceRequest(self.items[0], self.request_body)
1054 d56e7dc7 Michael Hanselmann
1055 d56e7dc7 Michael Hanselmann
    return baserlib.SubmitJob([op])
1056 d56e7dc7 Michael Hanselmann
1057 d56e7dc7 Michael Hanselmann
1058 3882937a Michael Hanselmann
def _ParseModifyInstanceRequest(name, data):
1059 3882937a Michael Hanselmann
  """Parses a request for modifying an instance.
1060 3882937a Michael Hanselmann

1061 3882937a Michael Hanselmann
  @rtype: L{opcodes.OpSetInstanceParams}
1062 3882937a Michael Hanselmann
  @return: Instance modify opcode
1063 3882937a Michael Hanselmann

1064 3882937a Michael Hanselmann
  """
1065 3882937a Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default={})
1066 3882937a Michael Hanselmann
  force = baserlib.CheckParameter(data, "force", default=False)
1067 3882937a Michael Hanselmann
  nics = baserlib.CheckParameter(data, "nics", default=[])
1068 3882937a Michael Hanselmann
  disks = baserlib.CheckParameter(data, "disks", default=[])
1069 3882937a Michael Hanselmann
  disk_template = baserlib.CheckParameter(data, "disk_template", default=None)
1070 3882937a Michael Hanselmann
  remote_node = baserlib.CheckParameter(data, "remote_node", default=None)
1071 3882937a Michael Hanselmann
  os_name = baserlib.CheckParameter(data, "os_name", default=None)
1072 3882937a Michael Hanselmann
  force_variant = baserlib.CheckParameter(data, "force_variant", default=False)
1073 3882937a Michael Hanselmann
1074 3882937a Michael Hanselmann
  # HV/BE parameters
1075 3882937a Michael Hanselmann
  hvparams = baserlib.CheckParameter(data, "hvparams", default={})
1076 3882937a Michael Hanselmann
  utils.ForceDictType(hvparams, constants.HVS_PARAMETER_TYPES,
1077 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1078 3882937a Michael Hanselmann
1079 3882937a Michael Hanselmann
  beparams = baserlib.CheckParameter(data, "beparams", default={})
1080 3882937a Michael Hanselmann
  utils.ForceDictType(beparams, constants.BES_PARAMETER_TYPES,
1081 3882937a Michael Hanselmann
                      allowed_values=[constants.VALUE_DEFAULT])
1082 3882937a Michael Hanselmann
1083 3882937a Michael Hanselmann
  return opcodes.OpSetInstanceParams(instance_name=name, hvparams=hvparams,
1084 3882937a Michael Hanselmann
                                     beparams=beparams, osparams=osparams,
1085 3882937a Michael Hanselmann
                                     force=force, nics=nics, disks=disks,
1086 3882937a Michael Hanselmann
                                     disk_template=disk_template,
1087 3882937a Michael Hanselmann
                                     remote_node=remote_node, os_name=os_name,
1088 3882937a Michael Hanselmann
                                     force_variant=force_variant)
1089 3882937a Michael Hanselmann
1090 3882937a Michael Hanselmann
1091 3882937a Michael Hanselmann
class R_2_instances_name_modify(baserlib.R_Generic):
1092 3882937a Michael Hanselmann
  """/2/instances/[instance_name]/modify resource.
1093 3882937a Michael Hanselmann

1094 3882937a Michael Hanselmann
  """
1095 3882937a Michael Hanselmann
  def PUT(self):
1096 3882937a Michael Hanselmann
    """Changes some parameters of an instance.
1097 3882937a Michael Hanselmann

1098 3882937a Michael Hanselmann
    @return: a job id
1099 3882937a Michael Hanselmann

1100 3882937a Michael Hanselmann
    """
1101 3882937a Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
1102 3882937a Michael Hanselmann
1103 3882937a Michael Hanselmann
    op = _ParseModifyInstanceRequest(self.items[0], self.request_body)
1104 3882937a Michael Hanselmann
1105 3882937a Michael Hanselmann
    return baserlib.SubmitJob([op])
1106 3882937a Michael Hanselmann
1107 3882937a Michael Hanselmann
1108 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
1109 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
1110 441e7cfd Oleksiy Mishchenko

1111 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
1112 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
1113 441e7cfd Oleksiy Mishchenko

1114 441e7cfd Oleksiy Mishchenko
  """
1115 7a6b9510 Iustin Pop
  TAG_LEVEL = None
1116 18cb43a2 Oleksiy Mishchenko
1117 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
1118 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
1119 18cb43a2 Oleksiy Mishchenko

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

1122 18cb43a2 Oleksiy Mishchenko
    """
1123 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
1124 18cb43a2 Oleksiy Mishchenko
1125 5313eed7 Michael Hanselmann
    if self.TAG_LEVEL == constants.TAG_CLUSTER:
1126 5313eed7 Michael Hanselmann
      self.name = None
1127 18cb43a2 Oleksiy Mishchenko
    else:
1128 5313eed7 Michael Hanselmann
      self.name = items[0]
1129 441e7cfd Oleksiy Mishchenko
1130 441e7cfd Oleksiy Mishchenko
  def GET(self):
1131 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
1132 441e7cfd Oleksiy Mishchenko

1133 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
1134 441e7cfd Oleksiy Mishchenko

1135 441e7cfd Oleksiy Mishchenko
    """
1136 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1137 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
1138 441e7cfd Oleksiy Mishchenko
1139 21f04e5e Oleksiy Mishchenko
  def PUT(self):
1140 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
1141 441e7cfd Oleksiy Mishchenko

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

1145 441e7cfd Oleksiy Mishchenko
    """
1146 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1147 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
1148 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
1149 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
1150 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
1151 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
1152 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
1153 15fd9fd5 Oleksiy Mishchenko
1154 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
1155 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
1156 15fd9fd5 Oleksiy Mishchenko

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

1161 15fd9fd5 Oleksiy Mishchenko
    """
1162 7260cfbe Iustin Pop
    # pylint: disable-msg=W0212
1163 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
1164 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
1165 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
1166 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
1167 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
1168 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
1169 6f59b964 Iustin Pop
                                 name=self.name,
1170 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
1171 18cb43a2 Oleksiy Mishchenko
1172 18cb43a2 Oleksiy Mishchenko
1173 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
1174 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
1175 18cb43a2 Oleksiy Mishchenko

1176 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
1177 18cb43a2 Oleksiy Mishchenko

1178 18cb43a2 Oleksiy Mishchenko
  """
1179 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
1180 18cb43a2 Oleksiy Mishchenko
1181 18cb43a2 Oleksiy Mishchenko
1182 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
1183 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
1184 18cb43a2 Oleksiy Mishchenko

1185 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
1186 18cb43a2 Oleksiy Mishchenko

1187 18cb43a2 Oleksiy Mishchenko
  """
1188 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
1189 18cb43a2 Oleksiy Mishchenko
1190 18cb43a2 Oleksiy Mishchenko
1191 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
1192 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
1193 18cb43a2 Oleksiy Mishchenko

1194 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
1195 18cb43a2 Oleksiy Mishchenko

1196 18cb43a2 Oleksiy Mishchenko
  """
1197 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER