Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ 2a2060ff

History | View | Annotate | Download (15.6 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 a8083063 Iustin Pop
  # export/import  --------------------------
215 a8083063 Iustin Pop
216 3ecf6786 Iustin Pop
  @staticmethod
217 3ecf6786 Iustin Pop
  def perspective_snapshot_export(params):
218 3ecf6786 Iustin Pop
    """Export a given snapshot.
219 3ecf6786 Iustin Pop
220 3ecf6786 Iustin Pop
    """
221 319856a9 Michael Hanselmann
    disk = objects.Disk.FromDict(params[0])
222 a8083063 Iustin Pop
    dest_node = params[1]
223 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[2])
224 3ecf6786 Iustin Pop
    return backend.ExportSnapshot(disk, dest_node, instance)
225 3ecf6786 Iustin Pop
226 3ecf6786 Iustin Pop
  @staticmethod
227 3ecf6786 Iustin Pop
  def perspective_finalize_export(params):
228 3ecf6786 Iustin Pop
    """Expose the finalize export functionality.
229 a8083063 Iustin Pop
230 3ecf6786 Iustin Pop
    """
231 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
232 319856a9 Michael Hanselmann
    snap_disks = [objects.Disk.FromDict(str_data)
233 a8083063 Iustin Pop
                  for str_data in params[1]]
234 a8083063 Iustin Pop
    return backend.FinalizeExport(instance, snap_disks)
235 a8083063 Iustin Pop
236 3ecf6786 Iustin Pop
  @staticmethod
237 3ecf6786 Iustin Pop
  def perspective_export_info(params):
238 3ecf6786 Iustin Pop
    """Query information about an existing export on this node.
239 3ecf6786 Iustin Pop
240 3ecf6786 Iustin Pop
    The given path may not contain an export, in which case we return
241 3ecf6786 Iustin Pop
    None.
242 3ecf6786 Iustin Pop
243 3ecf6786 Iustin Pop
    """
244 3ecf6786 Iustin Pop
    path = params[0]
245 3ecf6786 Iustin Pop
    einfo = backend.ExportInfo(path)
246 a8083063 Iustin Pop
    if einfo is None:
247 a8083063 Iustin Pop
      return einfo
248 a8083063 Iustin Pop
    return einfo.Dumps()
249 a8083063 Iustin Pop
250 3ecf6786 Iustin Pop
  @staticmethod
251 3ecf6786 Iustin Pop
  def perspective_export_list(params):
252 3ecf6786 Iustin Pop
    """List the available exports on this node.
253 3ecf6786 Iustin Pop
254 3ecf6786 Iustin Pop
    Note that as opposed to export_info, which may query data about an
255 3ecf6786 Iustin Pop
    export in any path, this only queries the standard Ganeti path
256 3ecf6786 Iustin Pop
    (constants.EXPORT_DIR).
257 3ecf6786 Iustin Pop
258 3ecf6786 Iustin Pop
    """
259 a8083063 Iustin Pop
    return backend.ListExports()
260 a8083063 Iustin Pop
261 3ecf6786 Iustin Pop
  @staticmethod
262 3ecf6786 Iustin Pop
  def perspective_export_remove(params):
263 3ecf6786 Iustin Pop
    """Remove an export.
264 3ecf6786 Iustin Pop
265 3ecf6786 Iustin Pop
    """
266 a8083063 Iustin Pop
    export = params[0]
267 a8083063 Iustin Pop
    return backend.RemoveExport(export)
268 a8083063 Iustin Pop
269 a8083063 Iustin Pop
  # volume  --------------------------
270 a8083063 Iustin Pop
271 3ecf6786 Iustin Pop
  @staticmethod
272 3ecf6786 Iustin Pop
  def perspective_volume_list(params):
273 3ecf6786 Iustin Pop
    """Query the list of logical volumes in a given volume group.
274 3ecf6786 Iustin Pop
275 3ecf6786 Iustin Pop
    """
276 a8083063 Iustin Pop
    vgname = params[0]
277 a8083063 Iustin Pop
    return backend.GetVolumeList(vgname)
278 a8083063 Iustin Pop
279 3ecf6786 Iustin Pop
  @staticmethod
280 3ecf6786 Iustin Pop
  def perspective_vg_list(params):
281 3ecf6786 Iustin Pop
    """Query the list of volume groups.
282 3ecf6786 Iustin Pop
283 3ecf6786 Iustin Pop
    """
284 a8083063 Iustin Pop
    return backend.ListVolumeGroups()
285 a8083063 Iustin Pop
286 a8083063 Iustin Pop
  # bridge  --------------------------
287 a8083063 Iustin Pop
288 3ecf6786 Iustin Pop
  @staticmethod
289 3ecf6786 Iustin Pop
  def perspective_bridges_exist(params):
290 3ecf6786 Iustin Pop
    """Check if all bridges given exist on this node.
291 3ecf6786 Iustin Pop
292 3ecf6786 Iustin Pop
    """
293 a8083063 Iustin Pop
    bridges_list = params[0]
294 a8083063 Iustin Pop
    return backend.BridgesExist(bridges_list)
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
  # instance  --------------------------
297 a8083063 Iustin Pop
298 3ecf6786 Iustin Pop
  @staticmethod
299 3ecf6786 Iustin Pop
  def perspective_instance_os_add(params):
300 3ecf6786 Iustin Pop
    """Install an OS on a given instance.
301 3ecf6786 Iustin Pop
302 3ecf6786 Iustin Pop
    """
303 a8083063 Iustin Pop
    inst_s, os_disk, swap_disk = params
304 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
305 a8083063 Iustin Pop
    return backend.AddOSToInstance(inst, os_disk, swap_disk)
306 a8083063 Iustin Pop
307 3ecf6786 Iustin Pop
  @staticmethod
308 decd5f45 Iustin Pop
  def perspective_instance_run_rename(params):
309 decd5f45 Iustin Pop
    """Runs the OS rename script for an instance.
310 decd5f45 Iustin Pop
311 decd5f45 Iustin Pop
    """
312 decd5f45 Iustin Pop
    inst_s, old_name, os_disk, swap_disk = params
313 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
314 decd5f45 Iustin Pop
    return backend.RunRenameInstance(inst, old_name, os_disk, swap_disk)
315 decd5f45 Iustin Pop
316 decd5f45 Iustin Pop
  @staticmethod
317 3ecf6786 Iustin Pop
  def perspective_instance_os_import(params):
318 3ecf6786 Iustin Pop
    """Run the import function of an OS onto a given instance.
319 3ecf6786 Iustin Pop
320 3ecf6786 Iustin Pop
    """
321 a8083063 Iustin Pop
    inst_s, os_disk, swap_disk, src_node, src_image = params
322 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
323 a8083063 Iustin Pop
    return backend.ImportOSIntoInstance(inst, os_disk, swap_disk,
324 a8083063 Iustin Pop
                                        src_node, src_image)
325 a8083063 Iustin Pop
326 3ecf6786 Iustin Pop
  @staticmethod
327 3ecf6786 Iustin Pop
  def perspective_instance_shutdown(params):
328 3ecf6786 Iustin Pop
    """Shutdown an instance.
329 3ecf6786 Iustin Pop
330 3ecf6786 Iustin Pop
    """
331 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
332 a8083063 Iustin Pop
    return backend.ShutdownInstance(instance)
333 a8083063 Iustin Pop
334 3ecf6786 Iustin Pop
  @staticmethod
335 3ecf6786 Iustin Pop
  def perspective_instance_start(params):
336 3ecf6786 Iustin Pop
    """Start an instance.
337 3ecf6786 Iustin Pop
338 3ecf6786 Iustin Pop
    """
339 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
340 a8083063 Iustin Pop
    extra_args = params[1]
341 a8083063 Iustin Pop
    return backend.StartInstance(instance, extra_args)
342 a8083063 Iustin Pop
343 3ecf6786 Iustin Pop
  @staticmethod
344 007a2f3e Alexander Schreiber
  def perspective_instance_reboot(params):
345 007a2f3e Alexander Schreiber
    """Reboot an instance.
346 007a2f3e Alexander Schreiber
347 007a2f3e Alexander Schreiber
    """
348 007a2f3e Alexander Schreiber
    instance = objects.Instance.FromDict(params[0])
349 007a2f3e Alexander Schreiber
    reboot_type = params[1]
350 007a2f3e Alexander Schreiber
    extra_args = params[2]
351 007a2f3e Alexander Schreiber
    return backend.RebootInstance(instance, reboot_type, extra_args)
352 007a2f3e Alexander Schreiber
353 007a2f3e Alexander Schreiber
  @staticmethod
354 3ecf6786 Iustin Pop
  def perspective_instance_info(params):
355 3ecf6786 Iustin Pop
    """Query instance information.
356 3ecf6786 Iustin Pop
357 3ecf6786 Iustin Pop
    """
358 a8083063 Iustin Pop
    return backend.GetInstanceInfo(params[0])
359 a8083063 Iustin Pop
360 3ecf6786 Iustin Pop
  @staticmethod
361 3ecf6786 Iustin Pop
  def perspective_all_instances_info(params):
362 3ecf6786 Iustin Pop
    """Query information about all instances.
363 3ecf6786 Iustin Pop
364 3ecf6786 Iustin Pop
    """
365 a8083063 Iustin Pop
    return backend.GetAllInstancesInfo()
366 a8083063 Iustin Pop
367 3ecf6786 Iustin Pop
  @staticmethod
368 3ecf6786 Iustin Pop
  def perspective_instance_list(params):
369 3ecf6786 Iustin Pop
    """Query the list of running instances.
370 3ecf6786 Iustin Pop
371 3ecf6786 Iustin Pop
    """
372 a8083063 Iustin Pop
    return backend.GetInstanceList()
373 a8083063 Iustin Pop
374 a8083063 Iustin Pop
  # node --------------------------
375 a8083063 Iustin Pop
376 3ecf6786 Iustin Pop
  @staticmethod
377 16abfbc2 Alexander Schreiber
  def perspective_node_tcp_ping(params):
378 16abfbc2 Alexander Schreiber
    """Do a TcpPing on the remote node.
379 16abfbc2 Alexander Schreiber
380 16abfbc2 Alexander Schreiber
    """
381 b15d625f Iustin Pop
    return utils.TcpPing(params[1], params[2], timeout=params[3],
382 b15d625f Iustin Pop
                         live_port_needed=params[4], source=params[0])
383 16abfbc2 Alexander Schreiber
384 16abfbc2 Alexander Schreiber
  @staticmethod
385 3ecf6786 Iustin Pop
  def perspective_node_info(params):
386 3ecf6786 Iustin Pop
    """Query node information.
387 3ecf6786 Iustin Pop
388 3ecf6786 Iustin Pop
    """
389 a8083063 Iustin Pop
    vgname = params[0]
390 a8083063 Iustin Pop
    return backend.GetNodeInfo(vgname)
391 a8083063 Iustin Pop
392 3ecf6786 Iustin Pop
  @staticmethod
393 3ecf6786 Iustin Pop
  def perspective_node_add(params):
394 3ecf6786 Iustin Pop
    """Complete the registration of this node in the cluster.
395 3ecf6786 Iustin Pop
396 3ecf6786 Iustin Pop
    """
397 a8083063 Iustin Pop
    return backend.AddNode(params[0], params[1], params[2],
398 a8083063 Iustin Pop
                           params[3], params[4], params[5])
399 a8083063 Iustin Pop
400 3ecf6786 Iustin Pop
  @staticmethod
401 3ecf6786 Iustin Pop
  def perspective_node_verify(params):
402 3ecf6786 Iustin Pop
    """Run a verify sequence on this node.
403 3ecf6786 Iustin Pop
404 3ecf6786 Iustin Pop
    """
405 a8083063 Iustin Pop
    return backend.VerifyNode(params[0])
406 a8083063 Iustin Pop
407 3ecf6786 Iustin Pop
  @staticmethod
408 3ecf6786 Iustin Pop
  def perspective_node_start_master(params):
409 3ecf6786 Iustin Pop
    """Promote this node to master status.
410 3ecf6786 Iustin Pop
411 3ecf6786 Iustin Pop
    """
412 a8083063 Iustin Pop
    return backend.StartMaster()
413 a8083063 Iustin Pop
414 3ecf6786 Iustin Pop
  @staticmethod
415 3ecf6786 Iustin Pop
  def perspective_node_stop_master(params):
416 3ecf6786 Iustin Pop
    """Demote this node from master status.
417 3ecf6786 Iustin Pop
418 3ecf6786 Iustin Pop
    """
419 a8083063 Iustin Pop
    return backend.StopMaster()
420 a8083063 Iustin Pop
421 3ecf6786 Iustin Pop
  @staticmethod
422 3ecf6786 Iustin Pop
  def perspective_node_leave_cluster(params):
423 3ecf6786 Iustin Pop
    """Cleanup after leaving a cluster.
424 3ecf6786 Iustin Pop
425 3ecf6786 Iustin Pop
    """
426 a8083063 Iustin Pop
    return backend.LeaveCluster()
427 a8083063 Iustin Pop
428 3ecf6786 Iustin Pop
  @staticmethod
429 3ecf6786 Iustin Pop
  def perspective_node_volumes(params):
430 3ecf6786 Iustin Pop
    """Query the list of all logical volume groups.
431 3ecf6786 Iustin Pop
432 3ecf6786 Iustin Pop
    """
433 dcb93971 Michael Hanselmann
    return backend.NodeVolumes()
434 dcb93971 Michael Hanselmann
435 a8083063 Iustin Pop
  # cluster --------------------------
436 a8083063 Iustin Pop
437 3ecf6786 Iustin Pop
  @staticmethod
438 3ecf6786 Iustin Pop
  def perspective_version(params):
439 3ecf6786 Iustin Pop
    """Query version information.
440 3ecf6786 Iustin Pop
441 3ecf6786 Iustin Pop
    """
442 a8083063 Iustin Pop
    return constants.PROTOCOL_VERSION
443 a8083063 Iustin Pop
444 3ecf6786 Iustin Pop
  @staticmethod
445 3ecf6786 Iustin Pop
  def perspective_upload_file(params):
446 3ecf6786 Iustin Pop
    """Upload a file.
447 3ecf6786 Iustin Pop
448 3ecf6786 Iustin Pop
    Note that the backend implementation imposes strict rules on which
449 3ecf6786 Iustin Pop
    files are accepted.
450 3ecf6786 Iustin Pop
451 3ecf6786 Iustin Pop
    """
452 a8083063 Iustin Pop
    return backend.UploadFile(*params)
453 a8083063 Iustin Pop
454 a8083063 Iustin Pop
455 a8083063 Iustin Pop
  # os -----------------------
456 a8083063 Iustin Pop
457 3ecf6786 Iustin Pop
  @staticmethod
458 3ecf6786 Iustin Pop
  def perspective_os_diagnose(params):
459 3ecf6786 Iustin Pop
    """Query detailed information about existing OSes.
460 3ecf6786 Iustin Pop
461 3ecf6786 Iustin Pop
    """
462 4e679f11 Guido Trotter
    return [os.ToDict() for os in backend.DiagnoseOS()]
463 a8083063 Iustin Pop
464 3ecf6786 Iustin Pop
  @staticmethod
465 3ecf6786 Iustin Pop
  def perspective_os_get(params):
466 3ecf6786 Iustin Pop
    """Query information about a given OS.
467 3ecf6786 Iustin Pop
468 3ecf6786 Iustin Pop
    """
469 a8083063 Iustin Pop
    name = params[0]
470 a8083063 Iustin Pop
    try:
471 dfa96ded Guido Trotter
      os_obj = backend.OSFromDisk(name)
472 a8083063 Iustin Pop
    except errors.InvalidOS, err:
473 dfa96ded Guido Trotter
      os_obj = objects.OS.FromInvalidOS(err)
474 dfa96ded Guido Trotter
    return os_obj.ToDict()
475 a8083063 Iustin Pop
476 a8083063 Iustin Pop
  # hooks -----------------------
477 a8083063 Iustin Pop
478 3ecf6786 Iustin Pop
  @staticmethod
479 3ecf6786 Iustin Pop
  def perspective_hooks_runner(params):
480 3ecf6786 Iustin Pop
    """Run hook scripts.
481 3ecf6786 Iustin Pop
482 3ecf6786 Iustin Pop
    """
483 a8083063 Iustin Pop
    hpath, phase, env = params
484 a8083063 Iustin Pop
    hr = backend.HooksRunner()
485 a8083063 Iustin Pop
    return hr.RunHooks(hpath, phase, env)
486 a8083063 Iustin Pop
487 8d528b7c Iustin Pop
  # iallocator -----------------
488 8d528b7c Iustin Pop
489 8d528b7c Iustin Pop
  @staticmethod
490 8d528b7c Iustin Pop
  def perspective_iallocator_runner(params):
491 8d528b7c Iustin Pop
    """Run an iallocator script.
492 8d528b7c Iustin Pop
493 8d528b7c Iustin Pop
    """
494 8d528b7c Iustin Pop
    name, idata = params
495 8d528b7c Iustin Pop
    iar = backend.IAllocatorRunner()
496 8d528b7c Iustin Pop
    return iar.Run(name, idata)
497 8d528b7c Iustin Pop
498 06009e27 Iustin Pop
  # test -----------------------
499 06009e27 Iustin Pop
500 06009e27 Iustin Pop
  @staticmethod
501 06009e27 Iustin Pop
  def perspective_test_delay(params):
502 06009e27 Iustin Pop
    """Run test delay.
503 06009e27 Iustin Pop
504 06009e27 Iustin Pop
    """
505 06009e27 Iustin Pop
    duration = params[0]
506 06009e27 Iustin Pop
    return utils.TestDelay(duration)
507 06009e27 Iustin Pop
508 a5d7fb43 Manuel Franceschini
  @staticmethod
509 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_create(params):
510 a5d7fb43 Manuel Franceschini
    """Create the file storage directory.
511 a5d7fb43 Manuel Franceschini
512 a5d7fb43 Manuel Franceschini
    """
513 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
514 a5d7fb43 Manuel Franceschini
    return backend.CreateFileStorageDir(file_storage_dir)
515 a5d7fb43 Manuel Franceschini
516 a5d7fb43 Manuel Franceschini
  @staticmethod
517 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_remove(params):
518 a5d7fb43 Manuel Franceschini
    """Remove the file storage directory.
519 a5d7fb43 Manuel Franceschini
520 a5d7fb43 Manuel Franceschini
    """
521 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
522 a5d7fb43 Manuel Franceschini
    return backend.RemoveFileStorageDir(file_storage_dir)
523 a5d7fb43 Manuel Franceschini
524 a5d7fb43 Manuel Franceschini
  @staticmethod
525 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_rename(params):
526 a5d7fb43 Manuel Franceschini
    """Rename the file storage directory.
527 a5d7fb43 Manuel Franceschini
528 a5d7fb43 Manuel Franceschini
    """
529 a5d7fb43 Manuel Franceschini
    old_file_storage_dir = params[0]
530 a5d7fb43 Manuel Franceschini
    new_file_storage_dir = params[1]
531 a5d7fb43 Manuel Franceschini
    return backend.RenameFileStorageDir(old_file_storage_dir,
532 a5d7fb43 Manuel Franceschini
                                        new_file_storage_dir)
533 a5d7fb43 Manuel Franceschini
534 a8083063 Iustin Pop
535 a8083063 Iustin Pop
def ParseOptions():
536 a8083063 Iustin Pop
  """Parse the command line options.
537 a8083063 Iustin Pop
538 a8083063 Iustin Pop
  Returns:
539 a8083063 Iustin Pop
    (options, args) as from OptionParser.parse_args()
540 a8083063 Iustin Pop
541 a8083063 Iustin Pop
  """
542 a8083063 Iustin Pop
  parser = OptionParser(description="Ganeti node daemon",
543 a8083063 Iustin Pop
                        usage="%prog [-f] [-d]",
544 a8083063 Iustin Pop
                        version="%%prog (ganeti) %s" %
545 a8083063 Iustin Pop
                        constants.RELEASE_VERSION)
546 a8083063 Iustin Pop
547 a8083063 Iustin Pop
  parser.add_option("-f", "--foreground", dest="fork",
548 a8083063 Iustin Pop
                    help="Don't detach from the current terminal",
549 a8083063 Iustin Pop
                    default=True, action="store_false")
550 a8083063 Iustin Pop
  parser.add_option("-d", "--debug", dest="debug",
551 a8083063 Iustin Pop
                    help="Enable some debug messages",
552 a8083063 Iustin Pop
                    default=False, action="store_true")
553 a8083063 Iustin Pop
  options, args = parser.parse_args()
554 a8083063 Iustin Pop
  return options, args
555 a8083063 Iustin Pop
556 a8083063 Iustin Pop
557 a8083063 Iustin Pop
def main():
558 3ecf6786 Iustin Pop
  """Main function for the node daemon.
559 3ecf6786 Iustin Pop
560 3ecf6786 Iustin Pop
  """
561 a8083063 Iustin Pop
  options, args = ParseOptions()
562 f362096f Iustin Pop
  utils.debug = options.debug
563 a8083063 Iustin Pop
  for fname in (constants.SSL_CERT_FILE,):
564 a8083063 Iustin Pop
    if not os.path.isfile(fname):
565 a8083063 Iustin Pop
      print "config %s not there, will not run." % fname
566 a8083063 Iustin Pop
      sys.exit(5)
567 a8083063 Iustin Pop
568 a8083063 Iustin Pop
  try:
569 a8083063 Iustin Pop
    ss = ssconf.SimpleStore()
570 a8083063 Iustin Pop
    port = ss.GetNodeDaemonPort()
571 a8083063 Iustin Pop
    pwdata = ss.GetNodeDaemonPassword()
572 a8083063 Iustin Pop
  except errors.ConfigurationError, err:
573 a8083063 Iustin Pop
    print "Cluster configuration incomplete: '%s'" % str(err)
574 a8083063 Iustin Pop
    sys.exit(5)
575 a8083063 Iustin Pop
576 0214b0c0 Iustin Pop
  # create /var/run/ganeti if not existing, in order to take care of
577 0214b0c0 Iustin Pop
  # tmpfs /var/run
578 0214b0c0 Iustin Pop
  if not os.path.exists(constants.BDEV_CACHE_DIR):
579 0214b0c0 Iustin Pop
    try:
580 0214b0c0 Iustin Pop
      os.mkdir(constants.BDEV_CACHE_DIR, 0755)
581 0214b0c0 Iustin Pop
    except EnvironmentError, err:
582 0214b0c0 Iustin Pop
      if err.errno != errno.EEXIST:
583 0214b0c0 Iustin Pop
        print ("Node setup wrong, cannot create directory %s: %s" %
584 0214b0c0 Iustin Pop
               (constants.BDEV_CACHE_DIR, err))
585 0214b0c0 Iustin Pop
        sys.exit(5)
586 0214b0c0 Iustin Pop
  if not os.path.isdir(constants.BDEV_CACHE_DIR):
587 0214b0c0 Iustin Pop
    print ("Node setup wrong, %s is not a directory" %
588 0214b0c0 Iustin Pop
           constants.BDEV_CACHE_DIR)
589 0214b0c0 Iustin Pop
    sys.exit(5)
590 0214b0c0 Iustin Pop
591 a8083063 Iustin Pop
  # become a daemon
592 a8083063 Iustin Pop
  if options.fork:
593 8f765069 Iustin Pop
    utils.Daemonize(logfile=constants.LOG_NODESERVER)
594 a8083063 Iustin Pop
595 2a2060ff Michael Hanselmann
  logger.SetupLogging(program="ganeti-noded", debug=options.debug)
596 a8083063 Iustin Pop
597 81010134 Iustin Pop
  httpd = BaseHTTPServer.HTTPServer(('', port), ServerObject)
598 81010134 Iustin Pop
  httpd.serve_forever()
599 a8083063 Iustin Pop
600 a8083063 Iustin Pop
601 3ecf6786 Iustin Pop
if __name__ == '__main__':
602 a8083063 Iustin Pop
  main()