Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 1a705513

History | View | Annotate | Download (39 kB)

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

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

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

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

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

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

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

52 10b207d4 Oleksiy Mishchenko
"""
53 10b207d4 Oleksiy Mishchenko
54 b459a848 Andrea Spadaccini
# pylint: disable=C0103
55 fe267188 Iustin Pop
56 fe267188 Iustin Pop
# C0103: Invalid name, since the R_* names are not conforming
57 fe267188 Iustin Pop
58 59b4eeef Iustin Pop
from ganeti import opcodes
59 e5ff1a47 René Nussbaumer
from ganeti import objects
60 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
61 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
62 59b4eeef Iustin Pop
from ganeti import cli
63 8381fa2d Michael Hanselmann
from ganeti import rapi
64 d1c172de Michael Hanselmann
from ganeti import ht
65 e987f166 Michael Hanselmann
from ganeti import compat
66 be1ddd09 Michael Hanselmann
from ganeti import ssconf
67 38206f3c Iustin Pop
from ganeti.rapi import baserlib
68 10b207d4 Oleksiy Mishchenko
69 4e5a68f8 Oleksiy Mishchenko
70 7118a0df Iustin Pop
_COMMON_FIELDS = ["ctime", "mtime", "uuid", "serial_no", "tags"]
71 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
72 9031ee8e Iustin Pop
            "pnode", "snodes",
73 9031ee8e Iustin Pop
            "disk_template",
74 9b5a7ce9 Christos Stavrakakis
            "nic.ips", "nic.macs", "nic.modes", "nic.uuids", "nic.names",
75 95c83fe6 Christos Stavrakakis
            "nic.links", "nic.networks", "nic.networks.names", "nic.bridges",
76 a8b16c4e Tim Boring
            "network_port",
77 17cda747 Guido Trotter
            "disk.sizes", "disk.spindles", "disk_usage", "disk.uuids",
78 17cda747 Guido Trotter
            "disk.names",
79 a5b9d725 Iustin Pop
            "beparams", "hvparams",
80 4ea3de4e Balazs Lecz
            "oper_state", "oper_ram", "oper_vcpus", "status",
81 90224407 Iustin Pop
            "custom_hvparams", "custom_beparams", "custom_nicparams",
82 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
83 9031ee8e Iustin Pop
84 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
85 06fb92cf Bernardo Dal Seno
            "dtotal", "dfree", "sptotal", "spfree",
86 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
87 7118a0df Iustin Pop
            "pinst_cnt", "sinst_cnt",
88 f43c898d Bernardo Dal Seno
            "ctotal", "cnos", "cnodes", "csockets",
89 7118a0df Iustin Pop
            "pip", "sip", "role",
90 93962b80 Iustin Pop
            "pinst_list", "sinst_list",
91 c190e817 Iustin Pop
            "master_capable", "vm_capable",
92 37e61a77 Iustin Pop
            "ndparams",
93 fd254195 Iustin Pop
            "group.uuid",
94 7118a0df Iustin Pop
            ] + _COMMON_FIELDS
95 4e5a68f8 Oleksiy Mishchenko
96 4588b4bd Dimitris Aragiorgis
NET_FIELDS = ["name", "network", "gateway",
97 4588b4bd Dimitris Aragiorgis
              "network6", "gateway6",
98 5cfa6c37 Dimitris Aragiorgis
              "mac_prefix",
99 4588b4bd Dimitris Aragiorgis
              "free_count", "reserved_count",
100 4588b4bd Dimitris Aragiorgis
              "map", "group_list", "inst_list",
101 95c83fe6 Christos Stavrakakis
              "external_reservations",
102 95c83fe6 Christos Stavrakakis
              ] + _COMMON_FIELDS
103 4588b4bd Dimitris Aragiorgis
104 f4e86448 Michael Hanselmann
G_FIELDS = [
105 f4e86448 Michael Hanselmann
  "alloc_policy",
106 f4e86448 Michael Hanselmann
  "name",
107 f4e86448 Michael Hanselmann
  "node_cnt",
108 f4e86448 Michael Hanselmann
  "node_list",
109 edd49f9b Agata Murawska
  "ipolicy",
110 003306f9 Iustin Pop
  "custom_ipolicy",
111 003306f9 Iustin Pop
  "diskparams",
112 003306f9 Iustin Pop
  "custom_diskparams",
113 003306f9 Iustin Pop
  "ndparams",
114 003306f9 Iustin Pop
  "custom_ndparams",
115 f4e86448 Michael Hanselmann
  ] + _COMMON_FIELDS
116 0897dc97 Adeodato Simo
117 bd7b2070 Michael Hanselmann
J_FIELDS_BULK = [
118 e987f166 Michael Hanselmann
  "id", "ops", "status", "summary",
119 bd7b2070 Michael Hanselmann
  "opstatus",
120 e987f166 Michael Hanselmann
  "received_ts", "start_ts", "end_ts",
121 e987f166 Michael Hanselmann
  ]
122 e987f166 Michael Hanselmann
123 bd7b2070 Michael Hanselmann
J_FIELDS = J_FIELDS_BULK + [
124 bd7b2070 Michael Hanselmann
  "oplog",
125 bd7b2070 Michael Hanselmann
  "opresult",
126 bd7b2070 Michael Hanselmann
  ]
127 bd7b2070 Michael Hanselmann
128 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
129 51cc8637 Michael Hanselmann
_NR_MASTER_CANDIDATE = "master-candidate"
130 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
131 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
132 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
133 64dae8fc Michael Hanselmann
134 64dae8fc Michael Hanselmann
_NR_MAP = {
135 1e28e3b8 Michael Hanselmann
  constants.NR_MASTER: _NR_MASTER,
136 51cc8637 Michael Hanselmann
  constants.NR_MCANDIDATE: _NR_MASTER_CANDIDATE,
137 1e28e3b8 Michael Hanselmann
  constants.NR_DRAINED: _NR_DRAINED,
138 1e28e3b8 Michael Hanselmann
  constants.NR_OFFLINE: _NR_OFFLINE,
139 1e28e3b8 Michael Hanselmann
  constants.NR_REGULAR: _NR_REGULAR,
140 64dae8fc Michael Hanselmann
  }
141 64dae8fc Michael Hanselmann
142 1e28e3b8 Michael Hanselmann
assert frozenset(_NR_MAP.keys()) == constants.NR_ALL
143 1e28e3b8 Michael Hanselmann
144 d975f482 Michael Hanselmann
# Request data version field
145 d975f482 Michael Hanselmann
_REQ_DATA_VERSION = "__version__"
146 d975f482 Michael Hanselmann
147 6395cebb Michael Hanselmann
# Feature string for instance creation request data version 1
148 6395cebb Michael Hanselmann
_INST_CREATE_REQV1 = "instance-create-reqv1"
149 6395cebb Michael Hanselmann
150 c744425f Michael Hanselmann
# Feature string for instance reinstall request version 1
151 c744425f Michael Hanselmann
_INST_REINSTALL_REQV1 = "instance-reinstall-reqv1"
152 c744425f Michael Hanselmann
153 b7a1c816 Michael Hanselmann
# Feature string for node migration version 1
154 b7a1c816 Michael Hanselmann
_NODE_MIGRATE_REQV1 = "node-migrate-reqv1"
155 b7a1c816 Michael Hanselmann
156 de40437a Michael Hanselmann
# Feature string for node evacuation with LU-generated jobs
157 de40437a Michael Hanselmann
_NODE_EVAC_RES1 = "node-evac-res1"
158 de40437a Michael Hanselmann
159 b8028dcf Michael Hanselmann
ALL_FEATURES = compat.UniqueFrozenset([
160 b4fcee5b Michael Hanselmann
  _INST_CREATE_REQV1,
161 b4fcee5b Michael Hanselmann
  _INST_REINSTALL_REQV1,
162 b4fcee5b Michael Hanselmann
  _NODE_MIGRATE_REQV1,
163 b4fcee5b Michael Hanselmann
  _NODE_EVAC_RES1,
164 b4fcee5b Michael Hanselmann
  ])
165 b4fcee5b Michael Hanselmann
166 793a8f7c Michael Hanselmann
# Timeout for /2/jobs/[job_id]/wait. Gives job up to 10 seconds to change.
167 793a8f7c Michael Hanselmann
_WFJC_TIMEOUT = 10
168 793a8f7c Michael Hanselmann
169 4e5a68f8 Oleksiy Mishchenko
170 28a45bfc René Nussbaumer
# FIXME: For compatibility we update the beparams/memory field. Needs to be
171 09b7b6f2 Michele Tartara
#        removed in Ganeti 2.8
172 28a45bfc René Nussbaumer
def _UpdateBeparams(inst):
173 28a45bfc René Nussbaumer
  """Updates the beparams dict of inst to support the memory field.
174 28a45bfc René Nussbaumer

175 28a45bfc René Nussbaumer
  @param inst: Inst dict
176 28a45bfc René Nussbaumer
  @return: Updated inst dict
177 28a45bfc René Nussbaumer

178 28a45bfc René Nussbaumer
  """
179 28a45bfc René Nussbaumer
  beparams = inst["beparams"]
180 28a45bfc René Nussbaumer
  beparams[constants.BE_MEMORY] = beparams[constants.BE_MAXMEM]
181 28a45bfc René Nussbaumer
182 28a45bfc René Nussbaumer
  return inst
183 28a45bfc René Nussbaumer
184 28a45bfc René Nussbaumer
185 26ff6ee2 Michael Hanselmann
class R_root(baserlib.ResourceBase):
186 0f945c65 Michael Hanselmann
  """/ resource.
187 0f945c65 Michael Hanselmann

188 0f945c65 Michael Hanselmann
  """
189 0f945c65 Michael Hanselmann
  @staticmethod
190 0f945c65 Michael Hanselmann
  def GET():
191 0f945c65 Michael Hanselmann
    """Supported for legacy reasons.
192 0f945c65 Michael Hanselmann

193 0f945c65 Michael Hanselmann
    """
194 0f945c65 Michael Hanselmann
    return None
195 0f945c65 Michael Hanselmann
196 0f945c65 Michael Hanselmann
197 132cdb87 Michael Hanselmann
class R_2(R_root):
198 132cdb87 Michael Hanselmann
  """/2 resource.
199 132cdb87 Michael Hanselmann

200 132cdb87 Michael Hanselmann
  """
201 132cdb87 Michael Hanselmann
202 132cdb87 Michael Hanselmann
203 26ff6ee2 Michael Hanselmann
class R_version(baserlib.ResourceBase):
204 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
205 4e5a68f8 Oleksiy Mishchenko

206 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
207 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
208 4e5a68f8 Oleksiy Mishchenko

209 4e5a68f8 Oleksiy Mishchenko
  """
210 7e950d31 Iustin Pop
  @staticmethod
211 7e950d31 Iustin Pop
  def GET():
212 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
213 4e5a68f8 Oleksiy Mishchenko

214 4e5a68f8 Oleksiy Mishchenko
    """
215 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
216 4e5a68f8 Oleksiy Mishchenko
217 4e5a68f8 Oleksiy Mishchenko
218 f6ce0ba2 Michael Hanselmann
class R_2_info(baserlib.OpcodeResource):
219 b58a4d16 Michael Hanselmann
  """/2/info resource.
220 4e5a68f8 Oleksiy Mishchenko

221 4e5a68f8 Oleksiy Mishchenko
  """
222 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpClusterQuery
223 f6ce0ba2 Michael Hanselmann
224 be1ddd09 Michael Hanselmann
  def GET(self):
225 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
226 4e5a68f8 Oleksiy Mishchenko

227 4e5a68f8 Oleksiy Mishchenko
    """
228 a2160e57 Iustin Pop
    client = self.GetClient(query=True)
229 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
230 4e5a68f8 Oleksiy Mishchenko
231 4e5a68f8 Oleksiy Mishchenko
232 26ff6ee2 Michael Hanselmann
class R_2_features(baserlib.ResourceBase):
233 7eac4a4d Michael Hanselmann
  """/2/features resource.
234 7eac4a4d Michael Hanselmann

235 7eac4a4d Michael Hanselmann
  """
236 7eac4a4d Michael Hanselmann
  @staticmethod
237 7eac4a4d Michael Hanselmann
  def GET():
238 7eac4a4d Michael Hanselmann
    """Returns list of optional RAPI features implemented.
239 7eac4a4d Michael Hanselmann

240 7eac4a4d Michael Hanselmann
    """
241 b4fcee5b Michael Hanselmann
    return list(ALL_FEATURES)
242 7eac4a4d Michael Hanselmann
243 7eac4a4d Michael Hanselmann
244 f6ce0ba2 Michael Hanselmann
class R_2_os(baserlib.OpcodeResource):
245 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
246 4e5a68f8 Oleksiy Mishchenko

247 4e5a68f8 Oleksiy Mishchenko
  """
248 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpOsDiagnose
249 f6ce0ba2 Michael Hanselmann
250 be1ddd09 Michael Hanselmann
  def GET(self):
251 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
252 4e5a68f8 Oleksiy Mishchenko

253 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
254 4e5a68f8 Oleksiy Mishchenko

255 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
256 4e5a68f8 Oleksiy Mishchenko

257 4e5a68f8 Oleksiy Mishchenko
    """
258 be1ddd09 Michael Hanselmann
    cl = self.GetClient()
259 da2d02e7 Iustin Pop
    op = opcodes.OpOsDiagnose(output_fields=["name", "variants"], names=[])
260 be1ddd09 Michael Hanselmann
    job_id = self.SubmitJob([op], cl=cl)
261 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
262 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
263 59b4eeef Iustin Pop
    diagnose_data = result[0]
264 4e5a68f8 Oleksiy Mishchenko
265 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
266 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
267 4e5a68f8 Oleksiy Mishchenko
268 e3ac208c Guido Trotter
    os_names = []
269 d22dfef7 Iustin Pop
    for (name, variants) in diagnose_data:
270 d22dfef7 Iustin Pop
      os_names.extend(cli.CalculateOSNames(name, variants))
271 e3ac208c Guido Trotter
272 e3ac208c Guido Trotter
    return os_names
273 51ee2f49 Oleksiy Mishchenko
274 10b207d4 Oleksiy Mishchenko
275 8fd625fc Michael Hanselmann
class R_2_redist_config(baserlib.OpcodeResource):
276 508e9b20 Michael Hanselmann
  """/2/redistribute-config resource.
277 508e9b20 Michael Hanselmann

278 508e9b20 Michael Hanselmann
  """
279 8fd625fc Michael Hanselmann
  PUT_OPCODE = opcodes.OpClusterRedistConf
280 508e9b20 Michael Hanselmann
281 508e9b20 Michael Hanselmann
282 50c7d82e Michael Hanselmann
class R_2_cluster_modify(baserlib.OpcodeResource):
283 62e999a5 Michael Hanselmann
  """/2/modify resource.
284 62e999a5 Michael Hanselmann

285 62e999a5 Michael Hanselmann
  """
286 50c7d82e Michael Hanselmann
  PUT_OPCODE = opcodes.OpClusterSetParams
287 62e999a5 Michael Hanselmann
288 62e999a5 Michael Hanselmann
289 26ff6ee2 Michael Hanselmann
class R_2_jobs(baserlib.ResourceBase):
290 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
291 10b207d4 Oleksiy Mishchenko

292 10b207d4 Oleksiy Mishchenko
  """
293 e987f166 Michael Hanselmann
  def GET(self):
294 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
295 10b207d4 Oleksiy Mishchenko

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

298 10b207d4 Oleksiy Mishchenko
    """
299 d45a824b Iustin Pop
    client = self.GetClient(query=True)
300 e987f166 Michael Hanselmann
301 e987f166 Michael Hanselmann
    if self.useBulk():
302 bd7b2070 Michael Hanselmann
      bulkdata = client.QueryJobs(None, J_FIELDS_BULK)
303 bd7b2070 Michael Hanselmann
      return baserlib.MapBulkFields(bulkdata, J_FIELDS_BULK)
304 e987f166 Michael Hanselmann
    else:
305 e987f166 Michael Hanselmann
      jobdata = map(compat.fst, client.QueryJobs(None, ["id"]))
306 e987f166 Michael Hanselmann
      return baserlib.BuildUriList(jobdata, "/2/jobs/%s",
307 e987f166 Michael Hanselmann
                                   uri_fields=("id", "uri"))
308 10b207d4 Oleksiy Mishchenko
309 10b207d4 Oleksiy Mishchenko
310 26ff6ee2 Michael Hanselmann
class R_2_jobs_id(baserlib.ResourceBase):
311 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
312 10b207d4 Oleksiy Mishchenko

313 10b207d4 Oleksiy Mishchenko
  """
314 10b207d4 Oleksiy Mishchenko
  def GET(self):
315 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
316 10b207d4 Oleksiy Mishchenko

317 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
318 c41eea6e Iustin Pop
        The result includes:
319 c41eea6e Iustin Pop
            - id: job ID as a number
320 c41eea6e Iustin Pop
            - status: current job status as a string
321 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
322 c41eea6e Iustin Pop
              opcodes in the job
323 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
324 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
325 38206f3c Iustin Pop

326 10b207d4 Oleksiy Mishchenko
    """
327 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
328 d45a824b Iustin Pop
    result = self.GetClient(query=True).QueryJobs([job_id, ], J_FIELDS)[0]
329 ee69c97f Iustin Pop
    if result is None:
330 ee69c97f Iustin Pop
      raise http.HttpNotFound()
331 e987f166 Michael Hanselmann
    return baserlib.MapFields(J_FIELDS, result)
332 10b207d4 Oleksiy Mishchenko
333 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
334 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
335 c7f5f338 Oleksiy Mishchenko

336 c7f5f338 Oleksiy Mishchenko
    """
337 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
338 be1ddd09 Michael Hanselmann
    result = self.GetClient().CancelJob(job_id)
339 c7f5f338 Oleksiy Mishchenko
    return result
340 c7f5f338 Oleksiy Mishchenko
341 10b207d4 Oleksiy Mishchenko
342 26ff6ee2 Michael Hanselmann
class R_2_jobs_id_wait(baserlib.ResourceBase):
343 793a8f7c Michael Hanselmann
  """/2/jobs/[job_id]/wait resource.
344 793a8f7c Michael Hanselmann

345 793a8f7c Michael Hanselmann
  """
346 793a8f7c Michael Hanselmann
  # WaitForJobChange provides access to sensitive information and blocks
347 793a8f7c Michael Hanselmann
  # machine resources (it's a blocking RAPI call), hence restricting access.
348 793a8f7c Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
349 793a8f7c Michael Hanselmann
350 793a8f7c Michael Hanselmann
  def GET(self):
351 793a8f7c Michael Hanselmann
    """Waits for job changes.
352 793a8f7c Michael Hanselmann

353 793a8f7c Michael Hanselmann
    """
354 793a8f7c Michael Hanselmann
    job_id = self.items[0]
355 793a8f7c Michael Hanselmann
356 793a8f7c Michael Hanselmann
    fields = self.getBodyParameter("fields")
357 793a8f7c Michael Hanselmann
    prev_job_info = self.getBodyParameter("previous_job_info", None)
358 793a8f7c Michael Hanselmann
    prev_log_serial = self.getBodyParameter("previous_log_serial", None)
359 793a8f7c Michael Hanselmann
360 793a8f7c Michael Hanselmann
    if not isinstance(fields, list):
361 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'fields' parameter should be a list")
362 793a8f7c Michael Hanselmann
363 793a8f7c Michael Hanselmann
    if not (prev_job_info is None or isinstance(prev_job_info, list)):
364 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_job_info' parameter should"
365 793a8f7c Michael Hanselmann
                                " be a list")
366 793a8f7c Michael Hanselmann
367 793a8f7c Michael Hanselmann
    if not (prev_log_serial is None or
368 793a8f7c Michael Hanselmann
            isinstance(prev_log_serial, (int, long))):
369 793a8f7c Michael Hanselmann
      raise http.HttpBadRequest("The 'previous_log_serial' parameter should"
370 793a8f7c Michael Hanselmann
                                " be a number")
371 793a8f7c Michael Hanselmann
372 be1ddd09 Michael Hanselmann
    client = self.GetClient()
373 793a8f7c Michael Hanselmann
    result = client.WaitForJobChangeOnce(job_id, fields,
374 793a8f7c Michael Hanselmann
                                         prev_job_info, prev_log_serial,
375 793a8f7c Michael Hanselmann
                                         timeout=_WFJC_TIMEOUT)
376 793a8f7c Michael Hanselmann
    if not result:
377 793a8f7c Michael Hanselmann
      raise http.HttpNotFound()
378 793a8f7c Michael Hanselmann
379 793a8f7c Michael Hanselmann
    if result == constants.JOB_NOTCHANGED:
380 793a8f7c Michael Hanselmann
      # No changes
381 793a8f7c Michael Hanselmann
      return None
382 793a8f7c Michael Hanselmann
383 793a8f7c Michael Hanselmann
    (job_info, log_entries) = result
384 793a8f7c Michael Hanselmann
385 793a8f7c Michael Hanselmann
    return {
386 793a8f7c Michael Hanselmann
      "job_info": job_info,
387 793a8f7c Michael Hanselmann
      "log_entries": log_entries,
388 793a8f7c Michael Hanselmann
      }
389 793a8f7c Michael Hanselmann
390 793a8f7c Michael Hanselmann
391 f6ce0ba2 Michael Hanselmann
class R_2_nodes(baserlib.OpcodeResource):
392 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
393 10b207d4 Oleksiy Mishchenko

394 10b207d4 Oleksiy Mishchenko
  """
395 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpNodeQuery
396 f6ce0ba2 Michael Hanselmann
397 10b207d4 Oleksiy Mishchenko
  def GET(self):
398 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
399 38206f3c Iustin Pop

400 10b207d4 Oleksiy Mishchenko
    """
401 d9a22528 Iustin Pop
    client = self.GetClient(query=True)
402 38206f3c Iustin Pop
403 3d103742 Iustin Pop
    if self.useBulk():
404 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
405 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
406 9031ee8e Iustin Pop
    else:
407 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
408 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
409 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
410 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
411 441e7cfd Oleksiy Mishchenko
412 441e7cfd Oleksiy Mishchenko
413 f6ce0ba2 Michael Hanselmann
class R_2_nodes_name(baserlib.OpcodeResource):
414 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name] resource.
415 028c6b76 Oleksiy Mishchenko

416 028c6b76 Oleksiy Mishchenko
  """
417 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpNodeQuery
418 f6ce0ba2 Michael Hanselmann
419 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
420 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
421 4e5a68f8 Oleksiy Mishchenko

422 4e5a68f8 Oleksiy Mishchenko
    """
423 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
424 d9a22528 Iustin Pop
    client = self.GetClient(query=True)
425 e8ebbd2b Michael Hanselmann
426 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryNodes,
427 e8ebbd2b Michael Hanselmann
                                            names=[node_name], fields=N_FIELDS,
428 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
429 4e5a68f8 Oleksiy Mishchenko
430 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
431 028c6b76 Oleksiy Mishchenko
432 028c6b76 Oleksiy Mishchenko
433 42d4d8b9 Michael Hanselmann
class R_2_nodes_name_powercycle(baserlib.OpcodeResource):
434 42d4d8b9 Michael Hanselmann
  """/2/nodes/[node_name]/powercycle resource.
435 42d4d8b9 Michael Hanselmann

436 42d4d8b9 Michael Hanselmann
  """
437 42d4d8b9 Michael Hanselmann
  POST_OPCODE = opcodes.OpNodePowercycle
438 42d4d8b9 Michael Hanselmann
439 42d4d8b9 Michael Hanselmann
  def GetPostOpInput(self):
440 42d4d8b9 Michael Hanselmann
    """Tries to powercycle a node.
441 42d4d8b9 Michael Hanselmann

442 42d4d8b9 Michael Hanselmann
    """
443 42d4d8b9 Michael Hanselmann
    return (self.request_body, {
444 42d4d8b9 Michael Hanselmann
      "node_name": self.items[0],
445 42d4d8b9 Michael Hanselmann
      "force": self.useForce(),
446 42d4d8b9 Michael Hanselmann
      })
447 42d4d8b9 Michael Hanselmann
448 42d4d8b9 Michael Hanselmann
449 51cc8637 Michael Hanselmann
class R_2_nodes_name_role(baserlib.OpcodeResource):
450 51cc8637 Michael Hanselmann
  """/2/nodes/[node_name]/role resource.
451 64dae8fc Michael Hanselmann

452 64dae8fc Michael Hanselmann
  """
453 51cc8637 Michael Hanselmann
  PUT_OPCODE = opcodes.OpNodeSetParams
454 51cc8637 Michael Hanselmann
455 64dae8fc Michael Hanselmann
  def GET(self):
456 64dae8fc Michael Hanselmann
    """Returns the current node role.
457 64dae8fc Michael Hanselmann

458 64dae8fc Michael Hanselmann
    @return: Node role
459 64dae8fc Michael Hanselmann

460 64dae8fc Michael Hanselmann
    """
461 64dae8fc Michael Hanselmann
    node_name = self.items[0]
462 9fbf0098 Iustin Pop
    client = self.GetClient(query=True)
463 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
464 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
465 64dae8fc Michael Hanselmann
466 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
467 64dae8fc Michael Hanselmann
468 51cc8637 Michael Hanselmann
  def GetPutOpInput(self):
469 64dae8fc Michael Hanselmann
    """Sets the node role.
470 64dae8fc Michael Hanselmann

471 64dae8fc Michael Hanselmann
    """
472 51cc8637 Michael Hanselmann
    baserlib.CheckType(self.request_body, basestring, "Body contents")
473 64dae8fc Michael Hanselmann
474 627ad739 Michael Hanselmann
    role = self.request_body
475 64dae8fc Michael Hanselmann
476 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
477 64dae8fc Michael Hanselmann
      candidate = False
478 64dae8fc Michael Hanselmann
      offline = False
479 64dae8fc Michael Hanselmann
      drained = False
480 64dae8fc Michael Hanselmann
481 51cc8637 Michael Hanselmann
    elif role == _NR_MASTER_CANDIDATE:
482 64dae8fc Michael Hanselmann
      candidate = True
483 64dae8fc Michael Hanselmann
      offline = drained = None
484 64dae8fc Michael Hanselmann
485 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
486 64dae8fc Michael Hanselmann
      drained = True
487 64dae8fc Michael Hanselmann
      candidate = offline = None
488 64dae8fc Michael Hanselmann
489 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
490 64dae8fc Michael Hanselmann
      offline = True
491 64dae8fc Michael Hanselmann
      candidate = drained = None
492 64dae8fc Michael Hanselmann
493 64dae8fc Michael Hanselmann
    else:
494 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
495 64dae8fc Michael Hanselmann
496 51cc8637 Michael Hanselmann
    assert len(self.items) == 1
497 64dae8fc Michael Hanselmann
498 51cc8637 Michael Hanselmann
    return ({}, {
499 51cc8637 Michael Hanselmann
      "node_name": self.items[0],
500 51cc8637 Michael Hanselmann
      "master_candidate": candidate,
501 51cc8637 Michael Hanselmann
      "offline": offline,
502 51cc8637 Michael Hanselmann
      "drained": drained,
503 51cc8637 Michael Hanselmann
      "force": self.useForce(),
504 682878d9 Guido Trotter
      "auto_promote": bool(self._checkIntVariable("auto-promote", default=0)),
505 51cc8637 Michael Hanselmann
      })
506 64dae8fc Michael Hanselmann
507 64dae8fc Michael Hanselmann
508 7fa91722 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.OpcodeResource):
509 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
510 73452f12 Michael Hanselmann

511 73452f12 Michael Hanselmann
  """
512 7fa91722 Michael Hanselmann
  POST_OPCODE = opcodes.OpNodeEvacuate
513 7fa91722 Michael Hanselmann
514 7fa91722 Michael Hanselmann
  def GetPostOpInput(self):
515 de40437a Michael Hanselmann
    """Evacuate all instances off a node.
516 73452f12 Michael Hanselmann

517 73452f12 Michael Hanselmann
    """
518 7fa91722 Michael Hanselmann
    return (self.request_body, {
519 de40437a Michael Hanselmann
      "node_name": self.items[0],
520 de40437a Michael Hanselmann
      "dry_run": self.dryRun(),
521 de40437a Michael Hanselmann
      })
522 941b9309 Iustin Pop
523 73452f12 Michael Hanselmann
524 55168cc7 Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.OpcodeResource):
525 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
526 1c482bab Michael Hanselmann

527 1c482bab Michael Hanselmann
  """
528 55168cc7 Michael Hanselmann
  POST_OPCODE = opcodes.OpNodeMigrate
529 55168cc7 Michael Hanselmann
530 55168cc7 Michael Hanselmann
  def GetPostOpInput(self):
531 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
532 1c482bab Michael Hanselmann

533 1c482bab Michael Hanselmann
    """
534 b7a1c816 Michael Hanselmann
    if self.queryargs:
535 b7a1c816 Michael Hanselmann
      # Support old-style requests
536 b7a1c816 Michael Hanselmann
      if "live" in self.queryargs and "mode" in self.queryargs:
537 b7a1c816 Michael Hanselmann
        raise http.HttpBadRequest("Only one of 'live' and 'mode' should"
538 b7a1c816 Michael Hanselmann
                                  " be passed")
539 b7a1c816 Michael Hanselmann
540 b7a1c816 Michael Hanselmann
      if "live" in self.queryargs:
541 b7a1c816 Michael Hanselmann
        if self._checkIntVariable("live", default=1):
542 b7a1c816 Michael Hanselmann
          mode = constants.HT_MIGRATION_LIVE
543 b7a1c816 Michael Hanselmann
        else:
544 b7a1c816 Michael Hanselmann
          mode = constants.HT_MIGRATION_NONLIVE
545 52194140 Iustin Pop
      else:
546 b7a1c816 Michael Hanselmann
        mode = self._checkStringVariable("mode", default=None)
547 b7a1c816 Michael Hanselmann
548 b7a1c816 Michael Hanselmann
      data = {
549 b7a1c816 Michael Hanselmann
        "mode": mode,
550 b7a1c816 Michael Hanselmann
        }
551 52194140 Iustin Pop
    else:
552 b7a1c816 Michael Hanselmann
      data = self.request_body
553 52194140 Iustin Pop
554 55168cc7 Michael Hanselmann
    return (data, {
555 55168cc7 Michael Hanselmann
      "node_name": self.items[0],
556 b7a1c816 Michael Hanselmann
      })
557 1c482bab Michael Hanselmann
558 1c482bab Michael Hanselmann
559 682878d9 Guido Trotter
class R_2_nodes_name_modify(baserlib.OpcodeResource):
560 94497dd1 Michael Hanselmann
  """/2/nodes/[node_name]/modify resource.
561 94497dd1 Michael Hanselmann

562 94497dd1 Michael Hanselmann
  """
563 8b8f54dd Guido Trotter
  POST_OPCODE = opcodes.OpNodeSetParams
564 94497dd1 Michael Hanselmann
565 8b8f54dd Guido Trotter
  def GetPostOpInput(self):
566 682878d9 Guido Trotter
    """Changes parameters of a node.
567 94497dd1 Michael Hanselmann

568 94497dd1 Michael Hanselmann
    """
569 682878d9 Guido Trotter
    assert len(self.items) == 1
570 94497dd1 Michael Hanselmann
571 682878d9 Guido Trotter
    return (self.request_body, {
572 370f2042 Guido Trotter
      "node_name": self.items[0],
573 94497dd1 Michael Hanselmann
      })
574 94497dd1 Michael Hanselmann
575 94497dd1 Michael Hanselmann
576 eb08e09d Michael Hanselmann
class R_2_nodes_name_storage(baserlib.OpcodeResource):
577 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage resource.
578 7a95a954 Michael Hanselmann

579 7a95a954 Michael Hanselmann
  """
580 ad8d0595 Iustin Pop
  # LUNodeQueryStorage acquires locks, hence restricting access to GET
581 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
582 eb08e09d Michael Hanselmann
  GET_OPCODE = opcodes.OpNodeQueryStorage
583 7a95a954 Michael Hanselmann
584 eb08e09d Michael Hanselmann
  def GetGetOpInput(self):
585 eb08e09d Michael Hanselmann
    """List storage available on a node.
586 7a95a954 Michael Hanselmann

587 eb08e09d Michael Hanselmann
    """
588 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
589 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
590 eb08e09d Michael Hanselmann
591 7a95a954 Michael Hanselmann
    if not output_fields:
592 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
593 7a95a954 Michael Hanselmann
                                " parameter")
594 7a95a954 Michael Hanselmann
595 eb08e09d Michael Hanselmann
    return ({}, {
596 eb08e09d Michael Hanselmann
      "nodes": [self.items[0]],
597 eb08e09d Michael Hanselmann
      "storage_type": storage_type,
598 eb08e09d Michael Hanselmann
      "output_fields": output_fields.split(","),
599 eb08e09d Michael Hanselmann
      })
600 7a95a954 Michael Hanselmann
601 7a95a954 Michael Hanselmann
602 8d232068 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.OpcodeResource):
603 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify resource.
604 1e82bc80 Michael Hanselmann

605 1e82bc80 Michael Hanselmann
  """
606 8d232068 Michael Hanselmann
  PUT_OPCODE = opcodes.OpNodeModifyStorage
607 1e82bc80 Michael Hanselmann
608 8d232068 Michael Hanselmann
  def GetPutOpInput(self):
609 8d232068 Michael Hanselmann
    """Modifies a storage volume on a node.
610 1e82bc80 Michael Hanselmann

611 8d232068 Michael Hanselmann
    """
612 8d232068 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
613 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
614 8d232068 Michael Hanselmann
615 1e82bc80 Michael Hanselmann
    if not name:
616 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
617 1e82bc80 Michael Hanselmann
                                " parameter")
618 1e82bc80 Michael Hanselmann
619 1e82bc80 Michael Hanselmann
    changes = {}
620 1e82bc80 Michael Hanselmann
621 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
622 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
623 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
624 1e82bc80 Michael Hanselmann
625 8d232068 Michael Hanselmann
    return ({}, {
626 8d232068 Michael Hanselmann
      "node_name": self.items[0],
627 8d232068 Michael Hanselmann
      "storage_type": storage_type,
628 8d232068 Michael Hanselmann
      "name": name,
629 8d232068 Michael Hanselmann
      "changes": changes,
630 8d232068 Michael Hanselmann
      })
631 1e82bc80 Michael Hanselmann
632 1e82bc80 Michael Hanselmann
633 98270691 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.OpcodeResource):
634 b58a4d16 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair resource.
635 723f4565 Michael Hanselmann

636 723f4565 Michael Hanselmann
  """
637 98270691 Michael Hanselmann
  PUT_OPCODE = opcodes.OpRepairNodeStorage
638 723f4565 Michael Hanselmann
639 98270691 Michael Hanselmann
  def GetPutOpInput(self):
640 98270691 Michael Hanselmann
    """Repairs a storage volume on a node.
641 723f4565 Michael Hanselmann

642 98270691 Michael Hanselmann
    """
643 98270691 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
644 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
645 723f4565 Michael Hanselmann
    if not name:
646 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
647 723f4565 Michael Hanselmann
                                " parameter")
648 723f4565 Michael Hanselmann
649 98270691 Michael Hanselmann
    return ({}, {
650 98270691 Michael Hanselmann
      "node_name": self.items[0],
651 98270691 Michael Hanselmann
      "storage_type": storage_type,
652 98270691 Michael Hanselmann
      "name": name,
653 98270691 Michael Hanselmann
      })
654 723f4565 Michael Hanselmann
655 723f4565 Michael Hanselmann
656 4588b4bd Dimitris Aragiorgis
class R_2_networks(baserlib.OpcodeResource):
657 4588b4bd Dimitris Aragiorgis
  """/2/networks resource.
658 4588b4bd Dimitris Aragiorgis

659 4588b4bd Dimitris Aragiorgis
  """
660 4588b4bd Dimitris Aragiorgis
  GET_OPCODE = opcodes.OpNetworkQuery
661 4588b4bd Dimitris Aragiorgis
  POST_OPCODE = opcodes.OpNetworkAdd
662 4588b4bd Dimitris Aragiorgis
  POST_RENAME = {
663 4588b4bd Dimitris Aragiorgis
    "name": "network_name",
664 4588b4bd Dimitris Aragiorgis
    }
665 4588b4bd Dimitris Aragiorgis
666 4588b4bd Dimitris Aragiorgis
  def GetPostOpInput(self):
667 4588b4bd Dimitris Aragiorgis
    """Create a network.
668 4588b4bd Dimitris Aragiorgis

669 4588b4bd Dimitris Aragiorgis
    """
670 4588b4bd Dimitris Aragiorgis
    assert not self.items
671 4588b4bd Dimitris Aragiorgis
    return (self.request_body, {
672 4588b4bd Dimitris Aragiorgis
      "dry_run": self.dryRun(),
673 4588b4bd Dimitris Aragiorgis
      })
674 4588b4bd Dimitris Aragiorgis
675 4588b4bd Dimitris Aragiorgis
  def GET(self):
676 4588b4bd Dimitris Aragiorgis
    """Returns a list of all networks.
677 4588b4bd Dimitris Aragiorgis

678 4588b4bd Dimitris Aragiorgis
    """
679 ab9e48d1 Iustin Pop
    client = self.GetClient(query=True)
680 4588b4bd Dimitris Aragiorgis
681 4588b4bd Dimitris Aragiorgis
    if self.useBulk():
682 4588b4bd Dimitris Aragiorgis
      bulkdata = client.QueryNetworks([], NET_FIELDS, False)
683 4588b4bd Dimitris Aragiorgis
      return baserlib.MapBulkFields(bulkdata, NET_FIELDS)
684 4588b4bd Dimitris Aragiorgis
    else:
685 4588b4bd Dimitris Aragiorgis
      data = client.QueryNetworks([], ["name"], False)
686 4588b4bd Dimitris Aragiorgis
      networknames = [row[0] for row in data]
687 4588b4bd Dimitris Aragiorgis
      return baserlib.BuildUriList(networknames, "/2/networks/%s",
688 4588b4bd Dimitris Aragiorgis
                                   uri_fields=("name", "uri"))
689 4588b4bd Dimitris Aragiorgis
690 4588b4bd Dimitris Aragiorgis
691 4588b4bd Dimitris Aragiorgis
class R_2_networks_name(baserlib.OpcodeResource):
692 6e8091f9 Dimitris Aragiorgis
  """/2/networks/[network_name] resource.
693 4588b4bd Dimitris Aragiorgis

694 4588b4bd Dimitris Aragiorgis
  """
695 4588b4bd Dimitris Aragiorgis
  DELETE_OPCODE = opcodes.OpNetworkRemove
696 4588b4bd Dimitris Aragiorgis
697 4588b4bd Dimitris Aragiorgis
  def GET(self):
698 4588b4bd Dimitris Aragiorgis
    """Send information about a network.
699 4588b4bd Dimitris Aragiorgis

700 4588b4bd Dimitris Aragiorgis
    """
701 4588b4bd Dimitris Aragiorgis
    network_name = self.items[0]
702 ab9e48d1 Iustin Pop
    client = self.GetClient(query=True)
703 4588b4bd Dimitris Aragiorgis
704 4588b4bd Dimitris Aragiorgis
    result = baserlib.HandleItemQueryErrors(client.QueryNetworks,
705 4588b4bd Dimitris Aragiorgis
                                            names=[network_name],
706 4588b4bd Dimitris Aragiorgis
                                            fields=NET_FIELDS,
707 4588b4bd Dimitris Aragiorgis
                                            use_locking=self.useLocking())
708 4588b4bd Dimitris Aragiorgis
709 4588b4bd Dimitris Aragiorgis
    return baserlib.MapFields(NET_FIELDS, result[0])
710 4588b4bd Dimitris Aragiorgis
711 4588b4bd Dimitris Aragiorgis
  def GetDeleteOpInput(self):
712 4588b4bd Dimitris Aragiorgis
    """Delete a network.
713 4588b4bd Dimitris Aragiorgis

714 4588b4bd Dimitris Aragiorgis
    """
715 4588b4bd Dimitris Aragiorgis
    assert len(self.items) == 1
716 4588b4bd Dimitris Aragiorgis
    return (self.request_body, {
717 4588b4bd Dimitris Aragiorgis
      "network_name": self.items[0],
718 4588b4bd Dimitris Aragiorgis
      "dry_run": self.dryRun(),
719 4588b4bd Dimitris Aragiorgis
      })
720 4588b4bd Dimitris Aragiorgis
721 3c286190 Dimitris Aragiorgis
722 4588b4bd Dimitris Aragiorgis
class R_2_networks_name_connect(baserlib.OpcodeResource):
723 6e8091f9 Dimitris Aragiorgis
  """/2/networks/[network_name]/connect resource.
724 4588b4bd Dimitris Aragiorgis

725 4588b4bd Dimitris Aragiorgis
  """
726 4588b4bd Dimitris Aragiorgis
  PUT_OPCODE = opcodes.OpNetworkConnect
727 4588b4bd Dimitris Aragiorgis
728 4588b4bd Dimitris Aragiorgis
  def GetPutOpInput(self):
729 4588b4bd Dimitris Aragiorgis
    """Changes some parameters of node group.
730 4588b4bd Dimitris Aragiorgis

731 4588b4bd Dimitris Aragiorgis
    """
732 4588b4bd Dimitris Aragiorgis
    assert self.items
733 4588b4bd Dimitris Aragiorgis
    return (self.request_body, {
734 4588b4bd Dimitris Aragiorgis
      "network_name": self.items[0],
735 6e8091f9 Dimitris Aragiorgis
      "dry_run": self.dryRun(),
736 4588b4bd Dimitris Aragiorgis
      })
737 4588b4bd Dimitris Aragiorgis
738 3c286190 Dimitris Aragiorgis
739 4588b4bd Dimitris Aragiorgis
class R_2_networks_name_disconnect(baserlib.OpcodeResource):
740 6e8091f9 Dimitris Aragiorgis
  """/2/networks/[network_name]/disconnect resource.
741 4588b4bd Dimitris Aragiorgis

742 4588b4bd Dimitris Aragiorgis
  """
743 4588b4bd Dimitris Aragiorgis
  PUT_OPCODE = opcodes.OpNetworkDisconnect
744 4588b4bd Dimitris Aragiorgis
745 4588b4bd Dimitris Aragiorgis
  def GetPutOpInput(self):
746 4588b4bd Dimitris Aragiorgis
    """Changes some parameters of node group.
747 4588b4bd Dimitris Aragiorgis

748 4588b4bd Dimitris Aragiorgis
    """
749 4588b4bd Dimitris Aragiorgis
    assert self.items
750 4588b4bd Dimitris Aragiorgis
    return (self.request_body, {
751 4588b4bd Dimitris Aragiorgis
      "network_name": self.items[0],
752 6e8091f9 Dimitris Aragiorgis
      "dry_run": self.dryRun(),
753 6e8091f9 Dimitris Aragiorgis
      })
754 6e8091f9 Dimitris Aragiorgis
755 3c286190 Dimitris Aragiorgis
756 6e8091f9 Dimitris Aragiorgis
class R_2_networks_name_modify(baserlib.OpcodeResource):
757 6e8091f9 Dimitris Aragiorgis
  """/2/networks/[network_name]/modify resource.
758 6e8091f9 Dimitris Aragiorgis

759 6e8091f9 Dimitris Aragiorgis
  """
760 6e8091f9 Dimitris Aragiorgis
  PUT_OPCODE = opcodes.OpNetworkSetParams
761 6e8091f9 Dimitris Aragiorgis
762 6e8091f9 Dimitris Aragiorgis
  def GetPutOpInput(self):
763 6e8091f9 Dimitris Aragiorgis
    """Changes some parameters of network.
764 6e8091f9 Dimitris Aragiorgis

765 6e8091f9 Dimitris Aragiorgis
    """
766 6e8091f9 Dimitris Aragiorgis
    assert self.items
767 6e8091f9 Dimitris Aragiorgis
    return (self.request_body, {
768 6e8091f9 Dimitris Aragiorgis
      "network_name": self.items[0],
769 4588b4bd Dimitris Aragiorgis
      })
770 4588b4bd Dimitris Aragiorgis
771 6e8091f9 Dimitris Aragiorgis
772 c91407bc Michael Hanselmann
class R_2_groups(baserlib.OpcodeResource):
773 c91407bc Michael Hanselmann
  """/2/groups resource.
774 90e99856 Adeodato Simo

775 90e99856 Adeodato Simo
  """
776 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpGroupQuery
777 c91407bc Michael Hanselmann
  POST_OPCODE = opcodes.OpGroupAdd
778 c91407bc Michael Hanselmann
  POST_RENAME = {
779 527fbde8 Michael Hanselmann
    "name": "group_name",
780 527fbde8 Michael Hanselmann
    }
781 527fbde8 Michael Hanselmann
782 c91407bc Michael Hanselmann
  def GetPostOpInput(self):
783 c91407bc Michael Hanselmann
    """Create a node group.
784 90e99856 Adeodato Simo

785 4588b4bd Dimitris Aragiorgis

786 c91407bc Michael Hanselmann
    """
787 c91407bc Michael Hanselmann
    assert not self.items
788 c91407bc Michael Hanselmann
    return (self.request_body, {
789 c91407bc Michael Hanselmann
      "dry_run": self.dryRun(),
790 c91407bc Michael Hanselmann
      })
791 0897dc97 Adeodato Simo
792 0897dc97 Adeodato Simo
  def GET(self):
793 0897dc97 Adeodato Simo
    """Returns a list of all node groups.
794 0897dc97 Adeodato Simo

795 0897dc97 Adeodato Simo
    """
796 9fbf0098 Iustin Pop
    client = self.GetClient(query=True)
797 0897dc97 Adeodato Simo
798 0897dc97 Adeodato Simo
    if self.useBulk():
799 0897dc97 Adeodato Simo
      bulkdata = client.QueryGroups([], G_FIELDS, False)
800 0897dc97 Adeodato Simo
      return baserlib.MapBulkFields(bulkdata, G_FIELDS)
801 0897dc97 Adeodato Simo
    else:
802 0897dc97 Adeodato Simo
      data = client.QueryGroups([], ["name"], False)
803 0897dc97 Adeodato Simo
      groupnames = [row[0] for row in data]
804 0897dc97 Adeodato Simo
      return baserlib.BuildUriList(groupnames, "/2/groups/%s",
805 0897dc97 Adeodato Simo
                                   uri_fields=("name", "uri"))
806 0897dc97 Adeodato Simo
807 0897dc97 Adeodato Simo
808 86f1f5d4 Michael Hanselmann
class R_2_groups_name(baserlib.OpcodeResource):
809 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name] resource.
810 0897dc97 Adeodato Simo

811 0897dc97 Adeodato Simo
  """
812 86f1f5d4 Michael Hanselmann
  DELETE_OPCODE = opcodes.OpGroupRemove
813 86f1f5d4 Michael Hanselmann
814 0897dc97 Adeodato Simo
  def GET(self):
815 0897dc97 Adeodato Simo
    """Send information about a node group.
816 0897dc97 Adeodato Simo

817 0897dc97 Adeodato Simo
    """
818 0897dc97 Adeodato Simo
    group_name = self.items[0]
819 9fbf0098 Iustin Pop
    client = self.GetClient(query=True)
820 0897dc97 Adeodato Simo
821 0897dc97 Adeodato Simo
    result = baserlib.HandleItemQueryErrors(client.QueryGroups,
822 0897dc97 Adeodato Simo
                                            names=[group_name], fields=G_FIELDS,
823 0897dc97 Adeodato Simo
                                            use_locking=self.useLocking())
824 0897dc97 Adeodato Simo
825 0897dc97 Adeodato Simo
    return baserlib.MapFields(G_FIELDS, result[0])
826 0897dc97 Adeodato Simo
827 86f1f5d4 Michael Hanselmann
  def GetDeleteOpInput(self):
828 0dbaa9ca Adeodato Simo
    """Delete a node group.
829 0dbaa9ca Adeodato Simo

830 0dbaa9ca Adeodato Simo
    """
831 86f1f5d4 Michael Hanselmann
    assert len(self.items) == 1
832 86f1f5d4 Michael Hanselmann
    return ({}, {
833 86f1f5d4 Michael Hanselmann
      "group_name": self.items[0],
834 86f1f5d4 Michael Hanselmann
      "dry_run": self.dryRun(),
835 86f1f5d4 Michael Hanselmann
      })
836 0dbaa9ca Adeodato Simo
837 0dbaa9ca Adeodato Simo
838 d5211458 Michael Hanselmann
class R_2_groups_name_modify(baserlib.OpcodeResource):
839 f18fab7d Adeodato Simo
  """/2/groups/[group_name]/modify resource.
840 f18fab7d Adeodato Simo

841 f18fab7d Adeodato Simo
  """
842 d5211458 Michael Hanselmann
  PUT_OPCODE = opcodes.OpGroupSetParams
843 f18fab7d Adeodato Simo
844 d5211458 Michael Hanselmann
  def GetPutOpInput(self):
845 d5211458 Michael Hanselmann
    """Changes some parameters of node group.
846 f18fab7d Adeodato Simo

847 f18fab7d Adeodato Simo
    """
848 d5211458 Michael Hanselmann
    assert self.items
849 d5211458 Michael Hanselmann
    return (self.request_body, {
850 d5211458 Michael Hanselmann
      "group_name": self.items[0],
851 d5211458 Michael Hanselmann
      })
852 f18fab7d Adeodato Simo
853 f18fab7d Adeodato Simo
854 cd0d4d5a Michael Hanselmann
class R_2_groups_name_rename(baserlib.OpcodeResource):
855 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name]/rename resource.
856 0dbaa9ca Adeodato Simo

857 0dbaa9ca Adeodato Simo
  """
858 cd0d4d5a Michael Hanselmann
  PUT_OPCODE = opcodes.OpGroupRename
859 0dbaa9ca Adeodato Simo
860 cd0d4d5a Michael Hanselmann
  def GetPutOpInput(self):
861 cd0d4d5a Michael Hanselmann
    """Changes the name of a node group.
862 0dbaa9ca Adeodato Simo

863 0dbaa9ca Adeodato Simo
    """
864 cd0d4d5a Michael Hanselmann
    assert len(self.items) == 1
865 cd0d4d5a Michael Hanselmann
    return (self.request_body, {
866 cd0d4d5a Michael Hanselmann
      "group_name": self.items[0],
867 cd0d4d5a Michael Hanselmann
      "dry_run": self.dryRun(),
868 cd0d4d5a Michael Hanselmann
      })
869 0897dc97 Adeodato Simo
870 0897dc97 Adeodato Simo
871 87fd3ec7 Michael Hanselmann
class R_2_groups_name_assign_nodes(baserlib.OpcodeResource):
872 b58a4d16 Michael Hanselmann
  """/2/groups/[group_name]/assign-nodes resource.
873 4245446f Adeodato Simo

874 4245446f Adeodato Simo
  """
875 87fd3ec7 Michael Hanselmann
  PUT_OPCODE = opcodes.OpGroupAssignNodes
876 4245446f Adeodato Simo
877 87fd3ec7 Michael Hanselmann
  def GetPutOpInput(self):
878 87fd3ec7 Michael Hanselmann
    """Assigns nodes to a group.
879 4245446f Adeodato Simo

880 4245446f Adeodato Simo
    """
881 87fd3ec7 Michael Hanselmann
    assert len(self.items) == 1
882 87fd3ec7 Michael Hanselmann
    return (self.request_body, {
883 4245446f Adeodato Simo
      "group_name": self.items[0],
884 4245446f Adeodato Simo
      "dry_run": self.dryRun(),
885 4245446f Adeodato Simo
      "force": self.useForce(),
886 4245446f Adeodato Simo
      })
887 4245446f Adeodato Simo
888 4245446f Adeodato Simo
889 09a43b39 Michael Hanselmann
class R_2_instances(baserlib.OpcodeResource):
890 09a43b39 Michael Hanselmann
  """/2/instances resource.
891 6395cebb Michael Hanselmann

892 6395cebb Michael Hanselmann
  """
893 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpInstanceQuery
894 09a43b39 Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceCreate
895 09a43b39 Michael Hanselmann
  POST_RENAME = {
896 526a662a Michael Hanselmann
    "os": "os_type",
897 526a662a Michael Hanselmann
    "name": "instance_name",
898 526a662a Michael Hanselmann
    }
899 526a662a Michael Hanselmann
900 441e7cfd Oleksiy Mishchenko
  def GET(self):
901 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
902 441e7cfd Oleksiy Mishchenko

903 441e7cfd Oleksiy Mishchenko
    """
904 be1ddd09 Michael Hanselmann
    client = self.GetClient()
905 441e7cfd Oleksiy Mishchenko
906 3d103742 Iustin Pop
    use_locking = self.useLocking()
907 3d103742 Iustin Pop
    if self.useBulk():
908 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
909 28a45bfc René Nussbaumer
      return map(_UpdateBeparams, baserlib.MapBulkFields(bulkdata, I_FIELDS))
910 441e7cfd Oleksiy Mishchenko
    else:
911 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
912 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
913 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
914 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
915 441e7cfd Oleksiy Mishchenko
916 09a43b39 Michael Hanselmann
  def GetPostOpInput(self):
917 d975f482 Michael Hanselmann
    """Create an instance.
918 d975f482 Michael Hanselmann

919 d975f482 Michael Hanselmann
    @return: a job id
920 d975f482 Michael Hanselmann

921 d975f482 Michael Hanselmann
    """
922 09a43b39 Michael Hanselmann
    baserlib.CheckType(self.request_body, dict, "Body contents")
923 d975f482 Michael Hanselmann
924 d975f482 Michael Hanselmann
    # Default to request data version 0
925 d975f482 Michael Hanselmann
    data_version = self.getBodyParameter(_REQ_DATA_VERSION, 0)
926 d975f482 Michael Hanselmann
927 d975f482 Michael Hanselmann
    if data_version == 0:
928 3fd7f652 Michael Hanselmann
      raise http.HttpBadRequest("Instance creation request version 0 is no"
929 3fd7f652 Michael Hanselmann
                                " longer supported")
930 09a43b39 Michael Hanselmann
    elif data_version != 1:
931 d975f482 Michael Hanselmann
      raise http.HttpBadRequest("Unsupported request data version %s" %
932 12eff9b9 Michael Hanselmann
                                data_version)
933 d975f482 Michael Hanselmann
934 09a43b39 Michael Hanselmann
    data = self.request_body.copy()
935 09a43b39 Michael Hanselmann
    # Remove "__version__"
936 09a43b39 Michael Hanselmann
    data.pop(_REQ_DATA_VERSION, None)
937 09a43b39 Michael Hanselmann
938 09a43b39 Michael Hanselmann
    return (data, {
939 09a43b39 Michael Hanselmann
      "dry_run": self.dryRun(),
940 09a43b39 Michael Hanselmann
      })
941 2f7635f4 Oleksiy Mishchenko
942 441e7cfd Oleksiy Mishchenko
943 4ee72287 René Nussbaumer
class R_2_instances_multi_alloc(baserlib.OpcodeResource):
944 4ee72287 René Nussbaumer
  """/2/instances-multi-alloc resource.
945 4ee72287 René Nussbaumer

946 4ee72287 René Nussbaumer
  """
947 4ee72287 René Nussbaumer
  POST_OPCODE = opcodes.OpInstanceMultiAlloc
948 4ee72287 René Nussbaumer
949 4ee72287 René Nussbaumer
  def GetPostOpInput(self):
950 4ee72287 René Nussbaumer
    """Try to allocate multiple instances.
951 4ee72287 René Nussbaumer

952 4ee72287 René Nussbaumer
    @return: A dict with submitted jobs, allocatable instances and failed
953 4ee72287 René Nussbaumer
             allocations
954 4ee72287 René Nussbaumer

955 4ee72287 René Nussbaumer
    """
956 e5ff1a47 René Nussbaumer
    if "instances" not in self.request_body:
957 e5ff1a47 René Nussbaumer
      raise http.HttpBadRequest("Request is missing required 'instances' field"
958 e5ff1a47 René Nussbaumer
                                " in body")
959 e5ff1a47 René Nussbaumer
960 e5ff1a47 René Nussbaumer
    op_id = {
961 e5ff1a47 René Nussbaumer
      "OP_ID": self.POST_OPCODE.OP_ID, # pylint: disable=E1101
962 e5ff1a47 René Nussbaumer
      }
963 e5ff1a47 René Nussbaumer
    body = objects.FillDict(self.request_body, {
964 e5ff1a47 René Nussbaumer
      "instances": [objects.FillDict(inst, op_id)
965 e5ff1a47 René Nussbaumer
                    for inst in self.request_body["instances"]],
966 e5ff1a47 René Nussbaumer
      })
967 e5ff1a47 René Nussbaumer
968 e5ff1a47 René Nussbaumer
    return (body, {
969 4ee72287 René Nussbaumer
      "dry_run": self.dryRun(),
970 4ee72287 René Nussbaumer
      })
971 4ee72287 René Nussbaumer
972 4ee72287 René Nussbaumer
973 a6fa7892 Michael Hanselmann
class R_2_instances_name(baserlib.OpcodeResource):
974 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name] resource.
975 028c6b76 Oleksiy Mishchenko

976 028c6b76 Oleksiy Mishchenko
  """
977 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpInstanceQuery
978 a6fa7892 Michael Hanselmann
  DELETE_OPCODE = opcodes.OpInstanceRemove
979 a6fa7892 Michael Hanselmann
980 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
981 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
982 4e5a68f8 Oleksiy Mishchenko

983 4e5a68f8 Oleksiy Mishchenko
    """
984 be1ddd09 Michael Hanselmann
    client = self.GetClient()
985 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
986 e8ebbd2b Michael Hanselmann
987 e8ebbd2b Michael Hanselmann
    result = baserlib.HandleItemQueryErrors(client.QueryInstances,
988 e8ebbd2b Michael Hanselmann
                                            names=[instance_name],
989 e8ebbd2b Michael Hanselmann
                                            fields=I_FIELDS,
990 e8ebbd2b Michael Hanselmann
                                            use_locking=self.useLocking())
991 4e5a68f8 Oleksiy Mishchenko
992 28a45bfc René Nussbaumer
    return _UpdateBeparams(baserlib.MapFields(I_FIELDS, result[0]))
993 028c6b76 Oleksiy Mishchenko
994 a6fa7892 Michael Hanselmann
  def GetDeleteOpInput(self):
995 6e99c5a0 Iustin Pop
    """Delete an instance.
996 6e99c5a0 Iustin Pop

997 6e99c5a0 Iustin Pop
    """
998 a6fa7892 Michael Hanselmann
    assert len(self.items) == 1
999 077892f8 Dimitris Aragiorgis
    return (self.request_body, {
1000 a6fa7892 Michael Hanselmann
      "instance_name": self.items[0],
1001 a6fa7892 Michael Hanselmann
      "ignore_failures": False,
1002 a6fa7892 Michael Hanselmann
      "dry_run": self.dryRun(),
1003 a6fa7892 Michael Hanselmann
      })
1004 6e99c5a0 Iustin Pop
1005 028c6b76 Oleksiy Mishchenko
1006 7b3df961 Michael Hanselmann
class R_2_instances_name_info(baserlib.OpcodeResource):
1007 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
1008 d8260842 Michael Hanselmann

1009 d8260842 Michael Hanselmann
  """
1010 7b3df961 Michael Hanselmann
  GET_OPCODE = opcodes.OpInstanceQueryData
1011 7b3df961 Michael Hanselmann
1012 7b3df961 Michael Hanselmann
  def GetGetOpInput(self):
1013 d8260842 Michael Hanselmann
    """Request detailed instance information.
1014 d8260842 Michael Hanselmann

1015 d8260842 Michael Hanselmann
    """
1016 7b3df961 Michael Hanselmann
    assert len(self.items) == 1
1017 7b3df961 Michael Hanselmann
    return ({}, {
1018 7b3df961 Michael Hanselmann
      "instances": [self.items[0]],
1019 7b3df961 Michael Hanselmann
      "static": bool(self._checkIntVariable("static", default=0)),
1020 7b3df961 Michael Hanselmann
      })
1021 d8260842 Michael Hanselmann
1022 d8260842 Michael Hanselmann
1023 ac4888c1 Michael Hanselmann
class R_2_instances_name_reboot(baserlib.OpcodeResource):
1024 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
1025 2276aa29 Oleksiy Mishchenko

1026 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
1027 2276aa29 Oleksiy Mishchenko

1028 2276aa29 Oleksiy Mishchenko
  """
1029 ac4888c1 Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceReboot
1030 ac4888c1 Michael Hanselmann
1031 ac4888c1 Michael Hanselmann
  def GetPostOpInput(self):
1032 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
1033 2276aa29 Oleksiy Mishchenko

1034 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
1035 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
1036 0c55c24b Oleksiy Mishchenko

1037 2276aa29 Oleksiy Mishchenko
    """
1038 077892f8 Dimitris Aragiorgis
    return (self.request_body, {
1039 ac4888c1 Michael Hanselmann
      "instance_name": self.items[0],
1040 ac4888c1 Michael Hanselmann
      "reboot_type":
1041 ac4888c1 Michael Hanselmann
        self.queryargs.get("type", [constants.INSTANCE_REBOOT_HARD])[0],
1042 ac4888c1 Michael Hanselmann
      "ignore_secondaries": bool(self._checkIntVariable("ignore_secondaries")),
1043 ac4888c1 Michael Hanselmann
      "dry_run": self.dryRun(),
1044 ac4888c1 Michael Hanselmann
      })
1045 2276aa29 Oleksiy Mishchenko
1046 2276aa29 Oleksiy Mishchenko
1047 4717e6eb Michael Hanselmann
class R_2_instances_name_startup(baserlib.OpcodeResource):
1048 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
1049 0c55c24b Oleksiy Mishchenko

1050 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
1051 0c55c24b Oleksiy Mishchenko

1052 0c55c24b Oleksiy Mishchenko
  """
1053 4717e6eb Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceStartup
1054 4717e6eb Michael Hanselmann
1055 4717e6eb Michael Hanselmann
  def GetPutOpInput(self):
1056 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
1057 0c55c24b Oleksiy Mishchenko

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

1061 0c55c24b Oleksiy Mishchenko
    """
1062 4717e6eb Michael Hanselmann
    return ({}, {
1063 4717e6eb Michael Hanselmann
      "instance_name": self.items[0],
1064 4717e6eb Michael Hanselmann
      "force": self.useForce(),
1065 4717e6eb Michael Hanselmann
      "dry_run": self.dryRun(),
1066 4717e6eb Michael Hanselmann
      "no_remember": bool(self._checkIntVariable("no_remember")),
1067 4717e6eb Michael Hanselmann
      })
1068 0c55c24b Oleksiy Mishchenko
1069 0c55c24b Oleksiy Mishchenko
1070 3175ade6 Michael Hanselmann
class R_2_instances_name_shutdown(baserlib.OpcodeResource):
1071 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
1072 0c55c24b Oleksiy Mishchenko

1073 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
1074 0c55c24b Oleksiy Mishchenko

1075 0c55c24b Oleksiy Mishchenko
  """
1076 3175ade6 Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceShutdown
1077 0c55c24b Oleksiy Mishchenko
1078 3175ade6 Michael Hanselmann
  def GetPutOpInput(self):
1079 3175ade6 Michael Hanselmann
    """Shutdown an instance.
1080 7fa310f6 René Nussbaumer

1081 0c55c24b Oleksiy Mishchenko
    """
1082 3175ade6 Michael Hanselmann
    return (self.request_body, {
1083 3175ade6 Michael Hanselmann
      "instance_name": self.items[0],
1084 3175ade6 Michael Hanselmann
      "no_remember": bool(self._checkIntVariable("no_remember")),
1085 3175ade6 Michael Hanselmann
      "dry_run": self.dryRun(),
1086 3175ade6 Michael Hanselmann
      })
1087 0c55c24b Oleksiy Mishchenko
1088 0c55c24b Oleksiy Mishchenko
1089 c744425f Michael Hanselmann
def _ParseInstanceReinstallRequest(name, data):
1090 c744425f Michael Hanselmann
  """Parses a request for reinstalling an instance.
1091 c744425f Michael Hanselmann

1092 c744425f Michael Hanselmann
  """
1093 c744425f Michael Hanselmann
  if not isinstance(data, dict):
1094 c744425f Michael Hanselmann
    raise http.HttpBadRequest("Invalid body contents, not a dictionary")
1095 c744425f Michael Hanselmann
1096 bd0807fe Guido Trotter
  ostype = baserlib.CheckParameter(data, "os", default=None)
1097 c744425f Michael Hanselmann
  start = baserlib.CheckParameter(data, "start", exptype=bool,
1098 c744425f Michael Hanselmann
                                  default=True)
1099 c744425f Michael Hanselmann
  osparams = baserlib.CheckParameter(data, "osparams", default=None)
1100 c744425f Michael Hanselmann
1101 c744425f Michael Hanselmann
  ops = [
1102 ee3e37a7 Iustin Pop
    opcodes.OpInstanceShutdown(instance_name=name),
1103 5073fd8f Iustin Pop
    opcodes.OpInstanceReinstall(instance_name=name, os_type=ostype,
1104 c744425f Michael Hanselmann
                                osparams=osparams),
1105 c744425f Michael Hanselmann
    ]
1106 c744425f Michael Hanselmann
1107 c744425f Michael Hanselmann
  if start:
1108 c873d91c Iustin Pop
    ops.append(opcodes.OpInstanceStartup(instance_name=name, force=False))
1109 c744425f Michael Hanselmann
1110 c744425f Michael Hanselmann
  return ops
1111 c744425f Michael Hanselmann
1112 c744425f Michael Hanselmann
1113 f6ce0ba2 Michael Hanselmann
class R_2_instances_name_reinstall(baserlib.OpcodeResource):
1114 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
1115 e5b7c4ca Iustin Pop

1116 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
1117 e5b7c4ca Iustin Pop

1118 e5b7c4ca Iustin Pop
  """
1119 f6ce0ba2 Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceReinstall
1120 f6ce0ba2 Michael Hanselmann
1121 e5b7c4ca Iustin Pop
  def POST(self):
1122 e5b7c4ca Iustin Pop
    """Reinstall an instance.
1123 e5b7c4ca Iustin Pop

1124 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
1125 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
1126 e5b7c4ca Iustin Pop
    automatically.
1127 e5b7c4ca Iustin Pop

1128 e5b7c4ca Iustin Pop
    """
1129 c744425f Michael Hanselmann
    if self.request_body:
1130 c744425f Michael Hanselmann
      if self.queryargs:
1131 c744425f Michael Hanselmann
        raise http.HttpBadRequest("Can't combine query and body parameters")
1132 c744425f Michael Hanselmann
1133 c744425f Michael Hanselmann
      body = self.request_body
1134 bd0807fe Guido Trotter
    elif self.queryargs:
1135 c744425f Michael Hanselmann
      # Legacy interface, do not modify/extend
1136 c744425f Michael Hanselmann
      body = {
1137 c744425f Michael Hanselmann
        "os": self._checkStringVariable("os"),
1138 c744425f Michael Hanselmann
        "start": not self._checkIntVariable("nostartup"),
1139 c744425f Michael Hanselmann
        }
1140 bd0807fe Guido Trotter
    else:
1141 bd0807fe Guido Trotter
      body = {}
1142 c744425f Michael Hanselmann
1143 c744425f Michael Hanselmann
    ops = _ParseInstanceReinstallRequest(self.items[0], body)
1144 c744425f Michael Hanselmann
1145 be1ddd09 Michael Hanselmann
    return self.SubmitJob(ops)
1146 e5b7c4ca Iustin Pop
1147 e5b7c4ca Iustin Pop
1148 0dbc732c Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.OpcodeResource):
1149 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
1150 4c98b915 Michael Hanselmann

1151 4c98b915 Michael Hanselmann
  """
1152 0dbc732c Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceReplaceDisks
1153 0dbc732c Michael Hanselmann
1154 0dbc732c Michael Hanselmann
  def GetPostOpInput(self):
1155 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
1156 4c98b915 Michael Hanselmann

1157 4c98b915 Michael Hanselmann
    """
1158 0dbc732c Michael Hanselmann
    static = {
1159 0dbc732c Michael Hanselmann
      "instance_name": self.items[0],
1160 0dbc732c Michael Hanselmann
      }
1161 4c98b915 Michael Hanselmann
1162 539d65ba Michael Hanselmann
    if self.request_body:
1163 7dcf333d Michael Hanselmann
      data = self.request_body
1164 539d65ba Michael Hanselmann
    elif self.queryargs:
1165 539d65ba Michael Hanselmann
      # Legacy interface, do not modify/extend
1166 7dcf333d Michael Hanselmann
      data = {
1167 539d65ba Michael Hanselmann
        "remote_node": self._checkStringVariable("remote_node", default=None),
1168 539d65ba Michael Hanselmann
        "mode": self._checkStringVariable("mode", default=None),
1169 539d65ba Michael Hanselmann
        "disks": self._checkStringVariable("disks", default=None),
1170 539d65ba Michael Hanselmann
        "iallocator": self._checkStringVariable("iallocator", default=None),
1171 539d65ba Michael Hanselmann
        }
1172 539d65ba Michael Hanselmann
    else:
1173 7dcf333d Michael Hanselmann
      data = {}
1174 539d65ba Michael Hanselmann
1175 0dbc732c Michael Hanselmann
    # Parse disks
1176 0dbc732c Michael Hanselmann
    try:
1177 7dcf333d Michael Hanselmann
      raw_disks = data.pop("disks")
1178 0dbc732c Michael Hanselmann
    except KeyError:
1179 0dbc732c Michael Hanselmann
      pass
1180 0dbc732c Michael Hanselmann
    else:
1181 7dcf333d Michael Hanselmann
      if raw_disks:
1182 7dcf333d Michael Hanselmann
        if ht.TListOf(ht.TInt)(raw_disks): # pylint: disable=E1102
1183 7dcf333d Michael Hanselmann
          data["disks"] = raw_disks
1184 7dcf333d Michael Hanselmann
        else:
1185 7dcf333d Michael Hanselmann
          # Backwards compatibility for strings of the format "1, 2, 3"
1186 7dcf333d Michael Hanselmann
          try:
1187 7dcf333d Michael Hanselmann
            data["disks"] = [int(part) for part in raw_disks.split(",")]
1188 7dcf333d Michael Hanselmann
          except (TypeError, ValueError), err:
1189 7dcf333d Michael Hanselmann
            raise http.HttpBadRequest("Invalid disk index passed: %s" % err)
1190 0dbc732c Michael Hanselmann
1191 0dbc732c Michael Hanselmann
    return (data, static)
1192 4c98b915 Michael Hanselmann
1193 4c98b915 Michael Hanselmann
1194 1824a7a1 Michael Hanselmann
class R_2_instances_name_activate_disks(baserlib.OpcodeResource):
1195 2197b66f René Nussbaumer
  """/2/instances/[instance_name]/activate-disks resource.
1196 2197b66f René Nussbaumer

1197 2197b66f René Nussbaumer
  """
1198 1824a7a1 Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceActivateDisks
1199 1824a7a1 Michael Hanselmann
1200 1824a7a1 Michael Hanselmann
  def GetPutOpInput(self):
1201 2197b66f René Nussbaumer
    """Activate disks for an instance.
1202 2197b66f René Nussbaumer

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

1205 2197b66f René Nussbaumer
    """
1206 1824a7a1 Michael Hanselmann
    return ({}, {
1207 1824a7a1 Michael Hanselmann
      "instance_name": self.items[0],
1208 1824a7a1 Michael Hanselmann
      "ignore_size": bool(self._checkIntVariable("ignore_size")),
1209 1824a7a1 Michael Hanselmann
      })
1210 2197b66f René Nussbaumer
1211 2197b66f René Nussbaumer
1212 973ec124 Michael Hanselmann
class R_2_instances_name_deactivate_disks(baserlib.OpcodeResource):
1213 0a37de5f René Nussbaumer
  """/2/instances/[instance_name]/deactivate-disks resource.
1214 0a37de5f René Nussbaumer

1215 0a37de5f René Nussbaumer
  """
1216 973ec124 Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceDeactivateDisks
1217 973ec124 Michael Hanselmann
1218 973ec124 Michael Hanselmann
  def GetPutOpInput(self):
1219 0a37de5f René Nussbaumer
    """Deactivate disks for an instance.
1220 0a37de5f René Nussbaumer

1221 0a37de5f René Nussbaumer
    """
1222 973ec124 Michael Hanselmann
    return ({}, {
1223 973ec124 Michael Hanselmann
      "instance_name": self.items[0],
1224 973ec124 Michael Hanselmann
      })
1225 0a37de5f René Nussbaumer
1226 0a37de5f René Nussbaumer
1227 a52978c7 Michael Hanselmann
class R_2_instances_name_recreate_disks(baserlib.OpcodeResource):
1228 a52978c7 Michael Hanselmann
  """/2/instances/[instance_name]/recreate-disks resource.
1229 a52978c7 Michael Hanselmann

1230 a52978c7 Michael Hanselmann
  """
1231 a52978c7 Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceRecreateDisks
1232 a52978c7 Michael Hanselmann
1233 a52978c7 Michael Hanselmann
  def GetPostOpInput(self):
1234 a52978c7 Michael Hanselmann
    """Recreate disks for an instance.
1235 a52978c7 Michael Hanselmann

1236 a52978c7 Michael Hanselmann
    """
1237 a52978c7 Michael Hanselmann
    return ({}, {
1238 a52978c7 Michael Hanselmann
      "instance_name": self.items[0],
1239 a52978c7 Michael Hanselmann
      })
1240 a52978c7 Michael Hanselmann
1241 a52978c7 Michael Hanselmann
1242 1c63311d Michael Hanselmann
class R_2_instances_name_prepare_export(baserlib.OpcodeResource):
1243 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/prepare-export resource.
1244 ebeb600f Michael Hanselmann

1245 ebeb600f Michael Hanselmann
  """
1246 1c63311d Michael Hanselmann
  PUT_OPCODE = opcodes.OpBackupPrepare
1247 ebeb600f Michael Hanselmann
1248 1c63311d Michael Hanselmann
  def GetPutOpInput(self):
1249 1c63311d Michael Hanselmann
    """Prepares an export for an instance.
1250 ebeb600f Michael Hanselmann

1251 ebeb600f Michael Hanselmann
    """
1252 1c63311d Michael Hanselmann
    return ({}, {
1253 1c63311d Michael Hanselmann
      "instance_name": self.items[0],
1254 1c63311d Michael Hanselmann
      "mode": self._checkStringVariable("mode"),
1255 1c63311d Michael Hanselmann
      })
1256 ebeb600f Michael Hanselmann
1257 ebeb600f Michael Hanselmann
1258 134afbe7 Michael Hanselmann
class R_2_instances_name_export(baserlib.OpcodeResource):
1259 ebeb600f Michael Hanselmann
  """/2/instances/[instance_name]/export resource.
1260 ebeb600f Michael Hanselmann

1261 ebeb600f Michael Hanselmann
  """
1262 134afbe7 Michael Hanselmann
  PUT_OPCODE = opcodes.OpBackupExport
1263 134afbe7 Michael Hanselmann
  PUT_RENAME = {
1264 134afbe7 Michael Hanselmann
    "destination": "target_node",
1265 134afbe7 Michael Hanselmann
    }
1266 ebeb600f Michael Hanselmann
1267 134afbe7 Michael Hanselmann
  def GetPutOpInput(self):
1268 134afbe7 Michael Hanselmann
    """Exports an instance.
1269 ebeb600f Michael Hanselmann

1270 ebeb600f Michael Hanselmann
    """
1271 134afbe7 Michael Hanselmann
    return (self.request_body, {
1272 134afbe7 Michael Hanselmann
      "instance_name": self.items[0],
1273 134afbe7 Michael Hanselmann
      })
1274 ebeb600f Michael Hanselmann
1275 ebeb600f Michael Hanselmann
1276 075a29be Michael Hanselmann
class R_2_instances_name_migrate(baserlib.OpcodeResource):
1277 5823e0d2 Michael Hanselmann
  """/2/instances/[instance_name]/migrate resource.
1278 5823e0d2 Michael Hanselmann

1279 5823e0d2 Michael Hanselmann
  """
1280 075a29be Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceMigrate
1281 5823e0d2 Michael Hanselmann
1282 075a29be Michael Hanselmann
  def GetPutOpInput(self):
1283 075a29be Michael Hanselmann
    """Migrates an instance.
1284 5823e0d2 Michael Hanselmann

1285 5823e0d2 Michael Hanselmann
    """
1286 075a29be Michael Hanselmann
    return (self.request_body, {
1287 075a29be Michael Hanselmann
      "instance_name": self.items[0],
1288 075a29be Michael Hanselmann
      })
1289 5823e0d2 Michael Hanselmann
1290 5823e0d2 Michael Hanselmann
1291 b5f2ab80 Michael Hanselmann
class R_2_instances_name_failover(baserlib.OpcodeResource):
1292 c0a146a1 Michael Hanselmann
  """/2/instances/[instance_name]/failover resource.
1293 c0a146a1 Michael Hanselmann

1294 c0a146a1 Michael Hanselmann
  """
1295 b5f2ab80 Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceFailover
1296 c0a146a1 Michael Hanselmann
1297 b5f2ab80 Michael Hanselmann
  def GetPutOpInput(self):
1298 b5f2ab80 Michael Hanselmann
    """Does a failover of an instance.
1299 c0a146a1 Michael Hanselmann

1300 c0a146a1 Michael Hanselmann
    """
1301 b5f2ab80 Michael Hanselmann
    return (self.request_body, {
1302 c0a146a1 Michael Hanselmann
      "instance_name": self.items[0],
1303 c0a146a1 Michael Hanselmann
      })
1304 c0a146a1 Michael Hanselmann
1305 c0a146a1 Michael Hanselmann
1306 d76f9b5d Michael Hanselmann
class R_2_instances_name_rename(baserlib.OpcodeResource):
1307 d56e7dc7 Michael Hanselmann
  """/2/instances/[instance_name]/rename resource.
1308 d56e7dc7 Michael Hanselmann

1309 d56e7dc7 Michael Hanselmann
  """
1310 d76f9b5d Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceRename
1311 d56e7dc7 Michael Hanselmann
1312 d76f9b5d Michael Hanselmann
  def GetPutOpInput(self):
1313 d76f9b5d Michael Hanselmann
    """Changes the name of an instance.
1314 d56e7dc7 Michael Hanselmann

1315 d56e7dc7 Michael Hanselmann
    """
1316 d76f9b5d Michael Hanselmann
    return (self.request_body, {
1317 d76f9b5d Michael Hanselmann
      "instance_name": self.items[0],
1318 d76f9b5d Michael Hanselmann
      })
1319 d56e7dc7 Michael Hanselmann
1320 d56e7dc7 Michael Hanselmann
1321 f3db88ba Michael Hanselmann
class R_2_instances_name_modify(baserlib.OpcodeResource):
1322 3882937a Michael Hanselmann
  """/2/instances/[instance_name]/modify resource.
1323 3882937a Michael Hanselmann

1324 3882937a Michael Hanselmann
  """
1325 f3db88ba Michael Hanselmann
  PUT_OPCODE = opcodes.OpInstanceSetParams
1326 3882937a Michael Hanselmann
1327 f3db88ba Michael Hanselmann
  def GetPutOpInput(self):
1328 f3db88ba Michael Hanselmann
    """Changes parameters of an instance.
1329 3882937a Michael Hanselmann

1330 3882937a Michael Hanselmann
    """
1331 f3db88ba Michael Hanselmann
    return (self.request_body, {
1332 f3db88ba Michael Hanselmann
      "instance_name": self.items[0],
1333 f3db88ba Michael Hanselmann
      })
1334 3882937a Michael Hanselmann
1335 3882937a Michael Hanselmann
1336 335965b9 Michael Hanselmann
class R_2_instances_name_disk_grow(baserlib.OpcodeResource):
1337 b58a4d16 Michael Hanselmann
  """/2/instances/[instance_name]/disk/[disk_index]/grow resource.
1338 e23881ed Michael Hanselmann

1339 e23881ed Michael Hanselmann
  """
1340 335965b9 Michael Hanselmann
  POST_OPCODE = opcodes.OpInstanceGrowDisk
1341 e23881ed Michael Hanselmann
1342 335965b9 Michael Hanselmann
  def GetPostOpInput(self):
1343 335965b9 Michael Hanselmann
    """Increases the size of an instance disk.
1344 e23881ed Michael Hanselmann

1345 e23881ed Michael Hanselmann
    """
1346 335965b9 Michael Hanselmann
    return (self.request_body, {
1347 e23881ed Michael Hanselmann
      "instance_name": self.items[0],
1348 e23881ed Michael Hanselmann
      "disk": int(self.items[1]),
1349 e23881ed Michael Hanselmann
      })
1350 e23881ed Michael Hanselmann
1351 e23881ed Michael Hanselmann
1352 26ff6ee2 Michael Hanselmann
class R_2_instances_name_console(baserlib.ResourceBase):
1353 b82d4c5e Michael Hanselmann
  """/2/instances/[instance_name]/console resource.
1354 b82d4c5e Michael Hanselmann

1355 b82d4c5e Michael Hanselmann
  """
1356 5e12acfe Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE, rapi.RAPI_ACCESS_READ]
1357 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpInstanceConsole
1358 b82d4c5e Michael Hanselmann
1359 b82d4c5e Michael Hanselmann
  def GET(self):
1360 b82d4c5e Michael Hanselmann
    """Request information for connecting to instance's console.
1361 b82d4c5e Michael Hanselmann

1362 b82d4c5e Michael Hanselmann
    @return: Serialized instance console description, see
1363 b82d4c5e Michael Hanselmann
             L{objects.InstanceConsole}
1364 b82d4c5e Michael Hanselmann

1365 b82d4c5e Michael Hanselmann
    """
1366 be1ddd09 Michael Hanselmann
    client = self.GetClient()
1367 b82d4c5e Michael Hanselmann
1368 b82d4c5e Michael Hanselmann
    ((console, ), ) = client.QueryInstances([self.items[0]], ["console"], False)
1369 b82d4c5e Michael Hanselmann
1370 b82d4c5e Michael Hanselmann
    if console is None:
1371 b82d4c5e Michael Hanselmann
      raise http.HttpServiceUnavailable("Instance console unavailable")
1372 b82d4c5e Michael Hanselmann
1373 b82d4c5e Michael Hanselmann
    assert isinstance(console, dict)
1374 b82d4c5e Michael Hanselmann
    return console
1375 b82d4c5e Michael Hanselmann
1376 b82d4c5e Michael Hanselmann
1377 208a6cff Michael Hanselmann
def _GetQueryFields(args):
1378 2a38e913 Michael Hanselmann
  """Tries to extract C{fields} query parameter.
1379 2a38e913 Michael Hanselmann

1380 2a38e913 Michael Hanselmann
  @type args: dictionary
1381 2a38e913 Michael Hanselmann
  @rtype: list of string
1382 2a38e913 Michael Hanselmann
  @raise http.HttpBadRequest: When parameter can't be found
1383 208a6cff Michael Hanselmann

1384 208a6cff Michael Hanselmann
  """
1385 208a6cff Michael Hanselmann
  try:
1386 208a6cff Michael Hanselmann
    fields = args["fields"]
1387 208a6cff Michael Hanselmann
  except KeyError:
1388 208a6cff Michael Hanselmann
    raise http.HttpBadRequest("Missing 'fields' query argument")
1389 208a6cff Michael Hanselmann
1390 208a6cff Michael Hanselmann
  return _SplitQueryFields(fields[0])
1391 208a6cff Michael Hanselmann
1392 208a6cff Michael Hanselmann
1393 208a6cff Michael Hanselmann
def _SplitQueryFields(fields):
1394 2a38e913 Michael Hanselmann
  """Splits fields as given for a query request.
1395 2a38e913 Michael Hanselmann

1396 2a38e913 Michael Hanselmann
  @type fields: string
1397 2a38e913 Michael Hanselmann
  @rtype: list of string
1398 208a6cff Michael Hanselmann

1399 208a6cff Michael Hanselmann
  """
1400 208a6cff Michael Hanselmann
  return [i.strip() for i in fields.split(",")]
1401 208a6cff Michael Hanselmann
1402 208a6cff Michael Hanselmann
1403 26ff6ee2 Michael Hanselmann
class R_2_query(baserlib.ResourceBase):
1404 208a6cff Michael Hanselmann
  """/2/query/[resource] resource.
1405 208a6cff Michael Hanselmann

1406 208a6cff Michael Hanselmann
  """
1407 208a6cff Michael Hanselmann
  # Results might contain sensitive information
1408 5e12acfe Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE, rapi.RAPI_ACCESS_READ]
1409 5e12acfe Michael Hanselmann
  PUT_ACCESS = GET_ACCESS
1410 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpQuery
1411 f6ce0ba2 Michael Hanselmann
  PUT_OPCODE = opcodes.OpQuery
1412 208a6cff Michael Hanselmann
1413 2e5c33db Iustin Pop
  def _Query(self, fields, qfilter):
1414 2e5c33db Iustin Pop
    return self.GetClient().Query(self.items[0], fields, qfilter).ToDict()
1415 208a6cff Michael Hanselmann
1416 208a6cff Michael Hanselmann
  def GET(self):
1417 208a6cff Michael Hanselmann
    """Returns resource information.
1418 208a6cff Michael Hanselmann

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

1421 208a6cff Michael Hanselmann
    """
1422 208a6cff Michael Hanselmann
    return self._Query(_GetQueryFields(self.queryargs), None)
1423 208a6cff Michael Hanselmann
1424 208a6cff Michael Hanselmann
  def PUT(self):
1425 208a6cff Michael Hanselmann
    """Submits job querying for resources.
1426 208a6cff Michael Hanselmann

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

1429 208a6cff Michael Hanselmann
    """
1430 208a6cff Michael Hanselmann
    body = self.request_body
1431 208a6cff Michael Hanselmann
1432 208a6cff Michael Hanselmann
    baserlib.CheckType(body, dict, "Body contents")
1433 208a6cff Michael Hanselmann
1434 208a6cff Michael Hanselmann
    try:
1435 208a6cff Michael Hanselmann
      fields = body["fields"]
1436 208a6cff Michael Hanselmann
    except KeyError:
1437 208a6cff Michael Hanselmann
      fields = _GetQueryFields(self.queryargs)
1438 208a6cff Michael Hanselmann
1439 2e5c33db Iustin Pop
    qfilter = body.get("qfilter", None)
1440 2e5c33db Iustin Pop
    # TODO: remove this after 2.7
1441 2e5c33db Iustin Pop
    if qfilter is None:
1442 2e5c33db Iustin Pop
      qfilter = body.get("filter", None)
1443 2e5c33db Iustin Pop
1444 2e5c33db Iustin Pop
    return self._Query(fields, qfilter)
1445 208a6cff Michael Hanselmann
1446 208a6cff Michael Hanselmann
1447 26ff6ee2 Michael Hanselmann
class R_2_query_fields(baserlib.ResourceBase):
1448 208a6cff Michael Hanselmann
  """/2/query/[resource]/fields resource.
1449 208a6cff Michael Hanselmann

1450 208a6cff Michael Hanselmann
  """
1451 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpQueryFields
1452 f6ce0ba2 Michael Hanselmann
1453 208a6cff Michael Hanselmann
  def GET(self):
1454 208a6cff Michael Hanselmann
    """Retrieves list of available fields for a resource.
1455 208a6cff Michael Hanselmann

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

1458 208a6cff Michael Hanselmann
    """
1459 208a6cff Michael Hanselmann
    try:
1460 208a6cff Michael Hanselmann
      raw_fields = self.queryargs["fields"]
1461 208a6cff Michael Hanselmann
    except KeyError:
1462 208a6cff Michael Hanselmann
      fields = None
1463 208a6cff Michael Hanselmann
    else:
1464 208a6cff Michael Hanselmann
      fields = _SplitQueryFields(raw_fields[0])
1465 208a6cff Michael Hanselmann
1466 be1ddd09 Michael Hanselmann
    return self.GetClient().QueryFields(self.items[0], fields).ToDict()
1467 208a6cff Michael Hanselmann
1468 208a6cff Michael Hanselmann
1469 460ef073 Michael Hanselmann
class _R_Tags(baserlib.OpcodeResource):
1470 3bd0f3d8 Iustin Pop
  """Quasiclass for tagging resources.
1471 441e7cfd Oleksiy Mishchenko

1472 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
1473 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
1474 441e7cfd Oleksiy Mishchenko

1475 441e7cfd Oleksiy Mishchenko
  """
1476 7a6b9510 Iustin Pop
  TAG_LEVEL = None
1477 f6ce0ba2 Michael Hanselmann
  GET_OPCODE = opcodes.OpTagsGet
1478 460ef073 Michael Hanselmann
  PUT_OPCODE = opcodes.OpTagsSet
1479 460ef073 Michael Hanselmann
  DELETE_OPCODE = opcodes.OpTagsDel
1480 18cb43a2 Oleksiy Mishchenko
1481 460ef073 Michael Hanselmann
  def __init__(self, items, queryargs, req, **kwargs):
1482 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
1483 18cb43a2 Oleksiy Mishchenko

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

1486 18cb43a2 Oleksiy Mishchenko
    """
1487 460ef073 Michael Hanselmann
    baserlib.OpcodeResource.__init__(self, items, queryargs, req, **kwargs)
1488 18cb43a2 Oleksiy Mishchenko
1489 5313eed7 Michael Hanselmann
    if self.TAG_LEVEL == constants.TAG_CLUSTER:
1490 5313eed7 Michael Hanselmann
      self.name = None
1491 18cb43a2 Oleksiy Mishchenko
    else:
1492 5313eed7 Michael Hanselmann
      self.name = items[0]
1493 441e7cfd Oleksiy Mishchenko
1494 441e7cfd Oleksiy Mishchenko
  def GET(self):
1495 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
1496 441e7cfd Oleksiy Mishchenko

1497 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
1498 441e7cfd Oleksiy Mishchenko

1499 441e7cfd Oleksiy Mishchenko
    """
1500 f87ec53f Michael Hanselmann
    kind = self.TAG_LEVEL
1501 f87ec53f Michael Hanselmann
1502 f87ec53f Michael Hanselmann
    if kind in (constants.TAG_INSTANCE,
1503 f87ec53f Michael Hanselmann
                constants.TAG_NODEGROUP,
1504 f87ec53f Michael Hanselmann
                constants.TAG_NODE):
1505 f87ec53f Michael Hanselmann
      if not self.name:
1506 f87ec53f Michael Hanselmann
        raise http.HttpBadRequest("Missing name on tag request")
1507 f87ec53f Michael Hanselmann
1508 f2374060 Iustin Pop
      cl = self.GetClient(query=True)
1509 cebd85d8 Iustin Pop
      tags = list(cl.QueryTags(kind, self.name))
1510 f87ec53f Michael Hanselmann
1511 f87ec53f Michael Hanselmann
    elif kind == constants.TAG_CLUSTER:
1512 f87ec53f Michael Hanselmann
      assert not self.name
1513 f87ec53f Michael Hanselmann
      # TODO: Use query API?
1514 f87ec53f Michael Hanselmann
      ssc = ssconf.SimpleStore()
1515 f87ec53f Michael Hanselmann
      tags = ssc.GetClusterTags()
1516 f87ec53f Michael Hanselmann
1517 f87ec53f Michael Hanselmann
    return list(tags)
1518 441e7cfd Oleksiy Mishchenko
1519 460ef073 Michael Hanselmann
  def GetPutOpInput(self):
1520 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
1521 441e7cfd Oleksiy Mishchenko

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

1525 441e7cfd Oleksiy Mishchenko
    """
1526 460ef073 Michael Hanselmann
    return ({}, {
1527 460ef073 Michael Hanselmann
      "kind": self.TAG_LEVEL,
1528 460ef073 Michael Hanselmann
      "name": self.name,
1529 460ef073 Michael Hanselmann
      "tags": self.queryargs.get("tag", []),
1530 460ef073 Michael Hanselmann
      "dry_run": self.dryRun(),
1531 460ef073 Michael Hanselmann
      })
1532 15fd9fd5 Oleksiy Mishchenko
1533 460ef073 Michael Hanselmann
  def GetDeleteOpInput(self):
1534 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
1535 15fd9fd5 Oleksiy Mishchenko

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

1540 15fd9fd5 Oleksiy Mishchenko
    """
1541 460ef073 Michael Hanselmann
    # Re-use code
1542 460ef073 Michael Hanselmann
    return self.GetPutOpInput()
1543 18cb43a2 Oleksiy Mishchenko
1544 18cb43a2 Oleksiy Mishchenko
1545 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
1546 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
1547 18cb43a2 Oleksiy Mishchenko

1548 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
1549 18cb43a2 Oleksiy Mishchenko

1550 18cb43a2 Oleksiy Mishchenko
  """
1551 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
1552 18cb43a2 Oleksiy Mishchenko
1553 18cb43a2 Oleksiy Mishchenko
1554 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
1555 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
1556 18cb43a2 Oleksiy Mishchenko

1557 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
1558 18cb43a2 Oleksiy Mishchenko

1559 18cb43a2 Oleksiy Mishchenko
  """
1560 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
1561 18cb43a2 Oleksiy Mishchenko
1562 18cb43a2 Oleksiy Mishchenko
1563 414ebaf1 Michael Hanselmann
class R_2_groups_name_tags(_R_Tags):
1564 414ebaf1 Michael Hanselmann
  """ /2/groups/[group_name]/tags resource.
1565 414ebaf1 Michael Hanselmann

1566 414ebaf1 Michael Hanselmann
  Manages per-nodegroup tags.
1567 414ebaf1 Michael Hanselmann

1568 414ebaf1 Michael Hanselmann
  """
1569 414ebaf1 Michael Hanselmann
  TAG_LEVEL = constants.TAG_NODEGROUP
1570 414ebaf1 Michael Hanselmann
1571 3c286190 Dimitris Aragiorgis
1572 6e8091f9 Dimitris Aragiorgis
class R_2_networks_name_tags(_R_Tags):
1573 6e8091f9 Dimitris Aragiorgis
  """ /2/networks/[network_name]/tags resource.
1574 6e8091f9 Dimitris Aragiorgis

1575 6e8091f9 Dimitris Aragiorgis
  Manages per-network tags.
1576 6e8091f9 Dimitris Aragiorgis

1577 6e8091f9 Dimitris Aragiorgis
  """
1578 6e8091f9 Dimitris Aragiorgis
  TAG_LEVEL = constants.TAG_NETWORK
1579 6e8091f9 Dimitris Aragiorgis
1580 414ebaf1 Michael Hanselmann
1581 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
1582 b58a4d16 Michael Hanselmann
  """ /2/tags resource.
1583 18cb43a2 Oleksiy Mishchenko

1584 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
1585 18cb43a2 Oleksiy Mishchenko

1586 18cb43a2 Oleksiy Mishchenko
  """
1587 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER