Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ 67fe61c4

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