Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / rlib2.py @ d1908b41

History | View | Annotate | Download (14.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 10b207d4 Oleksiy Mishchenko
import ganeti.opcodes
27 15fd9fd5 Oleksiy Mishchenko
from ganeti import http
28 10b207d4 Oleksiy Mishchenko
from ganeti import luxi
29 15fd9fd5 Oleksiy Mishchenko
from ganeti import constants
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 9031ee8e Iustin Pop
            "nic.ips", "nic.macs", "nic.bridges",
37 024e157f Iustin Pop
            "disk.sizes", "disk_usage",
38 a5b9d725 Iustin Pop
            "beparams", "hvparams",
39 9031ee8e Iustin Pop
            "oper_state", "oper_ram", "status",
40 9031ee8e Iustin Pop
            "tags"]
41 9031ee8e Iustin Pop
42 0b2454b9 Iustin Pop
N_FIELDS = ["name", "offline", "master_candidate", "drained",
43 9031ee8e Iustin Pop
            "dtotal", "dfree",
44 4e5a68f8 Oleksiy Mishchenko
            "mtotal", "mnode", "mfree",
45 0105bad3 Iustin Pop
            "pinst_cnt", "sinst_cnt", "tags",
46 0105bad3 Iustin Pop
            "ctotal", "cnodes", "csockets",
47 0105bad3 Iustin Pop
            ]
48 4e5a68f8 Oleksiy Mishchenko
49 4e5a68f8 Oleksiy Mishchenko
50 4e5a68f8 Oleksiy Mishchenko
class R_version(baserlib.R_Generic):
51 4e5a68f8 Oleksiy Mishchenko
  """/version resource.
52 4e5a68f8 Oleksiy Mishchenko

53 4e5a68f8 Oleksiy Mishchenko
  This resource should be used to determine the remote API version and
54 4e5a68f8 Oleksiy Mishchenko
  to adapt clients accordingly.
55 4e5a68f8 Oleksiy Mishchenko

56 4e5a68f8 Oleksiy Mishchenko
  """
57 4e5a68f8 Oleksiy Mishchenko
  DOC_URI = "/version"
58 4e5a68f8 Oleksiy Mishchenko
59 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
60 4e5a68f8 Oleksiy Mishchenko
    """Returns the remote API version.
61 4e5a68f8 Oleksiy Mishchenko

62 4e5a68f8 Oleksiy Mishchenko
    """
63 4e5a68f8 Oleksiy Mishchenko
    return constants.RAPI_VERSION
64 4e5a68f8 Oleksiy Mishchenko
65 4e5a68f8 Oleksiy Mishchenko
66 4e5a68f8 Oleksiy Mishchenko
class R_2_info(baserlib.R_Generic):
67 4e5a68f8 Oleksiy Mishchenko
  """Cluster info.
68 4e5a68f8 Oleksiy Mishchenko

69 4e5a68f8 Oleksiy Mishchenko
  """
70 4e5a68f8 Oleksiy Mishchenko
  DOC_URI = "/2/info"
71 4e5a68f8 Oleksiy Mishchenko
72 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
73 4e5a68f8 Oleksiy Mishchenko
    """Returns cluster information.
74 4e5a68f8 Oleksiy Mishchenko

75 4e5a68f8 Oleksiy Mishchenko
    Example::
76 4e5a68f8 Oleksiy Mishchenko

77 bf4a90af Iustin Pop
    {
78 bf4a90af Iustin Pop
      "config_version": 2000000,
79 bf4a90af Iustin Pop
      "name": "cluster",
80 74aa2478 Iustin Pop
      "software_version": "2.0.0~beta2",
81 bf4a90af Iustin Pop
      "os_api_version": 10,
82 bf4a90af Iustin Pop
      "export_version": 0,
83 bf4a90af Iustin Pop
      "candidate_pool_size": 10,
84 bf4a90af Iustin Pop
      "enabled_hypervisors": [
85 bf4a90af Iustin Pop
        "fake"
86 bf4a90af Iustin Pop
      ],
87 bf4a90af Iustin Pop
      "hvparams": {
88 bf4a90af Iustin Pop
        "fake": {}
89 bf4a90af Iustin Pop
       },
90 bf4a90af Iustin Pop
      "default_hypervisor": "fake",
91 bf4a90af Iustin Pop
      "master": "node1.example.com",
92 bf4a90af Iustin Pop
      "architecture": [
93 bf4a90af Iustin Pop
        "64bit",
94 bf4a90af Iustin Pop
        "x86_64"
95 bf4a90af Iustin Pop
      ],
96 bf4a90af Iustin Pop
      "protocol_version": 20,
97 bf4a90af Iustin Pop
      "beparams": {
98 bf4a90af Iustin Pop
        "default": {
99 bf4a90af Iustin Pop
          "auto_balance": true,
100 bf4a90af Iustin Pop
          "vcpus": 1,
101 bf4a90af Iustin Pop
          "memory": 128
102 bf4a90af Iustin Pop
         }
103 bf4a90af Iustin Pop
        }
104 4e5a68f8 Oleksiy Mishchenko
      }
105 4e5a68f8 Oleksiy Mishchenko

106 4e5a68f8 Oleksiy Mishchenko
    """
107 9031ee8e Iustin Pop
    client = luxi.Client()
108 9031ee8e Iustin Pop
    return client.QueryClusterInfo()
109 4e5a68f8 Oleksiy Mishchenko
110 4e5a68f8 Oleksiy Mishchenko
111 4e5a68f8 Oleksiy Mishchenko
class R_2_os(baserlib.R_Generic):
112 4e5a68f8 Oleksiy Mishchenko
  """/2/os resource.
113 4e5a68f8 Oleksiy Mishchenko

114 4e5a68f8 Oleksiy Mishchenko
  """
115 4e5a68f8 Oleksiy Mishchenko
  DOC_URI = "/2/os"
116 4e5a68f8 Oleksiy Mishchenko
117 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
118 4e5a68f8 Oleksiy Mishchenko
    """Return a list of all OSes.
119 4e5a68f8 Oleksiy Mishchenko

120 4e5a68f8 Oleksiy Mishchenko
    Can return error 500 in case of a problem.
121 4e5a68f8 Oleksiy Mishchenko

122 4e5a68f8 Oleksiy Mishchenko
    Example: ["debian-etch"]
123 4e5a68f8 Oleksiy Mishchenko

124 4e5a68f8 Oleksiy Mishchenko
    """
125 4e5a68f8 Oleksiy Mishchenko
    op = ganeti.opcodes.OpDiagnoseOS(output_fields=["name", "valid"],
126 4e5a68f8 Oleksiy Mishchenko
                                     names=[])
127 4e5a68f8 Oleksiy Mishchenko
    diagnose_data = ganeti.cli.SubmitOpCode(op)
128 4e5a68f8 Oleksiy Mishchenko
129 4e5a68f8 Oleksiy Mishchenko
    if not isinstance(diagnose_data, list):
130 4e5a68f8 Oleksiy Mishchenko
      raise http.HttpInternalServerError(message="Can't get OS list")
131 4e5a68f8 Oleksiy Mishchenko
132 4e5a68f8 Oleksiy Mishchenko
    return [row[0] for row in diagnose_data if row[1]]
133 51ee2f49 Oleksiy Mishchenko
134 10b207d4 Oleksiy Mishchenko
135 10b207d4 Oleksiy Mishchenko
class R_2_jobs(baserlib.R_Generic):
136 10b207d4 Oleksiy Mishchenko
  """/2/jobs resource.
137 10b207d4 Oleksiy Mishchenko

138 10b207d4 Oleksiy Mishchenko
  """
139 10b207d4 Oleksiy Mishchenko
  DOC_URI = "/2/jobs"
140 10b207d4 Oleksiy Mishchenko
141 10b207d4 Oleksiy Mishchenko
  def GET(self):
142 10b207d4 Oleksiy Mishchenko
    """Returns a dictionary of jobs.
143 10b207d4 Oleksiy Mishchenko

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

146 10b207d4 Oleksiy Mishchenko
    """
147 10b207d4 Oleksiy Mishchenko
    fields = ["id"]
148 10b207d4 Oleksiy Mishchenko
    # Convert the list of lists to the list of ids
149 10b207d4 Oleksiy Mishchenko
    result = [job_id for [job_id] in luxi.Client().QueryJobs(None, fields)]
150 9031ee8e Iustin Pop
    return baserlib.BuildUriList(result, "/2/jobs/%s",
151 9031ee8e Iustin Pop
                                 uri_fields=("id", "uri"))
152 10b207d4 Oleksiy Mishchenko
153 10b207d4 Oleksiy Mishchenko
154 10b207d4 Oleksiy Mishchenko
class R_2_jobs_id(baserlib.R_Generic):
155 10b207d4 Oleksiy Mishchenko
  """/2/jobs/[job_id] resource.
156 10b207d4 Oleksiy Mishchenko

157 10b207d4 Oleksiy Mishchenko
  """
158 10b207d4 Oleksiy Mishchenko
  DOC_URI = "/2/jobs/[job_id]"
159 10b207d4 Oleksiy Mishchenko
160 10b207d4 Oleksiy Mishchenko
  def GET(self):
161 10b207d4 Oleksiy Mishchenko
    """Returns a job status.
162 10b207d4 Oleksiy Mishchenko

163 c41eea6e Iustin Pop
    @return: a dictionary with job parameters.
164 c41eea6e Iustin Pop
        The result includes:
165 c41eea6e Iustin Pop
            - id: job ID as a number
166 c41eea6e Iustin Pop
            - status: current job status as a string
167 c41eea6e Iustin Pop
            - ops: involved OpCodes as a list of dictionaries for each
168 c41eea6e Iustin Pop
              opcodes in the job
169 c41eea6e Iustin Pop
            - opstatus: OpCodes status as a list
170 c41eea6e Iustin Pop
            - opresult: OpCodes results as a list of lists
171 38206f3c Iustin Pop

172 10b207d4 Oleksiy Mishchenko
    """
173 ee69c97f Iustin Pop
    fields = ["id", "ops", "status", "summary",
174 ee69c97f Iustin Pop
              "opstatus", "opresult", "oplog",
175 ee69c97f Iustin Pop
              "received_ts", "start_ts", "end_ts",
176 ee69c97f Iustin Pop
              ]
177 10b207d4 Oleksiy Mishchenko
    job_id = self.items[0]
178 38206f3c Iustin Pop
    result = luxi.Client().QueryJobs([job_id, ], fields)[0]
179 ee69c97f Iustin Pop
    if result is None:
180 ee69c97f Iustin Pop
      raise http.HttpNotFound()
181 10b207d4 Oleksiy Mishchenko
    return baserlib.MapFields(fields, result)
182 10b207d4 Oleksiy Mishchenko
183 c7f5f338 Oleksiy Mishchenko
  def DELETE(self):
184 c7f5f338 Oleksiy Mishchenko
    """Cancel not-yet-started job.
185 c7f5f338 Oleksiy Mishchenko

186 c7f5f338 Oleksiy Mishchenko
    """
187 c7f5f338 Oleksiy Mishchenko
    job_id = self.items[0]
188 c7f5f338 Oleksiy Mishchenko
    result = luxi.Client().CancelJob(job_id)
189 c7f5f338 Oleksiy Mishchenko
    return result
190 c7f5f338 Oleksiy Mishchenko
191 10b207d4 Oleksiy Mishchenko
192 10b207d4 Oleksiy Mishchenko
class R_2_nodes(baserlib.R_Generic):
193 10b207d4 Oleksiy Mishchenko
  """/2/nodes resource.
194 10b207d4 Oleksiy Mishchenko

195 10b207d4 Oleksiy Mishchenko
  """
196 10b207d4 Oleksiy Mishchenko
  DOC_URI = "/2/nodes"
197 38206f3c Iustin Pop
198 10b207d4 Oleksiy Mishchenko
  def GET(self):
199 10b207d4 Oleksiy Mishchenko
    """Returns a list of all nodes.
200 38206f3c Iustin Pop

201 c41eea6e Iustin Pop
    Example::
202 10b207d4 Oleksiy Mishchenko

203 c41eea6e Iustin Pop
      [
204 10b207d4 Oleksiy Mishchenko
        {
205 10b207d4 Oleksiy Mishchenko
          "id": "node1.example.com",
206 10b207d4 Oleksiy Mishchenko
          "uri": "\/instances\/node1.example.com"
207 10b207d4 Oleksiy Mishchenko
        },
208 10b207d4 Oleksiy Mishchenko
        {
209 10b207d4 Oleksiy Mishchenko
          "id": "node2.example.com",
210 10b207d4 Oleksiy Mishchenko
          "uri": "\/instances\/node2.example.com"
211 c41eea6e Iustin Pop
        }
212 c41eea6e Iustin Pop
      ]
213 10b207d4 Oleksiy Mishchenko

214 38206f3c Iustin Pop
    If the optional 'bulk' argument is provided and set to 'true'
215 10b207d4 Oleksiy Mishchenko
    value (i.e '?bulk=1'), the output contains detailed
216 10b207d4 Oleksiy Mishchenko
    information about nodes as a list.
217 10b207d4 Oleksiy Mishchenko

218 c41eea6e Iustin Pop
    Example::
219 c41eea6e Iustin Pop

220 c41eea6e Iustin Pop
      [
221 10b207d4 Oleksiy Mishchenko
        {
222 10b207d4 Oleksiy Mishchenko
          "pinst_cnt": 1,
223 10b207d4 Oleksiy Mishchenko
          "mfree": 31280,
224 10b207d4 Oleksiy Mishchenko
          "mtotal": 32763,
225 10b207d4 Oleksiy Mishchenko
          "name": "www.example.com",
226 10b207d4 Oleksiy Mishchenko
          "tags": [],
227 10b207d4 Oleksiy Mishchenko
          "mnode": 512,
228 10b207d4 Oleksiy Mishchenko
          "dtotal": 5246208,
229 10b207d4 Oleksiy Mishchenko
          "sinst_cnt": 2,
230 9031ee8e Iustin Pop
          "dfree": 5171712,
231 9031ee8e Iustin Pop
          "offline": false
232 10b207d4 Oleksiy Mishchenko
        },
233 10b207d4 Oleksiy Mishchenko
        ...
234 c41eea6e Iustin Pop
      ]
235 c41eea6e Iustin Pop

236 c41eea6e Iustin Pop
    @return: a dictionary with 'name' and 'uri' keys for each of them
237 10b207d4 Oleksiy Mishchenko

238 10b207d4 Oleksiy Mishchenko
    """
239 a0dcf7c2 Oleksiy Mishchenko
    client = luxi.Client()
240 38206f3c Iustin Pop
241 3d103742 Iustin Pop
    if self.useBulk():
242 9031ee8e Iustin Pop
      bulkdata = client.QueryNodes([], N_FIELDS, False)
243 a0dcf7c2 Oleksiy Mishchenko
      return baserlib.MapBulkFields(bulkdata, N_FIELDS)
244 9031ee8e Iustin Pop
    else:
245 9031ee8e Iustin Pop
      nodesdata = client.QueryNodes([], ["name"], False)
246 9031ee8e Iustin Pop
      nodeslist = [row[0] for row in nodesdata]
247 9031ee8e Iustin Pop
      return baserlib.BuildUriList(nodeslist, "/2/nodes/%s",
248 9031ee8e Iustin Pop
                                   uri_fields=("id", "uri"))
249 441e7cfd Oleksiy Mishchenko
250 441e7cfd Oleksiy Mishchenko
251 4e5a68f8 Oleksiy Mishchenko
class R_2_nodes_name(baserlib.R_Generic):
252 4e5a68f8 Oleksiy Mishchenko
  """/2/nodes/[node_name] resources.
253 028c6b76 Oleksiy Mishchenko

254 028c6b76 Oleksiy Mishchenko
  """
255 4e5a68f8 Oleksiy Mishchenko
  DOC_URI = "/nodes/[node_name]"
256 4e5a68f8 Oleksiy Mishchenko
257 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
258 4e5a68f8 Oleksiy Mishchenko
    """Send information about a node.
259 4e5a68f8 Oleksiy Mishchenko

260 4e5a68f8 Oleksiy Mishchenko
    """
261 4e5a68f8 Oleksiy Mishchenko
    node_name = self.items[0]
262 9031ee8e Iustin Pop
    client = luxi.Client()
263 9031ee8e Iustin Pop
    result = client.QueryNodes(names=[node_name], fields=N_FIELDS,
264 3d103742 Iustin Pop
                               use_locking=self.useLocking())
265 4e5a68f8 Oleksiy Mishchenko
266 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(N_FIELDS, result[0])
267 028c6b76 Oleksiy Mishchenko
268 028c6b76 Oleksiy Mishchenko
269 441e7cfd Oleksiy Mishchenko
class R_2_instances(baserlib.R_Generic):
270 441e7cfd Oleksiy Mishchenko
  """/2/instances resource.
271 441e7cfd Oleksiy Mishchenko

272 441e7cfd Oleksiy Mishchenko
  """
273 441e7cfd Oleksiy Mishchenko
  DOC_URI = "/2/instances"
274 441e7cfd Oleksiy Mishchenko
275 441e7cfd Oleksiy Mishchenko
  def GET(self):
276 441e7cfd Oleksiy Mishchenko
    """Returns a list of all available instances.
277 441e7cfd Oleksiy Mishchenko

278 441e7cfd Oleksiy Mishchenko

279 c41eea6e Iustin Pop
    Example::
280 c41eea6e Iustin Pop

281 c41eea6e Iustin Pop
      [
282 441e7cfd Oleksiy Mishchenko
        {
283 441e7cfd Oleksiy Mishchenko
          "name": "web.example.com",
284 441e7cfd Oleksiy Mishchenko
          "uri": "\/instances\/web.example.com"
285 441e7cfd Oleksiy Mishchenko
        },
286 441e7cfd Oleksiy Mishchenko
        {
287 441e7cfd Oleksiy Mishchenko
          "name": "mail.example.com",
288 441e7cfd Oleksiy Mishchenko
          "uri": "\/instances\/mail.example.com"
289 c41eea6e Iustin Pop
        }
290 c41eea6e Iustin Pop
      ]
291 441e7cfd Oleksiy Mishchenko

292 441e7cfd Oleksiy Mishchenko
    If the optional 'bulk' argument is provided and set to 'true'
293 441e7cfd Oleksiy Mishchenko
    value (i.e '?bulk=1'), the output contains detailed
294 441e7cfd Oleksiy Mishchenko
    information about instances as a list.
295 441e7cfd Oleksiy Mishchenko

296 c41eea6e Iustin Pop
    Example::
297 c41eea6e Iustin Pop

298 c41eea6e Iustin Pop
      [
299 441e7cfd Oleksiy Mishchenko
        {
300 441e7cfd Oleksiy Mishchenko
           "status": "running",
301 bf4a90af Iustin Pop
           "disk_usage": 20480,
302 bf4a90af Iustin Pop
           "nic.bridges": [
303 bf4a90af Iustin Pop
             "xen-br0"
304 bf4a90af Iustin Pop
            ],
305 441e7cfd Oleksiy Mishchenko
           "name": "web.example.com",
306 441e7cfd Oleksiy Mishchenko
           "tags": ["tag1", "tag2"],
307 bf4a90af Iustin Pop
           "beparams": {
308 bf4a90af Iustin Pop
             "vcpus": 2,
309 bf4a90af Iustin Pop
             "memory": 512
310 bf4a90af Iustin Pop
           },
311 bf4a90af Iustin Pop
           "disk.sizes": [
312 bf4a90af Iustin Pop
               20480
313 bf4a90af Iustin Pop
           ],
314 441e7cfd Oleksiy Mishchenko
           "pnode": "node1.example.com",
315 bf4a90af Iustin Pop
           "nic.macs": ["01:23:45:67:89:01"],
316 441e7cfd Oleksiy Mishchenko
           "snodes": ["node2.example.com"],
317 441e7cfd Oleksiy Mishchenko
           "disk_template": "drbd",
318 441e7cfd Oleksiy Mishchenko
           "admin_state": true,
319 441e7cfd Oleksiy Mishchenko
           "os": "debian-etch",
320 441e7cfd Oleksiy Mishchenko
           "oper_state": true
321 441e7cfd Oleksiy Mishchenko
        },
322 441e7cfd Oleksiy Mishchenko
        ...
323 c41eea6e Iustin Pop
      ]
324 c41eea6e Iustin Pop

325 5fcc718f Iustin Pop
    @return: a dictionary with 'name' and 'uri' keys for each of them.
326 441e7cfd Oleksiy Mishchenko

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

343 5fcc718f Iustin Pop
    @return: a job id
344 2f7635f4 Oleksiy Mishchenko

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

397 028c6b76 Oleksiy Mishchenko
  """
398 4e5a68f8 Oleksiy Mishchenko
  DOC_URI = "/2/instances/[instance_name]"
399 4e5a68f8 Oleksiy Mishchenko
400 4e5a68f8 Oleksiy Mishchenko
  def GET(self):
401 4e5a68f8 Oleksiy Mishchenko
    """Send information about an instance.
402 4e5a68f8 Oleksiy Mishchenko

403 4e5a68f8 Oleksiy Mishchenko
    """
404 9031ee8e Iustin Pop
    client = luxi.Client()
405 4e5a68f8 Oleksiy Mishchenko
    instance_name = self.items[0]
406 9031ee8e Iustin Pop
    result = client.QueryInstances(names=[instance_name], fields=I_FIELDS,
407 3d103742 Iustin Pop
                                   use_locking=self.useLocking())
408 4e5a68f8 Oleksiy Mishchenko
409 4e5a68f8 Oleksiy Mishchenko
    return baserlib.MapFields(I_FIELDS, result[0])
410 028c6b76 Oleksiy Mishchenko
411 6e99c5a0 Iustin Pop
  def DELETE(self):
412 6e99c5a0 Iustin Pop
    """Delete an instance.
413 6e99c5a0 Iustin Pop

414 6e99c5a0 Iustin Pop
    """
415 6e99c5a0 Iustin Pop
    op = ganeti.opcodes.OpRemoveInstance(instance_name=self.items[0],
416 6e99c5a0 Iustin Pop
                                         ignore_failures=False)
417 6e99c5a0 Iustin Pop
    job_id = ganeti.cli.SendJob([op])
418 6e99c5a0 Iustin Pop
    return job_id
419 6e99c5a0 Iustin Pop
420 028c6b76 Oleksiy Mishchenko
421 2276aa29 Oleksiy Mishchenko
class R_2_instances_name_reboot(baserlib.R_Generic):
422 2276aa29 Oleksiy Mishchenko
  """/2/instances/[instance_name]/reboot resource.
423 2276aa29 Oleksiy Mishchenko

424 2276aa29 Oleksiy Mishchenko
  Implements an instance reboot.
425 2276aa29 Oleksiy Mishchenko

426 2276aa29 Oleksiy Mishchenko
  """
427 2276aa29 Oleksiy Mishchenko
428 2276aa29 Oleksiy Mishchenko
  DOC_URI = "/2/instances/[instance_name]/reboot"
429 2276aa29 Oleksiy Mishchenko
430 21f04e5e Oleksiy Mishchenko
  def POST(self):
431 2276aa29 Oleksiy Mishchenko
    """Reboot an instance.
432 2276aa29 Oleksiy Mishchenko

433 0c55c24b Oleksiy Mishchenko
    The URI takes type=[hard|soft|full] and
434 0c55c24b Oleksiy Mishchenko
    ignore_secondaries=[False|True] parameters.
435 0c55c24b Oleksiy Mishchenko

436 2276aa29 Oleksiy Mishchenko
    """
437 2276aa29 Oleksiy Mishchenko
    instance_name = self.items[0]
438 0c55c24b Oleksiy Mishchenko
    reboot_type = self.queryargs.get('type',
439 0c55c24b Oleksiy Mishchenko
                                     [constants.INSTANCE_REBOOT_HARD])[0]
440 0c55c24b Oleksiy Mishchenko
    ignore_secondaries = bool(self.queryargs.get('ignore_secondaries',
441 0c55c24b Oleksiy Mishchenko
                                                 [False])[0])
442 2276aa29 Oleksiy Mishchenko
    op = ganeti.opcodes.OpRebootInstance(
443 2276aa29 Oleksiy Mishchenko
        instance_name=instance_name,
444 2276aa29 Oleksiy Mishchenko
        reboot_type=reboot_type,
445 2276aa29 Oleksiy Mishchenko
        ignore_secondaries=ignore_secondaries)
446 2276aa29 Oleksiy Mishchenko
447 2276aa29 Oleksiy Mishchenko
    job_id = ganeti.cli.SendJob([op])
448 2276aa29 Oleksiy Mishchenko
449 2276aa29 Oleksiy Mishchenko
    return job_id
450 2276aa29 Oleksiy Mishchenko
451 2276aa29 Oleksiy Mishchenko
452 0c55c24b Oleksiy Mishchenko
class R_2_instances_name_startup(baserlib.R_Generic):
453 0c55c24b Oleksiy Mishchenko
  """/2/instances/[instance_name]/startup resource.
454 0c55c24b Oleksiy Mishchenko

455 0c55c24b Oleksiy Mishchenko
  Implements an instance startup.
456 0c55c24b Oleksiy Mishchenko

457 0c55c24b Oleksiy Mishchenko
  """
458 0c55c24b Oleksiy Mishchenko
459 0c55c24b Oleksiy Mishchenko
  DOC_URI = "/2/instances/[instance_name]/startup"
460 0c55c24b Oleksiy Mishchenko
461 21f04e5e Oleksiy Mishchenko
  def PUT(self):
462 0c55c24b Oleksiy Mishchenko
    """Startup an instance.
463 0c55c24b Oleksiy Mishchenko

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

467 0c55c24b Oleksiy Mishchenko
    """
468 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
469 0c55c24b Oleksiy Mishchenko
    force_startup = bool(self.queryargs.get('force', [False])[0])
470 0c55c24b Oleksiy Mishchenko
    op = ganeti.opcodes.OpStartupInstance(instance_name=instance_name,
471 0c55c24b Oleksiy Mishchenko
                                          force=force_startup)
472 0c55c24b Oleksiy Mishchenko
473 0c55c24b Oleksiy Mishchenko
    job_id = ganeti.cli.SendJob([op])
474 0c55c24b Oleksiy Mishchenko
475 0c55c24b Oleksiy Mishchenko
    return job_id
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 0c55c24b Oleksiy Mishchenko
485 0c55c24b Oleksiy Mishchenko
  DOC_URI = "/2/instances/[instance_name]/shutdown"
486 0c55c24b Oleksiy Mishchenko
487 21f04e5e Oleksiy Mishchenko
  def PUT(self):
488 0c55c24b Oleksiy Mishchenko
    """Shutdown an instance.
489 0c55c24b Oleksiy Mishchenko

490 0c55c24b Oleksiy Mishchenko
    """
491 0c55c24b Oleksiy Mishchenko
    instance_name = self.items[0]
492 0c55c24b Oleksiy Mishchenko
    op = ganeti.opcodes.OpShutdownInstance(instance_name=instance_name)
493 0c55c24b Oleksiy Mishchenko
494 0c55c24b Oleksiy Mishchenko
    job_id = ganeti.cli.SendJob([op])
495 0c55c24b Oleksiy Mishchenko
496 0c55c24b Oleksiy Mishchenko
    return job_id
497 0c55c24b Oleksiy Mishchenko
498 0c55c24b Oleksiy Mishchenko
499 18cb43a2 Oleksiy Mishchenko
class _R_Tags(baserlib.R_Generic):
500 18cb43a2 Oleksiy Mishchenko
  """ Quasiclass for tagging resources
501 441e7cfd Oleksiy Mishchenko

502 18cb43a2 Oleksiy Mishchenko
  Manages tags. Inheriting this class you suppose to define DOC_URI and
503 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL for it.
504 441e7cfd Oleksiy Mishchenko

505 441e7cfd Oleksiy Mishchenko
  """
506 7a6b9510 Iustin Pop
  TAG_LEVEL = None
507 18cb43a2 Oleksiy Mishchenko
508 18cb43a2 Oleksiy Mishchenko
  def __init__(self, items, queryargs, req):
509 18cb43a2 Oleksiy Mishchenko
    """A tag resource constructor.
510 18cb43a2 Oleksiy Mishchenko

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

513 18cb43a2 Oleksiy Mishchenko
    """
514 18cb43a2 Oleksiy Mishchenko
    baserlib.R_Generic.__init__(self, items, queryargs, req)
515 18cb43a2 Oleksiy Mishchenko
516 18cb43a2 Oleksiy Mishchenko
    if self.TAG_LEVEL != constants.TAG_CLUSTER:
517 18cb43a2 Oleksiy Mishchenko
      self.name = items[0]
518 18cb43a2 Oleksiy Mishchenko
    else:
519 18cb43a2 Oleksiy Mishchenko
      self.name = ""
520 441e7cfd Oleksiy Mishchenko
521 441e7cfd Oleksiy Mishchenko
  def GET(self):
522 18cb43a2 Oleksiy Mishchenko
    """Returns a list of tags.
523 441e7cfd Oleksiy Mishchenko

524 441e7cfd Oleksiy Mishchenko
    Example: ["tag1", "tag2", "tag3"]
525 441e7cfd Oleksiy Mishchenko

526 441e7cfd Oleksiy Mishchenko
    """
527 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_GET(self.TAG_LEVEL, name=self.name)
528 441e7cfd Oleksiy Mishchenko
529 21f04e5e Oleksiy Mishchenko
  def PUT(self):
530 18cb43a2 Oleksiy Mishchenko
    """Add a set of tags.
531 441e7cfd Oleksiy Mishchenko

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

535 441e7cfd Oleksiy Mishchenko
    """
536 6e99c5a0 Iustin Pop
    if 'tag' not in self.queryargs:
537 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Please specify tag(s) to add using the"
538 6e99c5a0 Iustin Pop
                                " the 'tag' parameter")
539 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_PUT(self.TAG_LEVEL,
540 6e99c5a0 Iustin Pop
                              self.queryargs['tag'], name=self.name)
541 15fd9fd5 Oleksiy Mishchenko
542 15fd9fd5 Oleksiy Mishchenko
  def DELETE(self):
543 15fd9fd5 Oleksiy Mishchenko
    """Delete a tag.
544 15fd9fd5 Oleksiy Mishchenko

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

549 15fd9fd5 Oleksiy Mishchenko
    """
550 15fd9fd5 Oleksiy Mishchenko
    if 'tag' not in self.queryargs:
551 18cb43a2 Oleksiy Mishchenko
      # no we not gonna delete all tags
552 6e99c5a0 Iustin Pop
      raise http.HttpBadRequest("Cannot delete all tags - please specify"
553 6e99c5a0 Iustin Pop
                                " tag(s) using the 'tag' parameter")
554 18cb43a2 Oleksiy Mishchenko
    return baserlib._Tags_DELETE(self.TAG_LEVEL,
555 15fd9fd5 Oleksiy Mishchenko
                                 self.queryargs['tag'],
556 18cb43a2 Oleksiy Mishchenko
                                 name=self.name)
557 18cb43a2 Oleksiy Mishchenko
558 18cb43a2 Oleksiy Mishchenko
559 18cb43a2 Oleksiy Mishchenko
class R_2_instances_name_tags(_R_Tags):
560 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/[instance_name]/tags resource.
561 18cb43a2 Oleksiy Mishchenko

562 18cb43a2 Oleksiy Mishchenko
  Manages per-instance tags.
563 18cb43a2 Oleksiy Mishchenko

564 18cb43a2 Oleksiy Mishchenko
  """
565 18cb43a2 Oleksiy Mishchenko
  DOC_URI = "/2/instances/[instance_name]/tags"
566 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_INSTANCE
567 18cb43a2 Oleksiy Mishchenko
568 18cb43a2 Oleksiy Mishchenko
569 18cb43a2 Oleksiy Mishchenko
class R_2_nodes_name_tags(_R_Tags):
570 18cb43a2 Oleksiy Mishchenko
  """ /2/nodes/[node_name]/tags resource.
571 18cb43a2 Oleksiy Mishchenko

572 18cb43a2 Oleksiy Mishchenko
  Manages per-node tags.
573 18cb43a2 Oleksiy Mishchenko

574 18cb43a2 Oleksiy Mishchenko
  """
575 18cb43a2 Oleksiy Mishchenko
  DOC_URI = "/2/nodes/[node_name]/tags"
576 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_NODE
577 18cb43a2 Oleksiy Mishchenko
578 18cb43a2 Oleksiy Mishchenko
579 18cb43a2 Oleksiy Mishchenko
class R_2_tags(_R_Tags):
580 18cb43a2 Oleksiy Mishchenko
  """ /2/instances/tags resource.
581 18cb43a2 Oleksiy Mishchenko

582 18cb43a2 Oleksiy Mishchenko
  Manages cluster tags.
583 18cb43a2 Oleksiy Mishchenko

584 18cb43a2 Oleksiy Mishchenko
  """
585 18cb43a2 Oleksiy Mishchenko
  DOC_URI = "/2/tags"
586 18cb43a2 Oleksiy Mishchenko
  TAG_LEVEL = constants.TAG_CLUSTER