Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ a3db74e4

History | View | Annotate | Download (19.9 kB)

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

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

71 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
72 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
73 4e5a68f8 Oleksiy Mishchenko

74 4e5a68f8 Oleksiy Mishchenko
  """
75 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
76 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
77 4e5a68f8 Oleksiy Mishchenko

78 4e5a68f8 Oleksiy Mishchenko
    """
79 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
80 4e5a68f8 Oleksiy Mishchenko
81 4e5a68f8 Oleksiy Mishchenko
82 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
83 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
84 4e5a68f8 Oleksiy Mishchenko

85 4e5a68f8 Oleksiy Mishchenko
  """
86 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
87 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
88 4e5a68f8 Oleksiy Mishchenko

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

97 4e5a68f8 Oleksiy Mishchenko
  """
98 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
99 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
100 4e5a68f8 Oleksiy Mishchenko

101 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
102 4e5a68f8 Oleksiy Mishchenko

103 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
104 4e5a68f8 Oleksiy Mishchenko

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

122 508e9b20 Michael Hanselmann
  """
123 508e9b20 Michael Hanselmann
  def PUT(self):
124 508e9b20 Michael Hanselmann
    """Redistribute configuration to all nodes.
125 508e9b20 Michael Hanselmann

126 508e9b20 Michael Hanselmann
    """
127 508e9b20 Michael Hanselmann
    return baserlib.SubmitJob([opcodes.OpRedistributeConfig()])
128 508e9b20 Michael Hanselmann
129 508e9b20 Michael Hanselmann
130 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
131 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
132 10b207d4 Oleksiy Mishchenko

133 10b207d4 Oleksiy Mishchenko
  """
134 10b207d4 Oleksiy Mishchenko
  def GET(self):
135 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
136 10b207d4 Oleksiy Mishchenko

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

139 10b207d4 Oleksiy Mishchenko
    """
140 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
141 59b4eeef Iustin Pop
    cl = baserlib.GetClient()
142 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
143 59b4eeef Iustin Pop
    result = [job_id for [job_id] in cl.QueryJobs(None, fields)]
144 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
145 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
146 10b207d4 Oleksiy Mishchenko
147 10b207d4 Oleksiy Mishchenko
148 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
149 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
150 10b207d4 Oleksiy Mishchenko

151 10b207d4 Oleksiy Mishchenko
  """
152 10b207d4 Oleksiy Mishchenko
  def GET(self):
153 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
154 10b207d4 Oleksiy Mishchenko

155 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
156 c41eea6e Iustin Pop
        The result includes:
157 c41eea6e Iustin Pop
            - id: job ID as a number
158 c41eea6e Iustin Pop
            - status: current job status as a string
159 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
160 c41eea6e Iustin Pop
              opcodes in the job
161 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
162 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
163 38206f3c Iustin Pop

164 10b207d4 Oleksiy Mishchenko
    """
165 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
166 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
167 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
168 ee69c97f Iustin Pop
              ]
169 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
170 59b4eeef Iustin Pop
    result = baserlib.GetClient().QueryJobs([job_id, ], fields)[0]
171 ee69c97f Iustin Pop
    if result is None:
172 ee69c97f Iustin Pop
      raise http.HttpNotFound()
173 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
174 10b207d4 Oleksiy Mishchenko
175 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
176 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
177 c7f5f338 Oleksiy Mishchenko

178 c7f5f338 Oleksiy Mishchenko
    """
179 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
180 59b4eeef Iustin Pop
    result = baserlib.GetClient().CancelJob(job_id)
181 c7f5f338 Oleksiy Mishchenko
    return result
182 c7f5f338 Oleksiy Mishchenko
183 10b207d4 Oleksiy Mishchenko
184 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
185 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
186 10b207d4 Oleksiy Mishchenko

187 10b207d4 Oleksiy Mishchenko
  """
188 10b207d4 Oleksiy Mishchenko
  def GET(self):
189 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
190 38206f3c Iustin Pop

191 10b207d4 Oleksiy Mishchenko
    """
192 59b4eeef Iustin Pop
    client = baserlib.GetClient()
193 38206f3c Iustin Pop
194 3d103742 Iustin Pop
    if self.useBulk():
195 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
196 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
197 9031ee8e Iustin Pop
    else:
198 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
199 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
200 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
201 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
202 441e7cfd Oleksiy Mishchenko
203 441e7cfd Oleksiy Mishchenko
204 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
205 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
206 028c6b76 Oleksiy Mishchenko

207 028c6b76 Oleksiy Mishchenko
  """
208 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
209 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
210 4e5a68f8 Oleksiy Mishchenko

211 4e5a68f8 Oleksiy Mishchenko
    """
212 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
213 59b4eeef Iustin Pop
    client = baserlib.GetClient()
214 9031ee8e Iustin Pop
    result = client.QueryNodes(names=[node_name], fields=N_FIELDS,
215 3d103742 Iustin Pop
                               use_locking=self.useLocking())
216 4e5a68f8 Oleksiy Mishchenko
217 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
218 028c6b76 Oleksiy Mishchenko
219 028c6b76 Oleksiy Mishchenko
220 64dae8fc Michael Hanselmann
class R_2_nodes_name_role(baserlib.R_Generic):
221 64dae8fc Michael Hanselmann
  """ /2/nodes/[node_name]/role resource.
222 64dae8fc Michael Hanselmann

223 64dae8fc Michael Hanselmann
  """
224 64dae8fc Michael Hanselmann
  def GET(self):
225 64dae8fc Michael Hanselmann
    """Returns the current node role.
226 64dae8fc Michael Hanselmann

227 64dae8fc Michael Hanselmann
    @return: Node role
228 64dae8fc Michael Hanselmann

229 64dae8fc Michael Hanselmann
    """
230 64dae8fc Michael Hanselmann
    node_name = self.items[0]
231 64dae8fc Michael Hanselmann
    client = baserlib.GetClient()
232 64dae8fc Michael Hanselmann
    result = client.QueryNodes(names=[node_name], fields=["role"],
233 64dae8fc Michael Hanselmann
                               use_locking=self.useLocking())
234 64dae8fc Michael Hanselmann
235 64dae8fc Michael Hanselmann
    return _NR_MAP[result[0][0]]
236 64dae8fc Michael Hanselmann
237 64dae8fc Michael Hanselmann
  def PUT(self):
238 64dae8fc Michael Hanselmann
    """Sets the node role.
239 64dae8fc Michael Hanselmann

240 64dae8fc Michael Hanselmann
    @return: a job id
241 64dae8fc Michael Hanselmann

242 64dae8fc Michael Hanselmann
    """
243 64dae8fc Michael Hanselmann
    if not isinstance(self.req.request_body, basestring):
244 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Invalid body contents, not a string")
245 64dae8fc Michael Hanselmann
246 64dae8fc Michael Hanselmann
    node_name = self.items[0]
247 64dae8fc Michael Hanselmann
    role = self.req.request_body
248 64dae8fc Michael Hanselmann
249 64dae8fc Michael Hanselmann
    if role == _NR_REGULAR:
250 64dae8fc Michael Hanselmann
      candidate = False
251 64dae8fc Michael Hanselmann
      offline = False
252 64dae8fc Michael Hanselmann
      drained = False
253 64dae8fc Michael Hanselmann
254 64dae8fc Michael Hanselmann
    elif role == _NR_MASTER_CANDIATE:
255 64dae8fc Michael Hanselmann
      candidate = True
256 64dae8fc Michael Hanselmann
      offline = drained = None
257 64dae8fc Michael Hanselmann
258 64dae8fc Michael Hanselmann
    elif role == _NR_DRAINED:
259 64dae8fc Michael Hanselmann
      drained = True
260 64dae8fc Michael Hanselmann
      candidate = offline = None
261 64dae8fc Michael Hanselmann
262 64dae8fc Michael Hanselmann
    elif role == _NR_OFFLINE:
263 64dae8fc Michael Hanselmann
      offline = True
264 64dae8fc Michael Hanselmann
      candidate = drained = None
265 64dae8fc Michael Hanselmann
266 64dae8fc Michael Hanselmann
    else:
267 64dae8fc Michael Hanselmann
      raise http.HttpBadRequest("Can't set '%s' role" % role)
268 64dae8fc Michael Hanselmann
269 64dae8fc Michael Hanselmann
    op = opcodes.OpSetNodeParams(node_name=node_name,
270 64dae8fc Michael Hanselmann
                                 master_candidate=candidate,
271 64dae8fc Michael Hanselmann
                                 offline=offline,
272 64dae8fc Michael Hanselmann
                                 drained=drained,
273 64dae8fc Michael Hanselmann
                                 force=bool(self.useForce()))
274 64dae8fc Michael Hanselmann
275 64dae8fc Michael Hanselmann
    return baserlib.SubmitJob([op])
276 64dae8fc Michael Hanselmann
277 64dae8fc Michael Hanselmann
278 73452f12 Michael Hanselmann
class R_2_nodes_name_evacuate(baserlib.R_Generic):
279 73452f12 Michael Hanselmann
  """/2/nodes/[node_name]/evacuate resource.
280 73452f12 Michael Hanselmann

281 73452f12 Michael Hanselmann
  """
282 73452f12 Michael Hanselmann
  def POST(self):
283 73452f12 Michael Hanselmann
    """Evacuate all secondary instances off a node.
284 73452f12 Michael Hanselmann

285 73452f12 Michael Hanselmann
    """
286 73452f12 Michael Hanselmann
    node_name = self.items[0]
287 73452f12 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
288 73452f12 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
289 73452f12 Michael Hanselmann
290 73452f12 Michael Hanselmann
    op = opcodes.OpEvacuateNode(node_name=node_name,
291 73452f12 Michael Hanselmann
                                remote_node=remote_node,
292 73452f12 Michael Hanselmann
                                iallocator=iallocator)
293 73452f12 Michael Hanselmann
294 73452f12 Michael Hanselmann
    return baserlib.SubmitJob([op])
295 73452f12 Michael Hanselmann
296 73452f12 Michael Hanselmann
297 1c482bab Michael Hanselmann
class R_2_nodes_name_migrate(baserlib.R_Generic):
298 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/migrate resource.
299 1c482bab Michael Hanselmann

300 1c482bab Michael Hanselmann
  """
301 1c482bab Michael Hanselmann
  def POST(self):
302 1c482bab Michael Hanselmann
    """Migrate all primary instances from a node.
303 1c482bab Michael Hanselmann

304 1c482bab Michael Hanselmann
    """
305 1c482bab Michael Hanselmann
    node_name = self.items[0]
306 1c482bab Michael Hanselmann
    live = bool(self._checkIntVariable("live", default=1))
307 1c482bab Michael Hanselmann
308 1c482bab Michael Hanselmann
    op = opcodes.OpMigrateNode(node_name=node_name, live=live)
309 1c482bab Michael Hanselmann
310 1c482bab Michael Hanselmann
    return baserlib.SubmitJob([op])
311 1c482bab Michael Hanselmann
312 1c482bab Michael Hanselmann
313 7a95a954 Michael Hanselmann
class R_2_nodes_name_storage(baserlib.R_Generic):
314 7a95a954 Michael Hanselmann
  """/2/nodes/[node_name]/storage ressource.
315 7a95a954 Michael Hanselmann

316 7a95a954 Michael Hanselmann
  """
317 7a95a954 Michael Hanselmann
  # LUQueryNodeStorage acquires locks, hence restricting access to GET
318 7a95a954 Michael Hanselmann
  GET_ACCESS = [rapi.RAPI_ACCESS_WRITE]
319 7a95a954 Michael Hanselmann
320 7a95a954 Michael Hanselmann
  def GET(self):
321 7a95a954 Michael Hanselmann
    node_name = self.items[0]
322 7a95a954 Michael Hanselmann
323 7a95a954 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
324 7a95a954 Michael Hanselmann
    if not storage_type:
325 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
326 7a95a954 Michael Hanselmann
                                " parameter")
327 7a95a954 Michael Hanselmann
328 7a95a954 Michael Hanselmann
    output_fields = self._checkStringVariable("output_fields", None)
329 7a95a954 Michael Hanselmann
    if not output_fields:
330 7a95a954 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'output_fields'"
331 7a95a954 Michael Hanselmann
                                " parameter")
332 7a95a954 Michael Hanselmann
333 7a95a954 Michael Hanselmann
    op = opcodes.OpQueryNodeStorage(nodes=[node_name],
334 7a95a954 Michael Hanselmann
                                    storage_type=storage_type,
335 7a95a954 Michael Hanselmann
                                    output_fields=output_fields.split(","))
336 7a95a954 Michael Hanselmann
    return baserlib.SubmitJob([op])
337 7a95a954 Michael Hanselmann
338 7a95a954 Michael Hanselmann
339 1e82bc80 Michael Hanselmann
class R_2_nodes_name_storage_modify(baserlib.R_Generic):
340 1e82bc80 Michael Hanselmann
  """/2/nodes/[node_name]/storage/modify ressource.
341 1e82bc80 Michael Hanselmann

342 1e82bc80 Michael Hanselmann
  """
343 1e82bc80 Michael Hanselmann
  def PUT(self):
344 1e82bc80 Michael Hanselmann
    node_name = self.items[0]
345 1e82bc80 Michael Hanselmann
346 1e82bc80 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
347 1e82bc80 Michael Hanselmann
    if not storage_type:
348 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
349 1e82bc80 Michael Hanselmann
                                " parameter")
350 1e82bc80 Michael Hanselmann
351 1e82bc80 Michael Hanselmann
    name = self._checkStringVariable("name", None)
352 1e82bc80 Michael Hanselmann
    if not name:
353 1e82bc80 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
354 1e82bc80 Michael Hanselmann
                                " parameter")
355 1e82bc80 Michael Hanselmann
356 1e82bc80 Michael Hanselmann
    changes = {}
357 1e82bc80 Michael Hanselmann
358 1e82bc80 Michael Hanselmann
    if "allocatable" in self.queryargs:
359 1e82bc80 Michael Hanselmann
      changes[constants.SF_ALLOCATABLE] = \
360 1e82bc80 Michael Hanselmann
        bool(self._checkIntVariable("allocatable", default=1))
361 1e82bc80 Michael Hanselmann
362 1e82bc80 Michael Hanselmann
    op = opcodes.OpModifyNodeStorage(node_name=node_name,
363 1e82bc80 Michael Hanselmann
                                     storage_type=storage_type,
364 1e82bc80 Michael Hanselmann
                                     name=name,
365 1e82bc80 Michael Hanselmann
                                     changes=changes)
366 1e82bc80 Michael Hanselmann
    return baserlib.SubmitJob([op])
367 1e82bc80 Michael Hanselmann
368 1e82bc80 Michael Hanselmann
369 723f4565 Michael Hanselmann
class R_2_nodes_name_storage_repair(baserlib.R_Generic):
370 723f4565 Michael Hanselmann
  """/2/nodes/[node_name]/storage/repair ressource.
371 723f4565 Michael Hanselmann

372 723f4565 Michael Hanselmann
  """
373 723f4565 Michael Hanselmann
  def PUT(self):
374 723f4565 Michael Hanselmann
    node_name = self.items[0]
375 723f4565 Michael Hanselmann
376 723f4565 Michael Hanselmann
    storage_type = self._checkStringVariable("storage_type", None)
377 723f4565 Michael Hanselmann
    if not storage_type:
378 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'storage_type'"
379 723f4565 Michael Hanselmann
                                " parameter")
380 723f4565 Michael Hanselmann
381 723f4565 Michael Hanselmann
    name = self._checkStringVariable("name", None)
382 723f4565 Michael Hanselmann
    if not name:
383 723f4565 Michael Hanselmann
      raise http.HttpBadRequest("Missing the required 'name'"
384 723f4565 Michael Hanselmann
                                " parameter")
385 723f4565 Michael Hanselmann
386 723f4565 Michael Hanselmann
    op = opcodes.OpRepairNodeStorage(node_name=node_name,
387 723f4565 Michael Hanselmann
                                     storage_type=storage_type,
388 723f4565 Michael Hanselmann
                                     name=name)
389 723f4565 Michael Hanselmann
    return baserlib.SubmitJob([op])
390 723f4565 Michael Hanselmann
391 723f4565 Michael Hanselmann
392 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
393 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
394 441e7cfd Oleksiy Mishchenko

395 441e7cfd Oleksiy Mishchenko
  """
396 441e7cfd Oleksiy Mishchenko
  def GET(self):
397 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
398 441e7cfd Oleksiy Mishchenko

399 441e7cfd Oleksiy Mishchenko
    """
400 59b4eeef Iustin Pop
    client = baserlib.GetClient()
401 441e7cfd Oleksiy Mishchenko
402 3d103742 Iustin Pop
    use_locking = self.useLocking()
403 3d103742 Iustin Pop
    if self.useBulk():
404 3d103742 Iustin Pop
      bulkdata = client.QueryInstances([], I_FIELDS, use_locking)
405 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, I_FIELDS)
406 441e7cfd Oleksiy Mishchenko
    else:
407 3d103742 Iustin Pop
      instancesdata = client.QueryInstances([], ["name"], use_locking)
408 9031ee8e Iustin Pop
      instanceslist = [row[0] for row in instancesdata]
409 441e7cfd Oleksiy Mishchenko
      return baserlib.BuildUriList(instanceslist, "/2/instances/%s",
410 441e7cfd Oleksiy Mishchenko
                                   uri_fields=("id", "uri"))
411 441e7cfd Oleksiy Mishchenko
412 21f04e5e Oleksiy Mishchenko
  def POST(self):
413 2f7635f4 Oleksiy Mishchenko
    """Create an instance.
414 2f7635f4 Oleksiy Mishchenko

415 5fcc718f Iustin Pop
    @return: a job id
416 2f7635f4 Oleksiy Mishchenko

417 2f7635f4 Oleksiy Mishchenko
    """
418 6e99c5a0 Iustin Pop
    if not isinstance(self.req.request_body, dict):
419 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Invalid body contents, not a dictionary")
420 6e99c5a0 Iustin Pop
421 6e99c5a0 Iustin Pop
    beparams = baserlib.MakeParamsDict(self.req.request_body,
422 6e99c5a0 Iustin Pop
                                       constants.BES_PARAMETERS)
423 6e99c5a0 Iustin Pop
    hvparams = baserlib.MakeParamsDict(self.req.request_body,
424 6e99c5a0 Iustin Pop
                                       constants.HVS_PARAMETERS)
425 6e99c5a0 Iustin Pop
    fn = self.getBodyParameter
426 6e99c5a0 Iustin Pop
427 6e99c5a0 Iustin Pop
    # disk processing
428 6e99c5a0 Iustin Pop
    disk_data = fn('disks')
429 6e99c5a0 Iustin Pop
    if not isinstance(disk_data, list):
430 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("The 'disks' parameter should be a list")
431 6e99c5a0 Iustin Pop
    disks = []
432 6e99c5a0 Iustin Pop
    for idx, d in enumerate(disk_data):
433 6e99c5a0 Iustin Pop
      if not isinstance(d, int):
434 6e99c5a0 Iustin Pop
        raise http.HttpBadRequest("Disk %d specification wrong: should"
435 6e99c5a0 Iustin Pop
                                  " be an integer")
436 6e99c5a0 Iustin Pop
      disks.append({"size": d})
437 6e99c5a0 Iustin Pop
    # nic processing (one nic only)
438 495cfdf0 Guido Trotter
    nics = [{"mac": fn("mac", constants.VALUE_AUTO)}]
439 495cfdf0 Guido Trotter
    if fn("ip", None) is not None:
440 495cfdf0 Guido Trotter
      nics[0]["ip"] = fn("ip")
441 495cfdf0 Guido Trotter
    if fn("mode", None) is not None:
442 495cfdf0 Guido Trotter
      nics[0]["mode"] = fn("mode")
443 495cfdf0 Guido Trotter
    if fn("link", None) is not None:
444 495cfdf0 Guido Trotter
      nics[0]["link"] = fn("link")
445 495cfdf0 Guido Trotter
    if fn("bridge", None) is not None:
446 495cfdf0 Guido Trotter
       nics[0]["bridge"] = fn("bridge")
447 2f7635f4 Oleksiy Mishchenko
448 59b4eeef Iustin Pop
    op = opcodes.OpCreateInstance(
449 59b4eeef Iustin Pop
      mode=constants.INSTANCE_CREATE,
450 59b4eeef Iustin Pop
      instance_name=fn('name'),
451 59b4eeef Iustin Pop
      disks=disks,
452 59b4eeef Iustin Pop
      disk_template=fn('disk_template'),
453 59b4eeef Iustin Pop
      os_type=fn('os'),
454 59b4eeef Iustin Pop
      pnode=fn('pnode', None),
455 59b4eeef Iustin Pop
      snode=fn('snode', None),
456 59b4eeef Iustin Pop
      iallocator=fn('iallocator', None),
457 59b4eeef Iustin Pop
      nics=nics,
458 59b4eeef Iustin Pop
      start=fn('start', True),
459 59b4eeef Iustin Pop
      ip_check=fn('ip_check', True),
460 59b4eeef Iustin Pop
      wait_for_sync=True,
461 59b4eeef Iustin Pop
      hypervisor=fn('hypervisor', None),
462 59b4eeef Iustin Pop
      hvparams=hvparams,
463 59b4eeef Iustin Pop
      beparams=beparams,
464 59b4eeef Iustin Pop
      file_storage_dir=fn('file_storage_dir', None),
465 59b4eeef Iustin Pop
      file_driver=fn('file_driver', 'loop'),
466 6f59b964 Iustin Pop
      dry_run=bool(self.dryRun()),
467 59b4eeef Iustin Pop
      )
468 59b4eeef Iustin Pop
469 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
470 2f7635f4 Oleksiy Mishchenko
471 441e7cfd Oleksiy Mishchenko
472 4e5a68f8 Oleksiy Mishchenko
class R_2_instances_name(baserlib.R_Generic):
473 4e5a68f8 Oleksiy Mishchenko
  """/2/instances/[instance_name] resources.
474 028c6b76 Oleksiy Mishchenko

475 028c6b76 Oleksiy Mishchenko
  """
476 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
477 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
478 4e5a68f8 Oleksiy Mishchenko

479 4e5a68f8 Oleksiy Mishchenko
    """
480 59b4eeef Iustin Pop
    client = baserlib.GetClient()
481 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
482 9031ee8e Iustin Pop
    result = client.QueryInstances(names=[instance_name], fields=I_FIELDS,
483 3d103742 Iustin Pop
                                   use_locking=self.useLocking())
484 4e5a68f8 Oleksiy Mishchenko
485 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
486 028c6b76 Oleksiy Mishchenko
487 6e99c5a0 Iustin Pop
  def DELETE(self):
488 6e99c5a0 Iustin Pop
    """Delete an instance.
489 6e99c5a0 Iustin Pop

490 6e99c5a0 Iustin Pop
    """
491 59b4eeef Iustin Pop
    op = opcodes.OpRemoveInstance(instance_name=self.items[0],
492 6f59b964 Iustin Pop
                                  ignore_failures=False,
493 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
494 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
495 6e99c5a0 Iustin Pop
496 028c6b76 Oleksiy Mishchenko
497 d8260842 Michael Hanselmann
class R_2_instances_name_info(baserlib.R_Generic):
498 d8260842 Michael Hanselmann
  """/2/instances/[instance_name]/info resource.
499 d8260842 Michael Hanselmann

500 d8260842 Michael Hanselmann
  """
501 d8260842 Michael Hanselmann
  def GET(self):
502 d8260842 Michael Hanselmann
    """Request detailed instance information.
503 d8260842 Michael Hanselmann

504 d8260842 Michael Hanselmann
    """
505 d8260842 Michael Hanselmann
    instance_name = self.items[0]
506 d8260842 Michael Hanselmann
    static = bool(self._checkIntVariable("static", default=0))
507 d8260842 Michael Hanselmann
508 d8260842 Michael Hanselmann
    op = opcodes.OpQueryInstanceData(instances=[instance_name],
509 d8260842 Michael Hanselmann
                                     static=static)
510 d8260842 Michael Hanselmann
    return baserlib.SubmitJob([op])
511 d8260842 Michael Hanselmann
512 d8260842 Michael Hanselmann
513 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
514 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
515 2276aa29 Oleksiy Mishchenko

516 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
517 2276aa29 Oleksiy Mishchenko

518 2276aa29 Oleksiy Mishchenko
  """
519 21f04e5e Oleksiy Mishchenko
  def POST(self):
520 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
521 2276aa29 Oleksiy Mishchenko

522 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
523 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
524 0c55c24b Oleksiy Mishchenko

525 2276aa29 Oleksiy Mishchenko
    """
526 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
527 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
528 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
529 94cdfa4a Iustin Pop
    ignore_secondaries = bool(self._checkIntVariable('ignore_secondaries'))
530 59b4eeef Iustin Pop
    op = opcodes.OpRebootInstance(instance_name=instance_name,
531 59b4eeef Iustin Pop
                                  reboot_type=reboot_type,
532 6f59b964 Iustin Pop
                                  ignore_secondaries=ignore_secondaries,
533 6f59b964 Iustin Pop
                                  dry_run=bool(self.dryRun()))
534 2276aa29 Oleksiy Mishchenko
535 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
536 2276aa29 Oleksiy Mishchenko
537 2276aa29 Oleksiy Mishchenko
538 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
539 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
540 0c55c24b Oleksiy Mishchenko

541 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
542 0c55c24b Oleksiy Mishchenko

543 0c55c24b Oleksiy Mishchenko
  """
544 21f04e5e Oleksiy Mishchenko
  def PUT(self):
545 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
546 0c55c24b Oleksiy Mishchenko

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

550 0c55c24b Oleksiy Mishchenko
    """
551 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
552 94cdfa4a Iustin Pop
    force_startup = bool(self._checkIntVariable('force'))
553 59b4eeef Iustin Pop
    op = opcodes.OpStartupInstance(instance_name=instance_name,
554 6f59b964 Iustin Pop
                                   force=force_startup,
555 6f59b964 Iustin Pop
                                   dry_run=bool(self.dryRun()))
556 0c55c24b Oleksiy Mishchenko
557 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
558 0c55c24b Oleksiy Mishchenko
559 0c55c24b Oleksiy Mishchenko
560 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_shutdown(baserlib.R_Generic):
561 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/shutdown resource.
562 0c55c24b Oleksiy Mishchenko

563 0c55c24b Oleksiy Mishchenko
  Implements an instance shutdown.
564 0c55c24b Oleksiy Mishchenko

565 0c55c24b Oleksiy Mishchenko
  """
566 21f04e5e Oleksiy Mishchenko
  def PUT(self):
567 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
568 0c55c24b Oleksiy Mishchenko

569 0c55c24b Oleksiy Mishchenko
    """
570 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
571 6f59b964 Iustin Pop
    op = opcodes.OpShutdownInstance(instance_name=instance_name,
572 6f59b964 Iustin Pop
                                    dry_run=bool(self.dryRun()))
573 0c55c24b Oleksiy Mishchenko
574 59b4eeef Iustin Pop
    return baserlib.SubmitJob([op])
575 0c55c24b Oleksiy Mishchenko
576 0c55c24b Oleksiy Mishchenko
577 e5b7c4ca Iustin Pop
class R_2_instances_name_reinstall(baserlib.R_Generic):
578 e5b7c4ca Iustin Pop
  """/2/instances/[instance_name]/reinstall resource.
579 e5b7c4ca Iustin Pop

580 e5b7c4ca Iustin Pop
  Implements an instance reinstall.
581 e5b7c4ca Iustin Pop

582 e5b7c4ca Iustin Pop
  """
583 e5b7c4ca Iustin Pop
  def POST(self):
584 e5b7c4ca Iustin Pop
    """Reinstall an instance.
585 e5b7c4ca Iustin Pop

586 e5b7c4ca Iustin Pop
    The URI takes os=name and nostartup=[0|1] optional
587 e5b7c4ca Iustin Pop
    parameters. By default, the instance will be started
588 e5b7c4ca Iustin Pop
    automatically.
589 e5b7c4ca Iustin Pop

590 e5b7c4ca Iustin Pop
    """
591 e5b7c4ca Iustin Pop
    instance_name = self.items[0]
592 e5b7c4ca Iustin Pop
    ostype = self._checkStringVariable('os')
593 e5b7c4ca Iustin Pop
    nostartup = self._checkIntVariable('nostartup')
594 e5b7c4ca Iustin Pop
    ops = [
595 e5b7c4ca Iustin Pop
      opcodes.OpShutdownInstance(instance_name=instance_name),
596 e5b7c4ca Iustin Pop
      opcodes.OpReinstallInstance(instance_name=instance_name, os_type=ostype),
597 e5b7c4ca Iustin Pop
      ]
598 e5b7c4ca Iustin Pop
    if not nostartup:
599 e5b7c4ca Iustin Pop
      ops.append(opcodes.OpStartupInstance(instance_name=instance_name,
600 e5b7c4ca Iustin Pop
                                           force=False))
601 e5b7c4ca Iustin Pop
    return baserlib.SubmitJob(ops)
602 e5b7c4ca Iustin Pop
603 e5b7c4ca Iustin Pop
604 4c98b915 Michael Hanselmann
class R_2_instances_name_replace_disks(baserlib.R_Generic):
605 4c98b915 Michael Hanselmann
  """/2/instances/[instance_name]/replace-disks resource.
606 4c98b915 Michael Hanselmann

607 4c98b915 Michael Hanselmann
  """
608 4c98b915 Michael Hanselmann
  def POST(self):
609 4c98b915 Michael Hanselmann
    """Replaces disks on an instance.
610 4c98b915 Michael Hanselmann

611 4c98b915 Michael Hanselmann
    """
612 4c98b915 Michael Hanselmann
    instance_name = self.items[0]
613 4c98b915 Michael Hanselmann
    remote_node = self._checkStringVariable("remote_node", default=None)
614 4c98b915 Michael Hanselmann
    mode = self._checkStringVariable("mode", default=None)
615 4c98b915 Michael Hanselmann
    raw_disks = self._checkStringVariable("disks", default=None)
616 4c98b915 Michael Hanselmann
    iallocator = self._checkStringVariable("iallocator", default=None)
617 4c98b915 Michael Hanselmann
618 4c98b915 Michael Hanselmann
    if raw_disks:
619 4c98b915 Michael Hanselmann
      try:
620 4c98b915 Michael Hanselmann
        disks = [int(part) for part in raw_disks.split(",")]
621 4c98b915 Michael Hanselmann
      except ValueError, err:
622 4c98b915 Michael Hanselmann
        raise http.HttpBadRequest("Invalid disk index passed: %s" % str(err))
623 4c98b915 Michael Hanselmann
    else:
624 4c98b915 Michael Hanselmann
      disks = []
625 4c98b915 Michael Hanselmann
626 4c98b915 Michael Hanselmann
    op = opcodes.OpReplaceDisks(instance_name=instance_name,
627 4c98b915 Michael Hanselmann
                                remote_node=remote_node,
628 4c98b915 Michael Hanselmann
                                mode=mode,
629 4c98b915 Michael Hanselmann
                                disks=disks,
630 4c98b915 Michael Hanselmann
                                iallocator=iallocator)
631 4c98b915 Michael Hanselmann
632 4c98b915 Michael Hanselmann
    return baserlib.SubmitJob([op])
633 4c98b915 Michael Hanselmann
634 4c98b915 Michael Hanselmann
635 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
636 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
637 441e7cfd Oleksiy Mishchenko

638 c8e0a534 Iustin Pop
  Manages tags. When inheriting this class you must define the
639 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
640 441e7cfd Oleksiy Mishchenko

641 441e7cfd Oleksiy Mishchenko
  """
642 7a6b9510 Iustin Pop
  TAG_LEVEL = None
643 18cb43a2 Oleksiy Mishchenko
644 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
645 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
646 18cb43a2 Oleksiy Mishchenko

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

649 18cb43a2 Oleksiy Mishchenko
    """
650 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
651 18cb43a2 Oleksiy Mishchenko
652 18cb43a2 Oleksiy Mishchenko
    if self.TAG_LEVEL != constants.TAG_CLUSTER:
653 18cb43a2 Oleksiy Mishchenko
      self.name = items[0]
654 18cb43a2 Oleksiy Mishchenko
    else:
655 18cb43a2 Oleksiy Mishchenko
      self.name = ""
656 441e7cfd Oleksiy Mishchenko
657 441e7cfd Oleksiy Mishchenko
  def GET(self):
658 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
659 441e7cfd Oleksiy Mishchenko

660 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
661 441e7cfd Oleksiy Mishchenko

662 441e7cfd Oleksiy Mishchenko
    """
663 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
664 441e7cfd Oleksiy Mishchenko
665 21f04e5e Oleksiy Mishchenko
  def PUT(self):
666 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
667 441e7cfd Oleksiy Mishchenko

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

671 441e7cfd Oleksiy Mishchenko
    """
672 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
673 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
674 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
675 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
676 6f59b964 Iustin Pop
                              self.queryargs['tag'], name=self.name,
677 6f59b964 Iustin Pop
                              dry_run=bool(self.dryRun()))
678 15fd9fd5 Oleksiy Mishchenko
679 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
680 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
681 15fd9fd5 Oleksiy Mishchenko

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

686 15fd9fd5 Oleksiy Mishchenko
    """
687 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
688 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
689 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
690 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
691 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
692 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
693 6f59b964 Iustin Pop
                                 name=self.name,
694 6f59b964 Iustin Pop
                                 dry_run=bool(self.dryRun()))
695 18cb43a2 Oleksiy Mishchenko
696 18cb43a2 Oleksiy Mishchenko
697 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
698 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
699 18cb43a2 Oleksiy Mishchenko

700 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
701 18cb43a2 Oleksiy Mishchenko

702 18cb43a2 Oleksiy Mishchenko
  """
703 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
704 18cb43a2 Oleksiy Mishchenko
705 18cb43a2 Oleksiy Mishchenko
706 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
707 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
708 18cb43a2 Oleksiy Mishchenko

709 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
710 18cb43a2 Oleksiy Mishchenko

711 18cb43a2 Oleksiy Mishchenko
  """
712 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
713 18cb43a2 Oleksiy Mishchenko
714 18cb43a2 Oleksiy Mishchenko
715 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
716 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
717 18cb43a2 Oleksiy Mishchenko

718 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
719 18cb43a2 Oleksiy Mishchenko

720 18cb43a2 Oleksiy Mishchenko
  """
721 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER