Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ 7a95a954

History | View | Annotate | Download (16.6 kB)

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

24 10b207d4 Oleksiy Mishchenko
"""
25 10b207d4 Oleksiy Mishchenko
26 59b4eeef Iustin Pop
from ganeti import opcodes
27 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
28 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
29 59b4eeef Iustin Pop
from ganeti import cli
30 38206f3c Iustin Pop
from ganeti.rapi import baserlib
31 10b207d4 Oleksiy Mishchenko
32 4e5a68f8 Oleksiy Mishchenko
33 9031ee8e Iustin Pop
I_FIELDS = ["name", "admin_state", "os",
34 9031ee8e Iustin Pop
            "pnode", "snodes",
35 9031ee8e Iustin Pop
            "disk_template",
36 495cfdf0 Guido Trotter
            "nic.ips", "nic.macs", "nic.modes", "nic.links",
37 a8b16c4e Tim Boring
            "network_port",
38 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
39 a5b9d725 Iustin Pop
            "beparams", "hvparams",
40 9031ee8e Iustin Pop
            "oper_state", "oper_ram", "status",
41 9031ee8e Iustin Pop
            "tags"]
42 9031ee8e Iustin Pop
43 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
44 9031ee8e Iustin Pop
            "dtotal", "dfree",
45 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
46 0105bad3 Iustin Pop
            "pinst_cnt", "sinst_cnt", "tags",
47 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
48 0105bad3 Iustin Pop
            ]
49 4e5a68f8 Oleksiy Mishchenko
50 64dae8fc Michael Hanselmann
_NR_DRAINED = "drained"
51 64dae8fc Michael Hanselmann
_NR_MASTER_CANDIATE = "master-candidate"
52 64dae8fc Michael Hanselmann
_NR_MASTER = "master"
53 64dae8fc Michael Hanselmann
_NR_OFFLINE = "offline"
54 64dae8fc Michael Hanselmann
_NR_REGULAR = "regular"
55 64dae8fc Michael Hanselmann
56 64dae8fc Michael Hanselmann
_NR_MAP = {
57 64dae8fc Michael Hanselmann
  "M": _NR_MASTER,
58 64dae8fc Michael Hanselmann
  "C": _NR_MASTER_CANDIATE,
59 64dae8fc Michael Hanselmann
  "D": _NR_DRAINED,
60 64dae8fc Michael Hanselmann
  "O": _NR_OFFLINE,
61 64dae8fc Michael Hanselmann
  "R": _NR_REGULAR,
62 64dae8fc Michael Hanselmann
  }
63 64dae8fc Michael Hanselmann
64 4e5a68f8 Oleksiy Mishchenko
65 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
66 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
67 4e5a68f8 Oleksiy Mishchenko

68 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
69 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
70 4e5a68f8 Oleksiy Mishchenko

71 4e5a68f8 Oleksiy Mishchenko
  """
72 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
73 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
74 4e5a68f8 Oleksiy Mishchenko

75 4e5a68f8 Oleksiy Mishchenko
    """
76 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
77 4e5a68f8 Oleksiy Mishchenko
78 4e5a68f8 Oleksiy Mishchenko
79 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
80 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
81 4e5a68f8 Oleksiy Mishchenko

82 4e5a68f8 Oleksiy Mishchenko
  """
83 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
84 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
85 4e5a68f8 Oleksiy Mishchenko

86 4e5a68f8 Oleksiy Mishchenko
    """
87 59b4eeef Iustin Pop
    client = baserlib.GetClient()
88 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
89 4e5a68f8 Oleksiy Mishchenko
90 4e5a68f8 Oleksiy Mishchenko
91 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
92 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
93 4e5a68f8 Oleksiy Mishchenko

94 4e5a68f8 Oleksiy Mishchenko
  """
95 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
96 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
97 4e5a68f8 Oleksiy Mishchenko

98 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
99 4e5a68f8 Oleksiy Mishchenko

100 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
101 4e5a68f8 Oleksiy Mishchenko

102 4e5a68f8 Oleksiy Mishchenko
    """
103 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
104 59b4eeef Iustin Pop
    op = opcodes.OpDiagnoseOS(output_fields=["name", "valid"], names=[])
105 59b4eeef Iustin Pop
    job_id = baserlib.SubmitJob([op], cl)
106 59b4eeef Iustin Pop
    # we use custom feedback function, instead of print we log the status
107 59b4eeef Iustin Pop
    result = cli.PollJob(job_id, cl, feedback_fn=baserlib.FeedbackFn)
108 59b4eeef Iustin Pop
    diagnose_data = result[0]
109 4e5a68f8 Oleksiy Mishchenko
110 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
111 59b4eeef Iustin Pop
      raise http.HttpBadGateway(message="Can't get OS list")
112 4e5a68f8 Oleksiy Mishchenko
113 4e5a68f8 Oleksiy Mishchenko
    return [row[0] for row in diagnose_data if row[1]]
114 51ee2f49 Oleksiy Mishchenko
115 10b207d4 Oleksiy Mishchenko
116 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
117 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
118 10b207d4 Oleksiy Mishchenko

119 10b207d4 Oleksiy Mishchenko
  """
120 10b207d4 Oleksiy Mishchenko
  def GET(self):
121 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
122 10b207d4 Oleksiy Mishchenko

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

125 10b207d4 Oleksiy Mishchenko
    """
126 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
127 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
128 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
129 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
130 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
131 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
132 10b207d4 Oleksiy Mishchenko
133 10b207d4 Oleksiy Mishchenko
134 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
135 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
136 10b207d4 Oleksiy Mishchenko

137 10b207d4 Oleksiy Mishchenko
  """
138 10b207d4 Oleksiy Mishchenko
  def GET(self):
139 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
140 10b207d4 Oleksiy Mishchenko

141 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
142 c41eea6e Iustin Pop
        The result includes:
143 c41eea6e Iustin Pop
            - id: job ID as a number
144 c41eea6e Iustin Pop
            - status: current job status as a string
145 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
146 c41eea6e Iustin Pop
              opcodes in the job
147 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
148 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
149 38206f3c Iustin Pop

150 10b207d4 Oleksiy Mishchenko
    """
151 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
152 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
153 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
154 ee69c97f Iustin Pop
              ]
155 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
156 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
157 ee69c97f Iustin Pop
    if result is None:
158 ee69c97f Iustin Pop
      raise http.HttpNotFound()
159 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
160 10b207d4 Oleksiy Mishchenko
161 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
162 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
163 c7f5f338 Oleksiy Mishchenko

164 c7f5f338 Oleksiy Mishchenko
    """
165 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
166 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
167 c7f5f338 Oleksiy Mishchenko
    return result
168 c7f5f338 Oleksiy Mishchenko
169 10b207d4 Oleksiy Mishchenko
170 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
171 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
172 10b207d4 Oleksiy Mishchenko

173 10b207d4 Oleksiy Mishchenko
  """
174 10b207d4 Oleksiy Mishchenko
  def GET(self):
175 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
176 38206f3c Iustin Pop

177 10b207d4 Oleksiy Mishchenko
    """
178 59b4eeef Iustin Pop
    client = baserlib.GetClient()
179 38206f3c Iustin Pop
180 3d103742 Iustin Pop
    if self.useBulk():
181 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
182 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
183 9031ee8e Iustin Pop
    else:
184 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
185 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
186 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
187 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
188 441e7cfd Oleksiy Mishchenko
189 441e7cfd Oleksiy Mishchenko
190 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
191 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
192 028c6b76 Oleksiy Mishchenko

193 028c6b76 Oleksiy Mishchenko
  """
194 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
195 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
196 4e5a68f8 Oleksiy Mishchenko

197 4e5a68f8 Oleksiy Mishchenko
    """
198 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
199 59b4eeef Iustin Pop
    client = baserlib.GetClient()
200 9031ee8e Iustin Pop
    result = client.QueryNodes(names=[node_name], fields=N_FIELDS,
201 3d103742 Iustin Pop
                               use_locking=self.useLocking())
202 4e5a68f8 Oleksiy Mishchenko
203 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
204 028c6b76 Oleksiy Mishchenko
205 028c6b76 Oleksiy Mishchenko
206 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
207 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
208 64dae8fc Michael Hanselmann

