Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ 984f7c32

History | View | Annotate | Download (16.8 kB)

1 a8083063 Iustin Pop
#!/usr/bin/python
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Ganeti node daemon"""
23 a8083063 Iustin Pop
24 3ecf6786 Iustin Pop
# functions in this module need to have a given name structure, so:
25 3ecf6786 Iustin Pop
# pylint: disable-msg=C0103
26 3ecf6786 Iustin Pop
27 a8083063 Iustin Pop
import os
28 a8083063 Iustin Pop
import sys
29 a8083063 Iustin Pop
import traceback
30 81010134 Iustin Pop
import BaseHTTPServer
31 81010134 Iustin Pop
import simplejson
32 0214b0c0 Iustin Pop
import errno
33 a8083063 Iustin Pop
34 a8083063 Iustin Pop
from optparse import OptionParser
35 a8083063 Iustin Pop
36 a8083063 Iustin Pop
37 a8083063 Iustin Pop
from ganeti import backend
38 a8083063 Iustin Pop
from ganeti import logger
39 a8083063 Iustin Pop
from ganeti import constants
40 a8083063 Iustin Pop
from ganeti import objects
41 a8083063 Iustin Pop
from ganeti import errors
42 a8083063 Iustin Pop
from ganeti import ssconf
43 16abfbc2 Alexander Schreiber
from ganeti import utils
44 a8083063 Iustin Pop
45 a8083063 Iustin Pop
46 81010134 Iustin Pop
class ServerObject(BaseHTTPServer.BaseHTTPRequestHandler):
47 3ecf6786 Iustin Pop
  """The server implementation.
48 3ecf6786 Iustin Pop
49 3ecf6786 Iustin Pop
  This class holds all methods exposed over the RPC interface.
50 3ecf6786 Iustin Pop
51 3ecf6786 Iustin Pop
  """
52 81010134 Iustin Pop
  def do_PUT(self):
53 81010134 Iustin Pop
    """Handle a post request.
54 a8083063 Iustin Pop
55 098c0958 Michael Hanselmann
    """
56 81010134 Iustin Pop
    path = self.path
57 81010134 Iustin Pop
    if path.startswith("/"):
58 81010134 Iustin Pop
      path = path[1:]
59 81010134 Iustin Pop
    mname = "perspective_%s" % path
60 81010134 Iustin Pop
    if not hasattr(self, mname):
61 81010134 Iustin Pop
      self.send_error(404)
62 81010134 Iustin Pop
      return False
63 81010134 Iustin Pop
64 81010134 Iustin Pop
    method = getattr(self, mname)
65 a8083063 Iustin Pop
    try:
66 81010134 Iustin Pop
      body_length = int(self.headers.get('Content-Length', '0'))
67 81010134 Iustin Pop
    except ValueError:
68 81010134 Iustin Pop
      self.send_error(400, 'No Content-Length header or invalid format')
69 81010134 Iustin Pop
      return False
70 a8083063 Iustin Pop
71 81010134 Iustin Pop
    try:
72 81010134 Iustin Pop
      body = self.rfile.read(body_length)
73 81010134 Iustin Pop
    except socket.error, err:
74 81010134 Iustin Pop
      logger.Error("Socket error while reading: %s" % str(err))
75 81010134 Iustin Pop
      return
76 81010134 Iustin Pop
    try:
77 81010134 Iustin Pop
      params = simplejson.loads(body)
78 81010134 Iustin Pop
      result = method(params)
79 81010134 Iustin Pop
      payload = simplejson.dumps(result)
80 9ae49f27 Guido Trotter
    except errors.QuitGanetiException, err:
81 9ae49f27 Guido Trotter
      global _EXIT_GANETI_NODED
82 9ae49f27 Guido Trotter
      _EXIT_GANETI_NODED = True
83 c3d7f69b Guido Trotter
      if isinstance(err.args, tuple) and len(err.args) == 2:
84 c3d7f69b Guido Trotter
        if err.args[0]:
85 9ae49f27 Guido Trotter
          self.send_error(500, "Error: %s" % str(err[1]))
86 9ae49f27 Guido Trotter
        else:
87 c3d7f69b Guido Trotter
          payload = simplejson.dumps(err.args[1])
88 9ae49f27 Guido Trotter
      else:
89 c3d7f69b Guido Trotter
        self.log_message('QuitGanetiException Usage Error')
90 9ae49f27 Guido Trotter
        self.send_error(500, "Error: %s" % str(err))
91 81010134 Iustin Pop
    except Exception, err:
92 81010134 Iustin Pop
      self.send_error(500, "Error: %s" % str(err))
93 81010134 Iustin Pop
      return False
94 81010134 Iustin Pop
    self.send_response(200)
95 81010134 Iustin Pop
    self.send_header('Content-Length', str(len(payload)))
96 81010134 Iustin Pop
    self.end_headers()
97 81010134 Iustin Pop
    self.wfile.write(payload)
98 81010134 Iustin Pop
    return True
99 81010134 Iustin Pop
100 81010134 Iustin Pop
  def log_message(self, format, *args):
101 81010134 Iustin Pop
    """Log a request to the log.
102 81010134 Iustin Pop
103 81010134 Iustin Pop
    This is the same as the parent, we just log somewhere else.
104 81010134 Iustin Pop
105 81010134 Iustin Pop
    """
106 6e12fa3c Iustin Pop
    msg = ("%s - - [%s] %s" %
107 81010134 Iustin Pop
           (self.address_string(),
108 81010134 Iustin Pop
            self.log_date_time_string(),
109 81010134 Iustin Pop
            format % args))
110 81010134 Iustin Pop
    logger.Debug(msg)
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
  # the new block devices  --------------------------
113 a8083063 Iustin Pop
114 3ecf6786 Iustin Pop
  @staticmethod
115 3ecf6786 Iustin Pop
  def perspective_blockdev_create(params):
116 3ecf6786 Iustin Pop
    """Create a block device.
117 3ecf6786 Iustin Pop
118 3ecf6786 Iustin Pop
    """
119 3f78eef2 Iustin Pop
    bdev_s, size, owner, on_primary, info = params
120 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
121 a8083063 Iustin Pop
    if bdev is None:
122 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
123 3f78eef2 Iustin Pop
    return backend.CreateBlockDevice(bdev, size, owner, on_primary, info)
124 a8083063 Iustin Pop
125 3ecf6786 Iustin Pop
  @staticmethod
126 3ecf6786 Iustin Pop
  def perspective_blockdev_remove(params):
127 3ecf6786 Iustin Pop
    """Remove a block device.
128 3ecf6786 Iustin Pop
129 3ecf6786 Iustin Pop
    """
130 a8083063 Iustin Pop
    bdev_s = params[0]
131 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
132 a8083063 Iustin Pop
    return backend.RemoveBlockDevice(bdev)
133 a8083063 Iustin Pop
134 3ecf6786 Iustin Pop
  @staticmethod
135 f3e513ad Iustin Pop
  def perspective_blockdev_rename(params):
136 f3e513ad Iustin Pop
    """Remove a block device.
137 f3e513ad Iustin Pop
138 f3e513ad Iustin Pop
    """
139 f3e513ad Iustin Pop
    devlist = [(objects.Disk.FromDict(ds), uid) for ds, uid in params]
140 f3e513ad Iustin Pop
    return backend.RenameBlockDevices(devlist)
141 f3e513ad Iustin Pop
142 f3e513ad Iustin Pop
  @staticmethod
143 3ecf6786 Iustin Pop
  def perspective_blockdev_assemble(params):
144 3ecf6786 Iustin Pop
    """Assemble a block device.
145 3ecf6786 Iustin Pop
146 3ecf6786 Iustin Pop
    """
147 3f78eef2 Iustin Pop
    bdev_s, owner, on_primary = params
148 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
149 a8083063 Iustin Pop
    if bdev is None:
150 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
151 3f78eef2 Iustin Pop
    return backend.AssembleBlockDevice(bdev, owner, on_primary)
152 a8083063 Iustin Pop
153 3ecf6786 Iustin Pop
  @staticmethod
154 3ecf6786 Iustin Pop
  def perspective_blockdev_shutdown(params):
155 3ecf6786 Iustin Pop
    """Shutdown a block device.
156 3ecf6786 Iustin Pop
157 3ecf6786 Iustin Pop
    """
158 a8083063 Iustin Pop
    bdev_s = params[0]
159 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
160 a8083063 Iustin Pop
    if bdev is None:
161 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
162 a8083063 Iustin Pop
    return backend.ShutdownBlockDevice(bdev)
163 a8083063 Iustin Pop
164 3ecf6786 Iustin Pop
  @staticmethod
165 153d9724 Iustin Pop
  def perspective_blockdev_addchildren(params):
166 3ecf6786 Iustin Pop
    """Add a child to a mirror device.
167 3ecf6786 Iustin Pop
168 3ecf6786 Iustin Pop
    Note: this is only valid for mirror devices. It's the caller's duty
169 3ecf6786 Iustin Pop
    to send a correct disk, otherwise we raise an error.
170 3ecf6786 Iustin Pop
171 3ecf6786 Iustin Pop
    """
172 a8083063 Iustin Pop
    bdev_s, ndev_s = params
173 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
174 153d9724 Iustin Pop
    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
175 153d9724 Iustin Pop
    if bdev is None or ndevs.count(None) > 0:
176 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
177 153d9724 Iustin Pop
    return backend.MirrorAddChildren(bdev, ndevs)
178 a8083063 Iustin Pop
179 3ecf6786 Iustin Pop
  @staticmethod
180 153d9724 Iustin Pop
  def perspective_blockdev_removechildren(params):
181 3ecf6786 Iustin Pop
    """Remove a child from a mirror device.
182 3ecf6786 Iustin Pop
183 3ecf6786 Iustin Pop
    This is only valid for mirror devices, of course. It's the callers
184 3ecf6786 Iustin Pop
    duty to send a correct disk, otherwise we raise an error.
185 3ecf6786 Iustin Pop
186 3ecf6786 Iustin Pop
    """
187 a8083063 Iustin Pop
    bdev_s, ndev_s = params
188 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
189 153d9724 Iustin Pop
    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
190 153d9724 Iustin Pop
    if bdev is None or ndevs.count(None) > 0:
191 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
192 153d9724 Iustin Pop
    return backend.MirrorRemoveChildren(bdev, ndevs)
193 a8083063 Iustin Pop
194 3ecf6786 Iustin Pop
  @staticmethod
195 3ecf6786 Iustin Pop
  def perspective_blockdev_getmirrorstatus(params):
196 3ecf6786 Iustin Pop
    """Return the mirror status for a list of disks.
197 3ecf6786 Iustin Pop
198 3ecf6786 Iustin Pop
    """
199 319856a9 Michael Hanselmann
    disks = [objects.Disk.FromDict(dsk_s)
200 a8083063 Iustin Pop
            for dsk_s in params]
201 a8083063 Iustin Pop
    return backend.GetMirrorStatus(disks)
202 a8083063 Iustin Pop
203 3ecf6786 Iustin Pop
  @staticmethod
204 3ecf6786 Iustin Pop
  def perspective_blockdev_find(params):
205 3ecf6786 Iustin Pop
    """Expose the FindBlockDevice functionality for a disk.
206 3ecf6786 Iustin Pop
207 3ecf6786 Iustin Pop
    This will try to find but not activate a disk.
208 3ecf6786 Iustin Pop
209 3ecf6786 Iustin Pop
    """
210 319856a9 Michael Hanselmann
    disk = objects.Disk.FromDict(params[0])
211 a8083063 Iustin Pop
    return backend.FindBlockDevice(disk)
212 a8083063 Iustin Pop
213 3ecf6786 Iustin Pop
  @staticmethod
214 3ecf6786 Iustin Pop
  def perspective_blockdev_snapshot(params):
215 3ecf6786 Iustin Pop
    """Create a snapshot device.
216 3ecf6786 Iustin Pop
217 3ecf6786 Iustin Pop
    Note that this is only valid for LVM disks, if we get passed
218 3ecf6786 Iustin Pop
    something else we raise an exception. The snapshot device can be
219 3ecf6786 Iustin Pop
    remove by calling the generic block device remove call.
220 3ecf6786 Iustin Pop
221 3ecf6786 Iustin Pop
    """
222 319856a9 Michael Hanselmann
    cfbd = objects.Disk.FromDict(params[0])
223 a8083063 Iustin Pop
    return backend.SnapshotBlockDevice(cfbd)
224 a8083063 Iustin Pop
225 4c8ba8b3 Iustin Pop
  @staticmethod
226 4c8ba8b3 Iustin Pop
  def perspective_blockdev_grow(params):
227 4c8ba8b3 Iustin Pop
    """Grow a stack of devices.
228 4c8ba8b3 Iustin Pop
229 4c8ba8b3 Iustin Pop
    """
230 4c8ba8b3 Iustin Pop
    cfbd = objects.Disk.FromDict(params[0])
231 4c8ba8b3 Iustin Pop
    amount = params[1]
232 4c8ba8b3 Iustin Pop
    return backend.GrowBlockDevice(cfbd, amount)
233 4c8ba8b3 Iustin Pop
234 d61cbe76 Iustin Pop
  @staticmethod
235 d61cbe76 Iustin Pop
  def perspective_blockdev_close(params):
236 d61cbe76 Iustin Pop
    """Closes the given block devices.
237 d61cbe76 Iustin Pop
238 d61cbe76 Iustin Pop
    """
239 d61cbe76 Iustin Pop
    disks = [objects.Disk.FromDict(cf) for cf in params]
240 d61cbe76 Iustin Pop
    return backend.CloseBlockDevices(disks)
241 d61cbe76 Iustin Pop
242 a8083063 Iustin Pop
  # export/import  --------------------------
243 a8083063 Iustin Pop
244 3ecf6786 Iustin Pop
  @staticmethod
245 3ecf6786 Iustin Pop
  def perspective_snapshot_export(params):
246 3ecf6786 Iustin Pop
    """Export a given snapshot.
247 3ecf6786 Iustin Pop
248 3ecf6786 Iustin Pop
    """
249 319856a9 Michael Hanselmann
    disk = objects.Disk.FromDict(params[0])
250 a8083063 Iustin Pop
    dest_node = params[1]
251 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[2])
252 3ecf6786 Iustin Pop
    return backend.ExportSnapshot(disk, dest_node, instance)
253 3ecf6786 Iustin Pop
254 3ecf6786 Iustin Pop
  @staticmethod
255 3ecf6786 Iustin Pop
  def perspective_finalize_export(params):
256 3ecf6786 Iustin Pop
    """Expose the finalize export functionality.
257 a8083063 Iustin Pop
258 3ecf6786 Iustin Pop
    """
259 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
260 319856a9 Michael Hanselmann
    snap_disks = [objects.Disk.FromDict(str_data)
261 a8083063 Iustin Pop
                  for str_data in params[1]]
262 a8083063 Iustin Pop
    return backend.FinalizeExport(instance, snap_disks)
263 a8083063 Iustin Pop
264 3ecf6786 Iustin Pop
  @staticmethod
265 3ecf6786 Iustin Pop
  def perspective_export_info(params):
266 3ecf6786 Iustin Pop
    """Query information about an existing export on this node.
267 3ecf6786 Iustin Pop
268 3ecf6786 Iustin Pop
    The given path may not contain an export, in which case we return
269 3ecf6786 Iustin Pop
    None.
270 3ecf6786 Iustin Pop
271 3ecf6786 Iustin Pop
    """
272 3ecf6786 Iustin Pop
    path = params[0]
273 3ecf6786 Iustin Pop
    einfo = backend.ExportInfo(path)
274 a8083063 Iustin Pop
    if einfo is None:
275 a8083063 Iustin Pop
      return einfo
276 a8083063 Iustin Pop
    return einfo.Dumps()
277 a8083063 Iustin Pop
278 3ecf6786 Iustin Pop
  @staticmethod
279 3ecf6786 Iustin Pop
  def perspective_export_list(params):
280 3ecf6786 Iustin Pop
    """List the available exports on this node.
281 3ecf6786 Iustin Pop
282 3ecf6786 Iustin Pop
    Note that as opposed to export_info, which may query data about an
283 3ecf6786 Iustin Pop
    export in any path, this only queries the standard Ganeti path
284 3ecf6786 Iustin Pop
    (constants.EXPORT_DIR).
285 3ecf6786 Iustin Pop
286 3ecf6786 Iustin Pop
    """
287 a8083063 Iustin Pop
    return backend.ListExports()
288 a8083063 Iustin Pop
289 3ecf6786 Iustin Pop
  @staticmethod
290 3ecf6786 Iustin Pop
  def perspective_export_remove(params):
291 3ecf6786 Iustin Pop
    """Remove an export.
292 3ecf6786 Iustin Pop
293 3ecf6786 Iustin Pop
    """
294 a8083063 Iustin Pop
    export = params[0]
295 a8083063 Iustin Pop
    return backend.RemoveExport(export)
296 a8083063 Iustin Pop
297 a8083063 Iustin Pop
  # volume  --------------------------
298 a8083063 Iustin Pop
299 3ecf6786 Iustin Pop
  @staticmethod
300 3ecf6786 Iustin Pop
  def perspective_volume_list(params):
301 3ecf6786 Iustin Pop
    """Query the list of logical volumes in a given volume group.
302 3ecf6786 Iustin Pop
303 3ecf6786 Iustin Pop
    """
304 a8083063 Iustin Pop
    vgname = params[0]
305 a8083063 Iustin Pop
    return backend.GetVolumeList(vgname)
306 a8083063 Iustin Pop
307 3ecf6786 Iustin Pop
  @staticmethod
308 3ecf6786 Iustin Pop
  def perspective_vg_list(params):
309 3ecf6786 Iustin Pop
    """Query the list of volume groups.
310 3ecf6786 Iustin Pop
311 3ecf6786 Iustin Pop
    """
312 a8083063 Iustin Pop
    return backend.ListVolumeGroups()
313 a8083063 Iustin Pop
314 a8083063 Iustin Pop
  # bridge  --------------------------
315 a8083063 Iustin Pop
316 3ecf6786 Iustin Pop
  @staticmethod
317 3ecf6786 Iustin Pop
  def perspective_bridges_exist(params):
318 3ecf6786 Iustin Pop
    """Check if all bridges given exist on this node.
319 3ecf6786 Iustin Pop
320 3ecf6786 Iustin Pop
    """
321 a8083063 Iustin Pop
    bridges_list = params[0]
322 a8083063 Iustin Pop
    return backend.BridgesExist(bridges_list)
323 a8083063 Iustin Pop
324 a8083063 Iustin Pop
  # instance  --------------------------
325 a8083063 Iustin Pop
326 3ecf6786 Iustin Pop
  @staticmethod
327 3ecf6786 Iustin Pop
  def perspective_instance_os_add(params):
328 3ecf6786 Iustin Pop
    """Install an OS on a given instance.
329 3ecf6786 Iustin Pop
330 3ecf6786 Iustin Pop
    """
331 a8083063 Iustin Pop
    inst_s, os_disk, swap_disk = params
332 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
333 a8083063 Iustin Pop
    return backend.AddOSToInstance(inst, os_disk, swap_disk)
334 a8083063 Iustin Pop
335 3ecf6786 Iustin Pop
  @staticmethod
336 decd5f45 Iustin Pop
  def perspective_instance_run_rename(params):
337 decd5f45 Iustin Pop
    """Runs the OS rename script for an instance.
338 decd5f45 Iustin Pop
339 decd5f45 Iustin Pop
    """
340 decd5f45 Iustin Pop
    inst_s, old_name, os_disk, swap_disk = params
341 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
342 decd5f45 Iustin Pop
    return backend.RunRenameInstance(inst, old_name, os_disk, swap_disk)
343 decd5f45 Iustin Pop
344 decd5f45 Iustin Pop
  @staticmethod
345 3ecf6786 Iustin Pop
  def perspective_instance_os_import(params):
346 3ecf6786 Iustin Pop
    """Run the import function of an OS onto a given instance.
347 3ecf6786 Iustin Pop
348 3ecf6786 Iustin Pop
    """
349 a8083063 Iustin Pop
    inst_s, os_disk, swap_disk, src_node, src_image = params
350 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
351 a8083063 Iustin Pop
    return backend.ImportOSIntoInstance(inst, os_disk, swap_disk,
352 a8083063 Iustin Pop
                                        src_node, src_image)
353 a8083063 Iustin Pop
354 3ecf6786 Iustin Pop
  @staticmethod
355 3ecf6786 Iustin Pop
  def perspective_instance_shutdown(params):
356 3ecf6786 Iustin Pop
    """Shutdown an instance.
357 3ecf6786 Iustin Pop
358 3ecf6786 Iustin Pop
    """
359 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
360 a8083063 Iustin Pop
    return backend.ShutdownInstance(instance)
361 a8083063 Iustin Pop
362 3ecf6786 Iustin Pop
  @staticmethod
363 3ecf6786 Iustin Pop
  def perspective_instance_start(params):
364 3ecf6786 Iustin Pop
    """Start an instance.
365 3ecf6786 Iustin Pop
366 3ecf6786 Iustin Pop
    """
367 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
368 a8083063 Iustin Pop
    extra_args = params[1]
369 a8083063 Iustin Pop
    return backend.StartInstance(instance, extra_args)
370 a8083063 Iustin Pop
371 3ecf6786 Iustin Pop
  @staticmethod
372 2a10865c Iustin Pop
  def perspective_instance_migrate(params):
373 2a10865c Iustin Pop
    """Migrates an instance.
374 2a10865c Iustin Pop
375 2a10865c Iustin Pop
    """
376 2a10865c Iustin Pop
    instance, target, live = params
377 2a10865c Iustin Pop
    return backend.MigrateInstance(instance, target, live)
378 2a10865c Iustin Pop
379 2a10865c Iustin Pop
  @staticmethod
380 007a2f3e Alexander Schreiber
  def perspective_instance_reboot(params):
381 007a2f3e Alexander Schreiber
    """Reboot an instance.
382 007a2f3e Alexander Schreiber
383 007a2f3e Alexander Schreiber
    """
384 007a2f3e Alexander Schreiber
    instance = objects.Instance.FromDict(params[0])
385 007a2f3e Alexander Schreiber
    reboot_type = params[1]
386 007a2f3e Alexander Schreiber
    extra_args = params[2]
387 007a2f3e Alexander Schreiber
    return backend.RebootInstance(instance, reboot_type, extra_args)
388 007a2f3e Alexander Schreiber
389 007a2f3e Alexander Schreiber
  @staticmethod
390 3ecf6786 Iustin Pop
  def perspective_instance_info(params):
391 3ecf6786 Iustin Pop
    """Query instance information.
392 3ecf6786 Iustin Pop
393 3ecf6786 Iustin Pop
    """
394 a8083063 Iustin Pop
    return backend.GetInstanceInfo(params[0])
395 a8083063 Iustin Pop
396 3ecf6786 Iustin Pop
  @staticmethod
397 3ecf6786 Iustin Pop
  def perspective_all_instances_info(params):
398 3ecf6786 Iustin Pop
    """Query information about all instances.
399 3ecf6786 Iustin Pop
400 3ecf6786 Iustin Pop
    """
401 a8083063 Iustin Pop
    return backend.GetAllInstancesInfo()
402 a8083063 Iustin Pop
403 3ecf6786 Iustin Pop
  @staticmethod
404 3ecf6786 Iustin Pop
  def perspective_instance_list(params):
405 3ecf6786 Iustin Pop
    """Query the list of running instances.
406 3ecf6786 Iustin Pop
407 3ecf6786 Iustin Pop
    """
408 a8083063 Iustin Pop
    return backend.GetInstanceList()
409 a8083063 Iustin Pop
410 a8083063 Iustin Pop
  # node --------------------------
411 a8083063 Iustin Pop
412 3ecf6786 Iustin Pop
  @staticmethod
413 16abfbc2 Alexander Schreiber
  def perspective_node_tcp_ping(params):
414 16abfbc2 Alexander Schreiber
    """Do a TcpPing on the remote node.
415 16abfbc2 Alexander Schreiber
416 16abfbc2 Alexander Schreiber
    """
417 b15d625f Iustin Pop
    return utils.TcpPing(params[1], params[2], timeout=params[3],
418 b15d625f Iustin Pop
                         live_port_needed=params[4], source=params[0])
419 16abfbc2 Alexander Schreiber
420 16abfbc2 Alexander Schreiber
  @staticmethod
421 3ecf6786 Iustin Pop
  def perspective_node_info(params):
422 3ecf6786 Iustin Pop
    """Query node information.
423 3ecf6786 Iustin Pop
424 3ecf6786 Iustin Pop
    """
425 a8083063 Iustin Pop
    vgname = params[0]
426 a8083063 Iustin Pop
    return backend.GetNodeInfo(vgname)
427 a8083063 Iustin Pop
428 3ecf6786 Iustin Pop
  @staticmethod
429 3ecf6786 Iustin Pop
  def perspective_node_add(params):
430 3ecf6786 Iustin Pop
    """Complete the registration of this node in the cluster.
431 3ecf6786 Iustin Pop
432 3ecf6786 Iustin Pop
    """
433 a8083063 Iustin Pop
    return backend.AddNode(params[0], params[1], params[2],
434 a8083063 Iustin Pop
                           params[3], params[4], params[5])
435 a8083063 Iustin Pop
436 3ecf6786 Iustin Pop
  @staticmethod
437 3ecf6786 Iustin Pop
  def perspective_node_verify(params):
438 3ecf6786 Iustin Pop
    """Run a verify sequence on this node.
439 3ecf6786 Iustin Pop
440 3ecf6786 Iustin Pop
    """
441 a8083063 Iustin Pop
    return backend.VerifyNode(params[0])
442 a8083063 Iustin Pop
443 3ecf6786 Iustin Pop
  @staticmethod
444 3ecf6786 Iustin Pop
  def perspective_node_start_master(params):
445 3ecf6786 Iustin Pop
    """Promote this node to master status.
446 3ecf6786 Iustin Pop
447 3ecf6786 Iustin Pop
    """
448 a8083063 Iustin Pop
    return backend.StartMaster()
449 a8083063 Iustin Pop
450 3ecf6786 Iustin Pop
  @staticmethod
451 3ecf6786 Iustin Pop
  def perspective_node_stop_master(params):
452 3ecf6786 Iustin Pop
    """Demote this node from master status.
453 3ecf6786 Iustin Pop
454 3ecf6786 Iustin Pop
    """
455 a8083063 Iustin Pop
    return backend.StopMaster()
456 a8083063 Iustin Pop
457 3ecf6786 Iustin Pop
  @staticmethod
458 3ecf6786 Iustin Pop
  def perspective_node_leave_cluster(params):
459 3ecf6786 Iustin Pop
    """Cleanup after leaving a cluster.
460 3ecf6786 Iustin Pop
461 3ecf6786 Iustin Pop
    """
462 a8083063 Iustin Pop
    return backend.LeaveCluster()
463 a8083063 Iustin Pop
464 3ecf6786 Iustin Pop
  @staticmethod
465 3ecf6786 Iustin Pop
  def perspective_node_volumes(params):
466 3ecf6786 Iustin Pop
    """Query the list of all logical volume groups.
467 3ecf6786 Iustin Pop
468 3ecf6786 Iustin Pop
    """
469 dcb93971 Michael Hanselmann
    return backend.NodeVolumes()
470 dcb93971 Michael Hanselmann
471 a8083063 Iustin Pop
  # cluster --------------------------
472 a8083063 Iustin Pop
473 3ecf6786 Iustin Pop
  @staticmethod
474 3ecf6786 Iustin Pop
  def perspective_version(params):
475 3ecf6786 Iustin Pop
    """Query version information.
476 3ecf6786 Iustin Pop
477 3ecf6786 Iustin Pop
    """
478 a8083063 Iustin Pop
    return constants.PROTOCOL_VERSION
479 a8083063 Iustin Pop
480 3ecf6786 Iustin Pop
  @staticmethod
481 3ecf6786 Iustin Pop
  def perspective_upload_file(params):
482 3ecf6786 Iustin Pop
    """Upload a file.
483 3ecf6786 Iustin Pop
484 3ecf6786 Iustin Pop
    Note that the backend implementation imposes strict rules on which
485 3ecf6786 Iustin Pop
    files are accepted.
486 3ecf6786 Iustin Pop
487 3ecf6786 Iustin Pop
    """
488 a8083063 Iustin Pop
    return backend.UploadFile(*params)
489 a8083063 Iustin Pop
490 a8083063 Iustin Pop
491 a8083063 Iustin Pop
  # os -----------------------
492 a8083063 Iustin Pop
493 3ecf6786 Iustin Pop
  @staticmethod
494 3ecf6786 Iustin Pop
  def perspective_os_diagnose(params):
495 3ecf6786 Iustin Pop
    """Query detailed information about existing OSes.
496 3ecf6786 Iustin Pop
497 3ecf6786 Iustin Pop
    """
498 4e679f11 Guido Trotter
    return [os.ToDict() for os in backend.DiagnoseOS()]
499 a8083063 Iustin Pop
500 3ecf6786 Iustin Pop
  @staticmethod
501 3ecf6786 Iustin Pop
  def perspective_os_get(params):
502 3ecf6786 Iustin Pop
    """Query information about a given OS.
503 3ecf6786 Iustin Pop
504 3ecf6786 Iustin Pop
    """
505 a8083063 Iustin Pop
    name = params[0]
506 a8083063 Iustin Pop
    try:
507 dfa96ded Guido Trotter
      os_obj = backend.OSFromDisk(name)
508 a8083063 Iustin Pop
    except errors.InvalidOS, err:
509 dfa96ded Guido Trotter
      os_obj = objects.OS.FromInvalidOS(err)
510 dfa96ded Guido Trotter
    return os_obj.ToDict()
511 a8083063 Iustin Pop
512 a8083063 Iustin Pop
  # hooks -----------------------
513 a8083063 Iustin Pop
514 3ecf6786 Iustin Pop
  @staticmethod
515 3ecf6786 Iustin Pop
  def perspective_hooks_runner(params):
516 3ecf6786 Iustin Pop
    """Run hook scripts.
517 3ecf6786 Iustin Pop
518 3ecf6786 Iustin Pop
    """
519 a8083063 Iustin Pop
    hpath, phase, env = params
520 a8083063 Iustin Pop
    hr = backend.HooksRunner()
521 a8083063 Iustin Pop
    return hr.RunHooks(hpath, phase, env)
522 a8083063 Iustin Pop
523 8d528b7c Iustin Pop
  # iallocator -----------------
524 8d528b7c Iustin Pop
525 8d528b7c Iustin Pop
  @staticmethod
526 8d528b7c Iustin Pop
  def perspective_iallocator_runner(params):
527 8d528b7c Iustin Pop
    """Run an iallocator script.
528 8d528b7c Iustin Pop
529 8d528b7c Iustin Pop
    """
530 8d528b7c Iustin Pop
    name, idata = params
531 8d528b7c Iustin Pop
    iar = backend.IAllocatorRunner()
532 8d528b7c Iustin Pop
    return iar.Run(name, idata)
533 8d528b7c Iustin Pop
534 06009e27 Iustin Pop
  # test -----------------------
535 06009e27 Iustin Pop
536 06009e27 Iustin Pop
  @staticmethod
537 06009e27 Iustin Pop
  def perspective_test_delay(params):
538 06009e27 Iustin Pop
    """Run test delay.
539 06009e27 Iustin Pop
540 06009e27 Iustin Pop
    """
541 06009e27 Iustin Pop
    duration = params[0]
542 06009e27 Iustin Pop
    return utils.TestDelay(duration)
543 06009e27 Iustin Pop
544 a5d7fb43 Manuel Franceschini
  @staticmethod
545 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_create(params):
546 a5d7fb43 Manuel Franceschini
    """Create the file storage directory.
547 a5d7fb43 Manuel Franceschini
548 a5d7fb43 Manuel Franceschini
    """
549 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
550 a5d7fb43 Manuel Franceschini
    return backend.CreateFileStorageDir(file_storage_dir)
551 a5d7fb43 Manuel Franceschini
552 a5d7fb43 Manuel Franceschini
  @staticmethod
553 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_remove(params):
554 a5d7fb43 Manuel Franceschini
    """Remove the file storage directory.
555 a5d7fb43 Manuel Franceschini
556 a5d7fb43 Manuel Franceschini
    """
557 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
558 a5d7fb43 Manuel Franceschini
    return backend.RemoveFileStorageDir(file_storage_dir)
559 a5d7fb43 Manuel Franceschini
560 a5d7fb43 Manuel Franceschini
  @staticmethod
561 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_rename(params):
562 a5d7fb43 Manuel Franceschini
    """Rename the file storage directory.
563 a5d7fb43 Manuel Franceschini
564 a5d7fb43 Manuel Franceschini
    """
565 a5d7fb43 Manuel Franceschini
    old_file_storage_dir = params[0]
566 a5d7fb43 Manuel Franceschini
    new_file_storage_dir = params[1]
567 a5d7fb43 Manuel Franceschini
    return backend.RenameFileStorageDir(old_file_storage_dir,
568 a5d7fb43 Manuel Franceschini
                                        new_file_storage_dir)
569 a5d7fb43 Manuel Franceschini
570 a8083063 Iustin Pop
571 a8083063 Iustin Pop
def ParseOptions():
572 a8083063 Iustin Pop
  """Parse the command line options.
573 a8083063 Iustin Pop
574 a8083063 Iustin Pop
  Returns:
575 a8083063 Iustin Pop
    (options, args) as from OptionParser.parse_args()
576 a8083063 Iustin Pop
577 a8083063 Iustin Pop
  """
578 a8083063 Iustin Pop
  parser = OptionParser(description="Ganeti node daemon",
579 a8083063 Iustin Pop
                        usage="%prog [-f] [-d]",
580 a8083063 Iustin Pop
                        version="%%prog (ganeti) %s" %
581 a8083063 Iustin Pop
                        constants.RELEASE_VERSION)
582 a8083063 Iustin Pop
583 a8083063 Iustin Pop
  parser.add_option("-f", "--foreground", dest="fork",
584 a8083063 Iustin Pop
                    help="Don't detach from the current terminal",
585 a8083063 Iustin Pop
                    default=True, action="store_false")
586 a8083063 Iustin Pop
  parser.add_option("-d", "--debug", dest="debug",
587 a8083063 Iustin Pop
                    help="Enable some debug messages",
588 a8083063 Iustin Pop
                    default=False, action="store_true")
589 a8083063 Iustin Pop
  options, args = parser.parse_args()
590 a8083063 Iustin Pop
  return options, args
591 a8083063 Iustin Pop
592 a8083063 Iustin Pop
593 a8083063 Iustin Pop
def main():
594 3ecf6786 Iustin Pop
  """Main function for the node daemon.
595 3ecf6786 Iustin Pop
596 3ecf6786 Iustin Pop
  """
597 a8083063 Iustin Pop
  options, args = ParseOptions()
598 f362096f Iustin Pop
  utils.debug = options.debug
599 a8083063 Iustin Pop
  for fname in (constants.SSL_CERT_FILE,):
600 a8083063 Iustin Pop
    if not os.path.isfile(fname):
601 a8083063 Iustin Pop
      print "config %s not there, will not run." % fname
602 a8083063 Iustin Pop
      sys.exit(5)
603 a8083063 Iustin Pop
604 a8083063 Iustin Pop
  try:
605 a8083063 Iustin Pop
    ss = ssconf.SimpleStore()
606 a8083063 Iustin Pop
    port = ss.GetNodeDaemonPort()
607 a8083063 Iustin Pop
    pwdata = ss.GetNodeDaemonPassword()
608 a8083063 Iustin Pop
  except errors.ConfigurationError, err:
609 a8083063 Iustin Pop
    print "Cluster configuration incomplete: '%s'" % str(err)
610 a8083063 Iustin Pop
    sys.exit(5)
611 a8083063 Iustin Pop
612 0214b0c0 Iustin Pop
  # create /var/run/ganeti if not existing, in order to take care of
613 0214b0c0 Iustin Pop
  # tmpfs /var/run
614 0214b0c0 Iustin Pop
  if not os.path.exists(constants.BDEV_CACHE_DIR):
615 0214b0c0 Iustin Pop
    try:
616 0214b0c0 Iustin Pop
      os.mkdir(constants.BDEV_CACHE_DIR, 0755)
617 0214b0c0 Iustin Pop
    except EnvironmentError, err:
618 0214b0c0 Iustin Pop
      if err.errno != errno.EEXIST:
619 0214b0c0 Iustin Pop
        print ("Node setup wrong, cannot create directory %s: %s" %
620 0214b0c0 Iustin Pop
               (constants.BDEV_CACHE_DIR, err))
621 0214b0c0 Iustin Pop
        sys.exit(5)
622 0214b0c0 Iustin Pop
  if not os.path.isdir(constants.BDEV_CACHE_DIR):
623 0214b0c0 Iustin Pop
    print ("Node setup wrong, %s is not a directory" %
624 0214b0c0 Iustin Pop
           constants.BDEV_CACHE_DIR)
625 0214b0c0 Iustin Pop
    sys.exit(5)
626 0214b0c0 Iustin Pop
627 a8083063 Iustin Pop
  # become a daemon
628 a8083063 Iustin Pop
  if options.fork:
629 8f765069 Iustin Pop
    utils.Daemonize(logfile=constants.LOG_NODESERVER)
630 a8083063 Iustin Pop
631 2a2060ff Michael Hanselmann
  logger.SetupLogging(program="ganeti-noded", debug=options.debug)
632 a8083063 Iustin Pop
633 3b3db8fd Guido Trotter
  global _EXIT_GANETI_NODED
634 3b3db8fd Guido Trotter
  _EXIT_GANETI_NODED = False
635 3b3db8fd Guido Trotter
636 81010134 Iustin Pop
  httpd = BaseHTTPServer.HTTPServer(('', port), ServerObject)
637 3b3db8fd Guido Trotter
  while (not _EXIT_GANETI_NODED):
638 3b3db8fd Guido Trotter
    httpd.handle_request()
639 a8083063 Iustin Pop
640 a8083063 Iustin Pop
641 3ecf6786 Iustin Pop
if __name__ == '__main__':
642 a8083063 Iustin Pop
  main()