209 64dae8fc Michael Hanselmann
  """
210 64dae8fc Michael Hanselmann
  def GET(self):
211 64dae8fc Michael Hanselmann
    """Returns the current node role.
212 64dae8fc Michael Hanselmann

213 64dae8fc Michael Hanselmann
    @return: Node role
214 64dae8fc Michael Hanselmann

215 64dae8fc Michael Hanselmann
    """
216 64dae8fc Michael Hanselmann
    node_name = self.items[0]
217 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
218 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
219 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
220 64dae8fc Michael Hanselmann
221 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
222 64dae8fc Michael Hanselmann
223 64dae8fc Michael Hanselmann
  def PUT(self):
224 64dae8fc Michael Hanselmann
    """Sets the node role.
225 64dae8fc Michael Hanselmann

226 64dae8fc Michael Hanselmann
    @return: a job id
227 64dae8fc Michael Hanselmann

228 64dae8fc Michael Hanselmann
    """
229 64dae8fc Michael Hanselmann
    if not isinstance(self.req.request_body, basestring):
230 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
231 64dae8fc Michael Hanselmann
232 64dae8fc Michael Hanselmann
    node_name = self.items[0]
233 64dae8fc Michael Hanselmann
    role = self.req.request_body
234 64dae8fc Michael Hanselmann
235 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
236 64dae8fc Michael Hanselmann
      candidate = False
237 64dae8fc Michael Hanselmann
      offline = False
238 64dae8fc Michael Hanselmann
      drained = False
239 64dae8fc Michael Hanselmann
240 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
241 64dae8fc Michael Hanselmann
      candidate = True
242 64dae8fc Michael Hanselmann
      offline = drained = None
243 64dae8fc Michael Hanselmann
244 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
245 64dae8fc Michael Hanselmann
      drained = True
246 64dae8fc Michael Hanselmann
      candidate = offline = None
247 64dae8fc Michael Hanselmann
248 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
249 64dae8fc Michael Hanselmann
      offline = True
250 64dae8fc Michael Hanselmann
      candidate = drained = None
251 64dae8fc Michael Hanselmann
252 64dae8fc Michael Hanselmann
    else:
253 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
254 64dae8fc Michael Hanselmann
255 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
256 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
257 64dae8fc Michael Hanselmann
                                 offline=offline,
258 64dae8fc Michael Hanselmann
                                 drained=drained,
259 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
260 64dae8fc Michael Hanselmann
261 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
262 64dae8fc Michael Hanselmann
263 64dae8fc Michael Hanselmann
264 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
265 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
266 73452f12 Michael Hanselmann

267 73452f12 Michael Hanselmann
  """
268 73452f12 Michael Hanselmann
  def POST(self):
269 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
270 73452f12 Michael Hanselmann

271 73452f12 Michael Hanselmann
    """
272 73452f12 Michael Hanselmann
    node_name = self.items[0]
273 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
274 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
275 73452f12 Michael Hanselmann
276 73452f12 Michael Hanselmann
    op = opcodes.OpEvacuateNode(node_name=node_name,
277 73452f12 Michael Hanselmann
                                remote_node=remote_node,
278 73452f12 Michael Hanselmann
                                iallocator=iallocator)
279 73452f12 Michael Hanselmann
280 73452f12 Michael Hanselmann
    return baserlib.SubmitJob([op])
281 73452f12 Michael Hanselmann
282 73452f12 Michael Hanselmann
283 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
284 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
285 1c482bab Michael Hanselmann

286 1c482bab Michael Hanselmann
  """
287 1c482bab Michael Hanselmann
  def POST(self):
288 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
289 1c482bab Michael Hanselmann

290 1c482bab Michael Hanselmann
    """
291 1c482bab Michael Hanselmann
    node_name = self.items[0]
292 1c482bab Michael Hanselmann
    live = bool(self._checkIntVariable("live", default=1))
293 1c482bab Michael Hanselmann
294 1c482bab Michael Hanselmann
    op = opcodes.OpMigrateNode(node_name=node_name, live=live)
295 1c482bab Michael Hanselmann
296 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
297 1c482bab Michael Hanselmann
298 1c482bab Michael Hanselmann
299 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
300 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
301 7a95a954 Michael Hanselmann

302 7a95a954 Michael Hanselmann
  """
303 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
304 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
305 7a95a954 Michael Hanselmann
306 7a95a954 Michael Hanselmann
  def GET(self):
307 7a95a954 Michael Hanselmann
    node_name = self.items[0]
308 7a95a954 Michael Hanselmann
309 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
310 7a95a954 Michael Hanselmann
    if not storage_type:
311 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
312 7a95a954 Michael Hanselmann
                                " parameter")
313 7a95a954 Michael Hanselmann
314 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
315 7a95a954 Michael Hanselmann
    if not output_fields:
316 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
317 7a95a954 Michael Hanselmann
                                " parameter")
318 7a95a954 Michael Hanselmann
319 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
320 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
321 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
322 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
323 7a95a954 Michael Hanselmann
324 7a95a954 Michael Hanselmann
325 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
326 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
327 441e7cfd Oleksiy Mishchenko

328 441e7cfd Oleksiy Mishchenko
  """
329 441e7cfd Oleksiy Mishchenko
  def GET(self):
330 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
331 441e7cfd Oleksiy Mishchenko

332 441e7cfd Oleksiy Mishchenko
    """
333 59b4eeef Iustin Pop
    client = baserlib.GetClient()
334 441e7cfd Oleksiy Mishchenko
335 3d103742 Iustin Pop
    use_locking = self.useLocking()
336 3d103742 Iustin Pop
    if self.useBulk():
337 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
338 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
339 441e7cfd Oleksiy Mishchenko
    else:
340 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
341 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
342 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
343 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
344 441e7cfd Oleksiy Mishchenko
345 21f04e5e Oleksiy Mishchenko
  def POST(self):
346 2f7635f4 Oleksiy Mishchenko
    """Create an instance.
347 2f7635f4 Oleksiy Mishchenko

348 5fcc718f Iustin Pop
    @return: a job id
349 2f7635f4 Oleksiy Mishchenko

350 2f7635f4 Oleksiy Mishchenko
    """
351 6e99c5a0 Iustin Pop
    if not isinstance(self.req.request_body, dict):
352 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
353 6e99c5a0 Iustin Pop
354 6e99c5a0 Iustin Pop
    beparams = baserlib.MakeParamsDict(self.req.request_body,
355 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
356 6e99c5a0 Iustin Pop
    hvparams = baserlib.MakeParamsDict(self.req.request_body,
357 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
358 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
359 6e99c5a0 Iustin Pop
360 6e99c5a0 Iustin Pop
    # disk processing
361 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
362 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
363 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
364 6e99c5a0 Iustin Pop
    disks = []
365 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
366 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
367 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
368 6e99c5a0 Iustin Pop
                                  " be an integer")
369 6e99c5a0 Iustin Pop
      disks.append({"size": d})
370 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
371 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
372 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
373 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
374 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
375 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
376 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
377 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
378 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
379 495cfdf0 Guido Trotter
       nics[0]["bridge"] = fn("bridge")
380 2f7635f4 Oleksiy Mishchenko
381 59b4eeef Iustin Pop
    op = opcodes.OpCreateInstance(
382 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
383 59b4eeef Iustin Pop
      instance_name=fn('name'),
384 59b4eeef Iustin Pop
      disks=disks,
385 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
386 59b4eeef Iustin Pop
      os_type=fn('os'),
387 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
388 59b4eeef Iustin Pop
      snode=fn('snode', None),
389 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
390 59b4eeef Iustin Pop
      nics=nics,
391 59b4eeef Iustin Pop
      start=fn('start', True),
392 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
393 59b4eeef Iustin Pop
      wait_for_sync=True,
394 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
395 59b4eeef Iustin Pop
      hvparams=hvparams,
396 59b4eeef Iustin Pop
      beparams=beparams,
397 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
398 59b4eeef Iustin Pop
      file_driver=fn('file_driver', 'loop'),
399 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
400 59b4eeef Iustin Pop
      )
401 59b4eeef Iustin Pop
402 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
403 2f7635f4 Oleksiy Mishchenko
404 441e7cfd Oleksiy Mishchenko
405 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
406 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
407 028c6b76 Oleksiy Mishchenko

408 028c6b76 Oleksiy Mishchenko
  """
409 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
410 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
411 4e5a68f8 Oleksiy Mishchenko

412 4e5a68f8 Oleksiy Mishchenko
    """
413 59b4eeef Iustin Pop
    client = baserlib.GetClient()
414 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
415 9031ee8e Iustin Pop
    result = client.QueryInstances(names=[instance_name], fields=I_FIELDS,
416 3d103742 Iustin Pop
                                   use_locking=self.useLocking())
417 4e5a68f8 Oleksiy Mishchenko
418 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
419 028c6b76 Oleksiy Mishchenko
420 6e99c5a0 Iustin Pop
  def DELETE(self):
421 6e99c5a0 Iustin Pop
    """Delete an instance.
422 6e99c5a0 Iustin Pop

423 6e99c5a0 Iustin Pop
    """
424 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
425 6f59b964 Iustin Pop
                                  ignore_failures=False,
426 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
427 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
428 6e99c5a0 Iustin Pop
429 028c6b76 Oleksiy Mishchenko
430 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
431 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
432 2276aa29 Oleksiy Mishchenko

433 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
434 2276aa29 Oleksiy Mishchenko

435 2276aa29 Oleksiy Mishchenko
  """
436 21f04e5e Oleksiy Mishchenko
  def POST(self):
437 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
438 2276aa29 Oleksiy Mishchenko

439 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
440 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
441 0c55c24b Oleksiy Mishchenko

442 2276aa29 Oleksiy Mishchenko
    """
443 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
444 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
445 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
446 0c55c24b Oleksiy Mishchenko
    ignore_secondaries = bool(self.queryargs.get('ignore_secondaries',
447 0c55c24b Oleksiy Mishchenko
                                                 [False])[0])
448 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
449 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
450 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
451 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
452 2276aa29 Oleksiy Mishchenko
453 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
454 2276aa29 Oleksiy Mishchenko
455 2276aa29 Oleksiy Mishchenko
456 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
457 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
458 0c55c24b Oleksiy Mishchenko

459 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
460 0c55c24b Oleksiy Mishchenko

461 0c55c24b Oleksiy Mishchenko
  """
462 21f04e5e Oleksiy Mishchenko
  def PUT(self):
463 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
464 0c55c24b Oleksiy Mishchenko

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

468 0c55c24b Oleksiy Mishchenko
    """
469 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
470 0c55c24b Oleksiy Mishchenko
    force_startup = bool(self.queryargs.get('force', [False])[0])
471 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
472 6f59b964 Iustin Pop
                                   force=force_startup,
473 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
474 0c55c24b Oleksiy Mishchenko
475 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
476 0c55c24b Oleksiy Mishchenko
477 0c55c24b Oleksiy Mishchenko
478 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
479 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
480 0c55c24b Oleksiy Mishchenko

481 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
482 0c55c24b Oleksiy Mishchenko

483 0c55c24b Oleksiy Mishchenko
  """
484 21f04e5e Oleksiy Mishchenko
  def PUT(self):
485 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
486 0c55c24b Oleksiy Mishchenko

487 0c55c24b Oleksiy Mishchenko
    """
488 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
489 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
490 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
491 0c55c24b Oleksiy Mishchenko
492 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
493 0c55c24b Oleksiy Mishchenko
494 0c55c24b Oleksiy Mishchenko
495 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
496 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
497 e5b7c4ca Iustin Pop

498 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
499 e5b7c4ca Iustin Pop

500 e5b7c4ca Iustin Pop
  """
501 e5b7c4ca Iustin Pop
502 e5b7c4ca Iustin Pop
  DOC_URI = "/2/instances/[instance_name]/reinstall"
503 e5b7c4ca Iustin Pop
504 e5b7c4ca Iustin Pop
  def POST(self):
505 e5b7c4ca Iustin Pop
    """Reinstall an instance.
506 e5b7c4ca Iustin Pop

507 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
508 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
509 e5b7c4ca Iustin Pop
    automatically.
510 e5b7c4ca Iustin Pop

511 e5b7c4ca Iustin Pop
    """
512 e5b7c4ca Iustin Pop
    instance_name = self.items[0]
513 e5b7c4ca Iustin Pop
    ostype = self._checkStringVariable('os')
514 e5b7c4ca Iustin Pop
    nostartup = self._checkIntVariable('nostartup')
515 e5b7c4ca Iustin Pop
    ops = [
516 e5b7c4ca Iustin Pop
      opcodes.OpShutdownInstance(instance_name=instance_name),
517 e5b7c4ca Iustin Pop
      opcodes.OpReinstallInstance(instance_name=instance_name, os_type=ostype),
518 e5b7c4ca Iustin Pop
      ]
519 e5b7c4ca Iustin Pop
    if not nostartup:
520 e5b7c4ca Iustin Pop
      ops.append(opcodes.OpStartupInstance(instance_name=instance_name,
521 e5b7c4ca Iustin Pop
                                           force=False))
522 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
523 e5b7c4ca Iustin Pop
524 e5b7c4ca Iustin Pop
525 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
526 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
527 441e7cfd Oleksiy Mishchenko

528 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
529 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
530 441e7cfd Oleksiy Mishchenko

531 441e7cfd Oleksiy Mishchenko
  """
532 7a6b9510 Iustin Pop
  TAG_LEVEL = None
533 18cb43a2 Oleksiy Mishchenko
534 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
535 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
536 18cb43a2 Oleksiy Mishchenko

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

539 18cb43a2 Oleksiy Mishchenko
    """
540 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
541 18cb43a2 Oleksiy Mishchenko
542 18cb43a2 Oleksiy Mishchenko
    if self.TAG_LEVEL != constants.TAG_CLUSTER:
543 18cb43a2 Oleksiy Mishchenko
      self.name = items[0]
544 18cb43a2 Oleksiy Mishchenko
    else:
545 18cb43a2 Oleksiy Mishchenko
      self.name = ""
546 441e7cfd Oleksiy Mishchenko
547 441e7cfd Oleksiy Mishchenko
  def GET(self):
548 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
549 441e7cfd Oleksiy Mishchenko

550 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
551 441e7cfd Oleksiy Mishchenko

552 441e7cfd Oleksiy Mishchenko
    """
553 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
554 441e7cfd Oleksiy Mishchenko
555 21f04e5e Oleksiy Mishchenko
  def PUT(self):
556 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
557 441e7cfd Oleksiy Mishchenko

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

561 441e7cfd Oleksiy Mishchenko
    """
562 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
563 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
564 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
565 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
566 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
567 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
568 15fd9fd5 Oleksiy Mishchenko
569 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
570 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
571 15fd9fd5 Oleksiy Mishchenko

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

576 15fd9fd5 Oleksiy Mishchenko
    """
577 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
578 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
579 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
580 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
581 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
582 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
583 6f59b964 Iustin Pop
                                 name=self.name,
584 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
585 18cb43a2 Oleksiy Mishchenko
586 18cb43a2 Oleksiy Mishchenko
587 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
588 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
589 18cb43a2 Oleksiy Mishchenko

590 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
591 18cb43a2 Oleksiy Mishchenko

592 18cb43a2 Oleksiy Mishchenko
  """
593 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
594 18cb43a2 Oleksiy Mishchenko
595 18cb43a2 Oleksiy Mishchenko
596 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
597 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
598 18cb43a2 Oleksiy Mishchenko

599 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
600 18cb43a2 Oleksiy Mishchenko

601 18cb43a2 Oleksiy Mishchenko
  """
602 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
603 18cb43a2 Oleksiy Mishchenko
604 18cb43a2 Oleksiy Mishchenko
605 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
606 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
607 18cb43a2 Oleksiy Mishchenko

608 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
609 18cb43a2 Oleksiy Mishchenko

610 18cb43a2 Oleksiy Mishchenko
  """
611 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER