Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ 1fae010f

History | View | Annotate | Download (21.1 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 761ce945 Guido Trotter
import SocketServer
31 0214b0c0 Iustin Pop
import errno
32 c89189b1 Iustin Pop
import logging
33 84b58db2 Michael Hanselmann
import signal
34 a8083063 Iustin Pop
35 a8083063 Iustin Pop
from optparse import OptionParser
36 a8083063 Iustin Pop
37 a8083063 Iustin Pop
from ganeti import backend
38 a8083063 Iustin Pop
from ganeti import constants
39 a8083063 Iustin Pop
from ganeti import objects
40 a8083063 Iustin Pop
from ganeti import errors
41 25d6d12a Michael Hanselmann
from ganeti import jstore
42 cc28af80 Michael Hanselmann
from ganeti import daemon
43 1df6506c Michael Hanselmann
from ganeti import http
44 16abfbc2 Alexander Schreiber
from ganeti import utils
45 a8083063 Iustin Pop
46 19205c39 Michael Hanselmann
import ganeti.http.server
47 19205c39 Michael Hanselmann
48 a8083063 Iustin Pop
49 25d6d12a Michael Hanselmann
queue_lock = None
50 25d6d12a Michael Hanselmann
51 25d6d12a Michael Hanselmann
52 7f30777b Michael Hanselmann
def _RequireJobQueueLock(fn):
53 7f30777b Michael Hanselmann
  """Decorator for job queue manipulating functions.
54 7f30777b Michael Hanselmann
55 7f30777b Michael Hanselmann
  """
56 8785cb30 Michael Hanselmann
  QUEUE_LOCK_TIMEOUT = 10
57 8785cb30 Michael Hanselmann
58 7f30777b Michael Hanselmann
  def wrapper(*args, **kwargs):
59 7f30777b Michael Hanselmann
    # Locking in exclusive, blocking mode because there could be several
60 506cff12 Michael Hanselmann
    # children running at the same time. Waiting up to 10 seconds.
61 8785cb30 Michael Hanselmann
    queue_lock.Exclusive(blocking=True, timeout=QUEUE_LOCK_TIMEOUT)
62 7f30777b Michael Hanselmann
    try:
63 7f30777b Michael Hanselmann
      return fn(*args, **kwargs)
64 7f30777b Michael Hanselmann
    finally:
65 7f30777b Michael Hanselmann
      queue_lock.Unlock()
66 8785cb30 Michael Hanselmann
67 7f30777b Michael Hanselmann
  return wrapper
68 7f30777b Michael Hanselmann
69 7f30777b Michael Hanselmann
70 19205c39 Michael Hanselmann
class NodeHttpServer(http.server.HttpServer):
71 3ecf6786 Iustin Pop
  """The server implementation.
72 3ecf6786 Iustin Pop
73 3ecf6786 Iustin Pop
  This class holds all methods exposed over the RPC interface.
74 3ecf6786 Iustin Pop
75 3ecf6786 Iustin Pop
  """
76 cc28af80 Michael Hanselmann
  def __init__(self, *args, **kwargs):
77 19205c39 Michael Hanselmann
    http.server.HttpServer.__init__(self, *args, **kwargs)
78 cc28af80 Michael Hanselmann
    self.noded_pid = os.getpid()
79 cc28af80 Michael Hanselmann
80 cc28af80 Michael Hanselmann
  def HandleRequest(self, req):
81 1df6506c Michael Hanselmann
    """Handle a request.
82 a8083063 Iustin Pop
83 098c0958 Michael Hanselmann
    """
84 19205c39 Michael Hanselmann
    if req.request_method.upper() != http.HTTP_PUT:
85 84f2756e Michael Hanselmann
      raise http.HttpBadRequest()
86 1df6506c Michael Hanselmann
87 cc28af80 Michael Hanselmann
    path = req.request_path
88 81010134 Iustin Pop
    if path.startswith("/"):
89 81010134 Iustin Pop
      path = path[1:]
90 81010134 Iustin Pop
91 1df6506c Michael Hanselmann
    method = getattr(self, "perspective_%s" % path, None)
92 1df6506c Michael Hanselmann
    if method is None:
93 84f2756e Michael Hanselmann
      raise http.HttpNotFound()
94 a8083063 Iustin Pop
95 81010134 Iustin Pop
    try:
96 aa9075c5 Michael Hanselmann
      try:
97 19205c39 Michael Hanselmann
        return method(req.request_body)
98 aa9075c5 Michael Hanselmann
      except:
99 aa9075c5 Michael Hanselmann
        logging.exception("Error in RPC call")
100 aa9075c5 Michael Hanselmann
        raise
101 9ae49f27 Guido Trotter
    except errors.QuitGanetiException, err:
102 84b58db2 Michael Hanselmann
      # Tell parent to quit
103 cc28af80 Michael Hanselmann
      os.kill(self.noded_pid, signal.SIGTERM)
104 a8083063 Iustin Pop
105 a8083063 Iustin Pop
  # the new block devices  --------------------------
106 a8083063 Iustin Pop
107 3ecf6786 Iustin Pop
  @staticmethod
108 3ecf6786 Iustin Pop
  def perspective_blockdev_create(params):
109 3ecf6786 Iustin Pop
    """Create a block device.
110 3ecf6786 Iustin Pop
111 3ecf6786 Iustin Pop
    """
112 3f78eef2 Iustin Pop
    bdev_s, size, owner, on_primary, info = params
113 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
114 a8083063 Iustin Pop
    if bdev is None:
115 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
116 821d1bd1 Iustin Pop
    return backend.BlockdevCreate(bdev, size, owner, on_primary, info)
117 a8083063 Iustin Pop
118 3ecf6786 Iustin Pop
  @staticmethod
119 3ecf6786 Iustin Pop
  def perspective_blockdev_remove(params):
120 3ecf6786 Iustin Pop
    """Remove a block device.
121 3ecf6786 Iustin Pop
122 3ecf6786 Iustin Pop
    """
123 a8083063 Iustin Pop
    bdev_s = params[0]
124 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
125 821d1bd1 Iustin Pop
    return backend.BlockdevRemove(bdev)
126 a8083063 Iustin Pop
127 3ecf6786 Iustin Pop
  @staticmethod
128 f3e513ad Iustin Pop
  def perspective_blockdev_rename(params):
129 f3e513ad Iustin Pop
    """Remove a block device.
130 f3e513ad Iustin Pop
131 f3e513ad Iustin Pop
    """
132 f3e513ad Iustin Pop
    devlist = [(objects.Disk.FromDict(ds), uid) for ds, uid in params]
133 821d1bd1 Iustin Pop
    return backend.BlockdevRename(devlist)
134 f3e513ad Iustin Pop
135 f3e513ad Iustin Pop
  @staticmethod
136 3ecf6786 Iustin Pop
  def perspective_blockdev_assemble(params):
137 3ecf6786 Iustin Pop
    """Assemble a block device.
138 3ecf6786 Iustin Pop
139 3ecf6786 Iustin Pop
    """
140 3f78eef2 Iustin Pop
    bdev_s, owner, on_primary = params
141 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
142 a8083063 Iustin Pop
    if bdev is None:
143 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
144 821d1bd1 Iustin Pop
    return backend.BlockdevAssemble(bdev, owner, on_primary)
145 a8083063 Iustin Pop
146 3ecf6786 Iustin Pop
  @staticmethod
147 3ecf6786 Iustin Pop
  def perspective_blockdev_shutdown(params):
148 3ecf6786 Iustin Pop
    """Shutdown a block device.
149 3ecf6786 Iustin Pop
150 3ecf6786 Iustin Pop
    """
151 a8083063 Iustin Pop
    bdev_s = params[0]
152 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
153 a8083063 Iustin Pop
    if bdev is None:
154 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
155 821d1bd1 Iustin Pop
    return backend.BlockdevShutdown(bdev)
156 a8083063 Iustin Pop
157 3ecf6786 Iustin Pop
  @staticmethod
158 153d9724 Iustin Pop
  def perspective_blockdev_addchildren(params):
159 3ecf6786 Iustin Pop
    """Add a child to a mirror device.
160 3ecf6786 Iustin Pop
161 3ecf6786 Iustin Pop
    Note: this is only valid for mirror devices. It's the caller's duty
162 3ecf6786 Iustin Pop
    to send a correct disk, otherwise we raise an error.
163 3ecf6786 Iustin Pop
164 3ecf6786 Iustin Pop
    """
165 a8083063 Iustin Pop
    bdev_s, ndev_s = params
166 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
167 153d9724 Iustin Pop
    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
168 153d9724 Iustin Pop
    if bdev is None or ndevs.count(None) > 0:
169 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
170 821d1bd1 Iustin Pop
    return backend.BlockdevAddchildren(bdev, ndevs)
171 a8083063 Iustin Pop
172 3ecf6786 Iustin Pop
  @staticmethod
173 153d9724 Iustin Pop
  def perspective_blockdev_removechildren(params):
174 3ecf6786 Iustin Pop
    """Remove a child from a mirror device.
175 3ecf6786 Iustin Pop
176 3ecf6786 Iustin Pop
    This is only valid for mirror devices, of course. It's the callers
177 3ecf6786 Iustin Pop
    duty to send a correct disk, otherwise we raise an error.
178 3ecf6786 Iustin Pop
179 3ecf6786 Iustin Pop
    """
180 a8083063 Iustin Pop
    bdev_s, ndev_s = params
181 319856a9 Michael Hanselmann
    bdev = objects.Disk.FromDict(bdev_s)
182 153d9724 Iustin Pop
    ndevs = [objects.Disk.FromDict(disk_s) for disk_s in ndev_s]
183 153d9724 Iustin Pop
    if bdev is None or ndevs.count(None) > 0:
184 a8083063 Iustin Pop
      raise ValueError("can't unserialize data!")
185 821d1bd1 Iustin Pop
    return backend.BlockdevRemovechildren(bdev, ndevs)
186 a8083063 Iustin Pop
187 3ecf6786 Iustin Pop
  @staticmethod
188 3ecf6786 Iustin Pop
  def perspective_blockdev_getmirrorstatus(params):
189 3ecf6786 Iustin Pop
    """Return the mirror status for a list of disks.
190 3ecf6786 Iustin Pop
191 3ecf6786 Iustin Pop
    """
192 319856a9 Michael Hanselmann
    disks = [objects.Disk.FromDict(dsk_s)
193 a8083063 Iustin Pop
            for dsk_s in params]
194 821d1bd1 Iustin Pop
    return backend.BlockdevGetmirrorstatus(disks)
195 a8083063 Iustin Pop
196 3ecf6786 Iustin Pop
  @staticmethod
197 3ecf6786 Iustin Pop
  def perspective_blockdev_find(params):
198 3ecf6786 Iustin Pop
    """Expose the FindBlockDevice functionality for a disk.
199 3ecf6786 Iustin Pop
200 3ecf6786 Iustin Pop
    This will try to find but not activate a disk.
201 3ecf6786 Iustin Pop
202 3ecf6786 Iustin Pop
    """
203 319856a9 Michael Hanselmann
    disk = objects.Disk.FromDict(params[0])
204 821d1bd1 Iustin Pop
    return backend.BlockdevFind(disk)
205 a8083063 Iustin Pop
206 3ecf6786 Iustin Pop
  @staticmethod
207 3ecf6786 Iustin Pop
  def perspective_blockdev_snapshot(params):
208 3ecf6786 Iustin Pop
    """Create a snapshot device.
209 3ecf6786 Iustin Pop
210 3ecf6786 Iustin Pop
    Note that this is only valid for LVM disks, if we get passed
211 3ecf6786 Iustin Pop
    something else we raise an exception. The snapshot device can be
212 3ecf6786 Iustin Pop
    remove by calling the generic block device remove call.
213 3ecf6786 Iustin Pop
214 3ecf6786 Iustin Pop
    """
215 319856a9 Michael Hanselmann
    cfbd = objects.Disk.FromDict(params[0])
216 821d1bd1 Iustin Pop
    return backend.BlockdevSnapshot(cfbd)
217 a8083063 Iustin Pop
218 4c8ba8b3 Iustin Pop
  @staticmethod
219 4c8ba8b3 Iustin Pop
  def perspective_blockdev_grow(params):
220 4c8ba8b3 Iustin Pop
    """Grow a stack of devices.
221 4c8ba8b3 Iustin Pop
222 4c8ba8b3 Iustin Pop
    """
223 4c8ba8b3 Iustin Pop
    cfbd = objects.Disk.FromDict(params[0])
224 4c8ba8b3 Iustin Pop
    amount = params[1]
225 821d1bd1 Iustin Pop
    return backend.BlockdevGrow(cfbd, amount)
226 4c8ba8b3 Iustin Pop
227 d61cbe76 Iustin Pop
  @staticmethod
228 d61cbe76 Iustin Pop
  def perspective_blockdev_close(params):
229 d61cbe76 Iustin Pop
    """Closes the given block devices.
230 d61cbe76 Iustin Pop
231 d61cbe76 Iustin Pop
    """
232 b2e7666a Iustin Pop
    disks = [objects.Disk.FromDict(cf) for cf in params[1]]
233 821d1bd1 Iustin Pop
    return backend.BlockdevClose(params[0], disks)
234 d61cbe76 Iustin Pop
235 6b93ec9d Iustin Pop
  # blockdev/drbd specific methods ----------
236 6b93ec9d Iustin Pop
237 6b93ec9d Iustin Pop
  @staticmethod
238 6b93ec9d Iustin Pop
  def perspective_drbd_disconnect_net(params):
239 6b93ec9d Iustin Pop
    """Disconnects the network connection of drbd disks.
240 6b93ec9d Iustin Pop
241 6b93ec9d Iustin Pop
    Note that this is only valid for drbd disks, so the members of the
242 6b93ec9d Iustin Pop
    disk list must all be drbd devices.
243 6b93ec9d Iustin Pop
244 6b93ec9d Iustin Pop
    """
245 6b93ec9d Iustin Pop
    nodes_ip, disks = params
246 6b93ec9d Iustin Pop
    disks = [objects.Disk.FromDict(cf) for cf in disks]
247 6b93ec9d Iustin Pop
    return backend.DrbdDisconnectNet(nodes_ip, disks)
248 6b93ec9d Iustin Pop
249 6b93ec9d Iustin Pop
  @staticmethod
250 6b93ec9d Iustin Pop
  def perspective_drbd_attach_net(params):
251 6b93ec9d Iustin Pop
    """Attaches the network connection of drbd disks.
252 6b93ec9d Iustin Pop
253 6b93ec9d Iustin Pop
    Note that this is only valid for drbd disks, so the members of the
254 6b93ec9d Iustin Pop
    disk list must all be drbd devices.
255 6b93ec9d Iustin Pop
256 6b93ec9d Iustin Pop
    """
257 6b93ec9d Iustin Pop
    nodes_ip, disks, instance_name, multimaster = params
258 6b93ec9d Iustin Pop
    disks = [objects.Disk.FromDict(cf) for cf in disks]
259 821d1bd1 Iustin Pop
    return backend.DrbdAttachNet(nodes_ip, disks,
260 821d1bd1 Iustin Pop
                                     instance_name, multimaster)
261 6b93ec9d Iustin Pop
262 6b93ec9d Iustin Pop
  @staticmethod
263 6b93ec9d Iustin Pop
  def perspective_drbd_wait_sync(params):
264 6b93ec9d Iustin Pop
    """Wait until DRBD disks are synched.
265 6b93ec9d Iustin Pop
266 6b93ec9d Iustin Pop
    Note that this is only valid for drbd disks, so the members of the
267 6b93ec9d Iustin Pop
    disk list must all be drbd devices.
268 6b93ec9d Iustin Pop
269 6b93ec9d Iustin Pop
    """
270 6b93ec9d Iustin Pop
    nodes_ip, disks = params
271 6b93ec9d Iustin Pop
    disks = [objects.Disk.FromDict(cf) for cf in disks]
272 6b93ec9d Iustin Pop
    return backend.DrbdWaitSync(nodes_ip, disks)
273 6b93ec9d Iustin Pop
274 a8083063 Iustin Pop
  # export/import  --------------------------
275 a8083063 Iustin Pop
276 3ecf6786 Iustin Pop
  @staticmethod
277 3ecf6786 Iustin Pop
  def perspective_snapshot_export(params):
278 3ecf6786 Iustin Pop
    """Export a given snapshot.
279 3ecf6786 Iustin Pop
280 3ecf6786 Iustin Pop
    """
281 319856a9 Michael Hanselmann
    disk = objects.Disk.FromDict(params[0])
282 a8083063 Iustin Pop
    dest_node = params[1]
283 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[2])
284 62c9ec92 Iustin Pop
    cluster_name = params[3]
285 74c47259 Iustin Pop
    dev_idx = params[4]
286 74c47259 Iustin Pop
    return backend.ExportSnapshot(disk, dest_node, instance,
287 74c47259 Iustin Pop
                                  cluster_name, dev_idx)
288 3ecf6786 Iustin Pop
289 3ecf6786 Iustin Pop
  @staticmethod
290 3ecf6786 Iustin Pop
  def perspective_finalize_export(params):
291 3ecf6786 Iustin Pop
    """Expose the finalize export functionality.
292 a8083063 Iustin Pop
293 3ecf6786 Iustin Pop
    """
294 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
295 319856a9 Michael Hanselmann
    snap_disks = [objects.Disk.FromDict(str_data)
296 a8083063 Iustin Pop
                  for str_data in params[1]]
297 a8083063 Iustin Pop
    return backend.FinalizeExport(instance, snap_disks)
298 a8083063 Iustin Pop
299 3ecf6786 Iustin Pop
  @staticmethod
300 3ecf6786 Iustin Pop
  def perspective_export_info(params):
301 3ecf6786 Iustin Pop
    """Query information about an existing export on this node.
302 3ecf6786 Iustin Pop
303 3ecf6786 Iustin Pop
    The given path may not contain an export, in which case we return
304 3ecf6786 Iustin Pop
    None.
305 3ecf6786 Iustin Pop
306 3ecf6786 Iustin Pop
    """
307 3ecf6786 Iustin Pop
    path = params[0]
308 3ecf6786 Iustin Pop
    einfo = backend.ExportInfo(path)
309 a8083063 Iustin Pop
    if einfo is None:
310 a8083063 Iustin Pop
      return einfo
311 a8083063 Iustin Pop
    return einfo.Dumps()
312 a8083063 Iustin Pop
313 3ecf6786 Iustin Pop
  @staticmethod
314 3ecf6786 Iustin Pop
  def perspective_export_list(params):
315 3ecf6786 Iustin Pop
    """List the available exports on this node.
316 3ecf6786 Iustin Pop
317 3ecf6786 Iustin Pop
    Note that as opposed to export_info, which may query data about an
318 3ecf6786 Iustin Pop
    export in any path, this only queries the standard Ganeti path
319 3ecf6786 Iustin Pop
    (constants.EXPORT_DIR).
320 3ecf6786 Iustin Pop
321 3ecf6786 Iustin Pop
    """
322 a8083063 Iustin Pop
    return backend.ListExports()
323 a8083063 Iustin Pop
324 3ecf6786 Iustin Pop
  @staticmethod
325 3ecf6786 Iustin Pop
  def perspective_export_remove(params):
326 3ecf6786 Iustin Pop
    """Remove an export.
327 3ecf6786 Iustin Pop
328 3ecf6786 Iustin Pop
    """
329 a8083063 Iustin Pop
    export = params[0]
330 a8083063 Iustin Pop
    return backend.RemoveExport(export)
331 a8083063 Iustin Pop
332 a8083063 Iustin Pop
  # volume  --------------------------
333 a8083063 Iustin Pop
334 3ecf6786 Iustin Pop
  @staticmethod
335 3ecf6786 Iustin Pop
  def perspective_volume_list(params):
336 3ecf6786 Iustin Pop
    """Query the list of logical volumes in a given volume group.
337 3ecf6786 Iustin Pop
338 3ecf6786 Iustin Pop
    """
339 a8083063 Iustin Pop
    vgname = params[0]
340 a8083063 Iustin Pop
    return backend.GetVolumeList(vgname)
341 a8083063 Iustin Pop
342 3ecf6786 Iustin Pop
  @staticmethod
343 3ecf6786 Iustin Pop
  def perspective_vg_list(params):
344 3ecf6786 Iustin Pop
    """Query the list of volume groups.
345 3ecf6786 Iustin Pop
346 3ecf6786 Iustin Pop
    """
347 a8083063 Iustin Pop
    return backend.ListVolumeGroups()
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
  # bridge  --------------------------
350 a8083063 Iustin Pop
351 3ecf6786 Iustin Pop
  @staticmethod
352 3ecf6786 Iustin Pop
  def perspective_bridges_exist(params):
353 3ecf6786 Iustin Pop
    """Check if all bridges given exist on this node.
354 3ecf6786 Iustin Pop
355 3ecf6786 Iustin Pop
    """
356 a8083063 Iustin Pop
    bridges_list = params[0]
357 a8083063 Iustin Pop
    return backend.BridgesExist(bridges_list)
358 a8083063 Iustin Pop
359 a8083063 Iustin Pop
  # instance  --------------------------
360 a8083063 Iustin Pop
361 3ecf6786 Iustin Pop
  @staticmethod
362 3ecf6786 Iustin Pop
  def perspective_instance_os_add(params):
363 3ecf6786 Iustin Pop
    """Install an OS on a given instance.
364 3ecf6786 Iustin Pop
365 3ecf6786 Iustin Pop
    """
366 d15a9ad3 Guido Trotter
    inst_s = params[0]
367 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
368 1268d6fd Iustin Pop
    return backend.InstanceOsAdd(inst)
369 a8083063 Iustin Pop
370 3ecf6786 Iustin Pop
  @staticmethod
371 decd5f45 Iustin Pop
  def perspective_instance_run_rename(params):
372 decd5f45 Iustin Pop
    """Runs the OS rename script for an instance.
373 decd5f45 Iustin Pop
374 decd5f45 Iustin Pop
    """
375 d15a9ad3 Guido Trotter
    inst_s, old_name = params
376 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
377 d15a9ad3 Guido Trotter
    return backend.RunRenameInstance(inst, old_name)
378 decd5f45 Iustin Pop
379 decd5f45 Iustin Pop
  @staticmethod
380 3ecf6786 Iustin Pop
  def perspective_instance_os_import(params):
381 3ecf6786 Iustin Pop
    """Run the import function of an OS onto a given instance.
382 3ecf6786 Iustin Pop
383 3ecf6786 Iustin Pop
    """
384 6c0af70e Guido Trotter
    inst_s, src_node, src_images, cluster_name = params
385 319856a9 Michael Hanselmann
    inst = objects.Instance.FromDict(inst_s)
386 6c0af70e Guido Trotter
    return backend.ImportOSIntoInstance(inst, src_node, src_images,
387 6c0af70e Guido Trotter
                                        cluster_name)
388 a8083063 Iustin Pop
389 3ecf6786 Iustin Pop
  @staticmethod
390 3ecf6786 Iustin Pop
  def perspective_instance_shutdown(params):
391 3ecf6786 Iustin Pop
    """Shutdown an instance.
392 3ecf6786 Iustin Pop
393 3ecf6786 Iustin Pop
    """
394 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
395 1fae010f Iustin Pop
    return backend.InstanceShutdown(instance)
396 a8083063 Iustin Pop
397 3ecf6786 Iustin Pop
  @staticmethod
398 3ecf6786 Iustin Pop
  def perspective_instance_start(params):
399 3ecf6786 Iustin Pop
    """Start an instance.
400 3ecf6786 Iustin Pop
401 3ecf6786 Iustin Pop
    """
402 319856a9 Michael Hanselmann
    instance = objects.Instance.FromDict(params[0])
403 a8083063 Iustin Pop
    extra_args = params[1]
404 a8083063 Iustin Pop
    return backend.StartInstance(instance, extra_args)
405 a8083063 Iustin Pop
406 3ecf6786 Iustin Pop
  @staticmethod
407 6906a9d8 Guido Trotter
  def perspective_migration_info(params):
408 6906a9d8 Guido Trotter
    """Gather information about an instance to be migrated.
409 6906a9d8 Guido Trotter
410 6906a9d8 Guido Trotter
    """
411 6906a9d8 Guido Trotter
    instance = objects.Instance.FromDict(params[0])
412 6906a9d8 Guido Trotter
    return backend.MigrationInfo(instance)
413 6906a9d8 Guido Trotter
414 6906a9d8 Guido Trotter
  @staticmethod
415 6906a9d8 Guido Trotter
  def perspective_accept_instance(params):
416 6906a9d8 Guido Trotter
    """Prepare the node to accept an instance.
417 6906a9d8 Guido Trotter
418 6906a9d8 Guido Trotter
    """
419 6906a9d8 Guido Trotter
    instance, info, target = params
420 6906a9d8 Guido Trotter
    instance = objects.Instance.FromDict(instance)
421 6906a9d8 Guido Trotter
    return backend.AcceptInstance(instance, info, target)
422 6906a9d8 Guido Trotter
423 6906a9d8 Guido Trotter
  @staticmethod
424 6906a9d8 Guido Trotter
  def perspective_finalize_migration(params):
425 6906a9d8 Guido Trotter
    """Finalize the instance migration.
426 6906a9d8 Guido Trotter
427 6906a9d8 Guido Trotter
    """
428 6906a9d8 Guido Trotter
    instance, info, success = params
429 6906a9d8 Guido Trotter
    instance = objects.Instance.FromDict(instance)
430 6906a9d8 Guido Trotter
    return backend.FinalizeMigration(instance, info, success)
431 6906a9d8 Guido Trotter
432 6906a9d8 Guido Trotter
  @staticmethod
433 2a10865c Iustin Pop
  def perspective_instance_migrate(params):
434 2a10865c Iustin Pop
    """Migrates an instance.
435 2a10865c Iustin Pop
436 2a10865c Iustin Pop
    """
437 2a10865c Iustin Pop
    instance, target, live = params
438 9f0e6b37 Iustin Pop
    instance = objects.Instance.FromDict(instance)
439 2a10865c Iustin Pop
    return backend.MigrateInstance(instance, target, live)
440 2a10865c Iustin Pop
441 2a10865c Iustin Pop
  @staticmethod
442 007a2f3e Alexander Schreiber
  def perspective_instance_reboot(params):
443 007a2f3e Alexander Schreiber
    """Reboot an instance.
444 007a2f3e Alexander Schreiber
445 007a2f3e Alexander Schreiber
    """
446 007a2f3e Alexander Schreiber
    instance = objects.Instance.FromDict(params[0])
447 007a2f3e Alexander Schreiber
    reboot_type = params[1]
448 007a2f3e Alexander Schreiber
    extra_args = params[2]
449 489fcbe9 Iustin Pop
    return backend.InstanceReboot(instance, reboot_type, extra_args)
450 007a2f3e Alexander Schreiber
451 007a2f3e Alexander Schreiber
  @staticmethod
452 3ecf6786 Iustin Pop
  def perspective_instance_info(params):
453 3ecf6786 Iustin Pop
    """Query instance information.
454 3ecf6786 Iustin Pop
455 3ecf6786 Iustin Pop
    """
456 16ad1a83 Iustin Pop
    return backend.GetInstanceInfo(params[0], params[1])
457 a8083063 Iustin Pop
458 3ecf6786 Iustin Pop
  @staticmethod
459 56e7640c Iustin Pop
  def perspective_instance_migratable(params):
460 56e7640c Iustin Pop
    """Query whether the specified instance can be migrated.
461 56e7640c Iustin Pop
462 56e7640c Iustin Pop
    """
463 56e7640c Iustin Pop
    instance = objects.Instance.FromDict(params[0])
464 56e7640c Iustin Pop
    return backend.GetInstanceMigratable(instance)
465 56e7640c Iustin Pop
466 56e7640c Iustin Pop
  @staticmethod
467 3ecf6786 Iustin Pop
  def perspective_all_instances_info(params):
468 3ecf6786 Iustin Pop
    """Query information about all instances.
469 3ecf6786 Iustin Pop
470 3ecf6786 Iustin Pop
    """
471 e69d05fd Iustin Pop
    return backend.GetAllInstancesInfo(params[0])
472 a8083063 Iustin Pop
473 3ecf6786 Iustin Pop
  @staticmethod
474 3ecf6786 Iustin Pop
  def perspective_instance_list(params):
475 3ecf6786 Iustin Pop
    """Query the list of running instances.
476 3ecf6786 Iustin Pop
477 3ecf6786 Iustin Pop
    """
478 e69d05fd Iustin Pop
    return backend.GetInstanceList(params[0])
479 a8083063 Iustin Pop
480 a8083063 Iustin Pop
  # node --------------------------
481 a8083063 Iustin Pop
482 3ecf6786 Iustin Pop
  @staticmethod
483 16abfbc2 Alexander Schreiber
  def perspective_node_tcp_ping(params):
484 16abfbc2 Alexander Schreiber
    """Do a TcpPing on the remote node.
485 16abfbc2 Alexander Schreiber
486 16abfbc2 Alexander Schreiber
    """
487 b15d625f Iustin Pop
    return utils.TcpPing(params[1], params[2], timeout=params[3],
488 b15d625f Iustin Pop
                         live_port_needed=params[4], source=params[0])
489 16abfbc2 Alexander Schreiber
490 16abfbc2 Alexander Schreiber
  @staticmethod
491 caad16e2 Iustin Pop
  def perspective_node_has_ip_address(params):
492 caad16e2 Iustin Pop
    """Checks if a node has the given ip address.
493 caad16e2 Iustin Pop
494 caad16e2 Iustin Pop
    """
495 caad16e2 Iustin Pop
    return utils.OwnIpAddress(params[0])
496 caad16e2 Iustin Pop
497 caad16e2 Iustin Pop
  @staticmethod
498 3ecf6786 Iustin Pop
  def perspective_node_info(params):
499 3ecf6786 Iustin Pop
    """Query node information.
500 3ecf6786 Iustin Pop
501 3ecf6786 Iustin Pop
    """
502 e69d05fd Iustin Pop
    vgname, hypervisor_type = params
503 e69d05fd Iustin Pop
    return backend.GetNodeInfo(vgname, hypervisor_type)
504 a8083063 Iustin Pop
505 3ecf6786 Iustin Pop
  @staticmethod
506 3ecf6786 Iustin Pop
  def perspective_node_add(params):
507 3ecf6786 Iustin Pop
    """Complete the registration of this node in the cluster.
508 3ecf6786 Iustin Pop
509 3ecf6786 Iustin Pop
    """
510 a8083063 Iustin Pop
    return backend.AddNode(params[0], params[1], params[2],
511 a8083063 Iustin Pop
                           params[3], params[4], params[5])
512 a8083063 Iustin Pop
513 3ecf6786 Iustin Pop
  @staticmethod
514 3ecf6786 Iustin Pop
  def perspective_node_verify(params):
515 3ecf6786 Iustin Pop
    """Run a verify sequence on this node.
516 3ecf6786 Iustin Pop
517 3ecf6786 Iustin Pop
    """
518 62c9ec92 Iustin Pop
    return backend.VerifyNode(params[0], params[1])
519 a8083063 Iustin Pop
520 3ecf6786 Iustin Pop
  @staticmethod
521 3ecf6786 Iustin Pop
  def perspective_node_start_master(params):
522 3ecf6786 Iustin Pop
    """Promote this node to master status.
523 3ecf6786 Iustin Pop
524 3ecf6786 Iustin Pop
    """
525 1c65840b Iustin Pop
    return backend.StartMaster(params[0])
526 a8083063 Iustin Pop
527 3ecf6786 Iustin Pop
  @staticmethod
528 3ecf6786 Iustin Pop
  def perspective_node_stop_master(params):
529 3ecf6786 Iustin Pop
    """Demote this node from master status.
530 3ecf6786 Iustin Pop
531 3ecf6786 Iustin Pop
    """
532 1c65840b Iustin Pop
    return backend.StopMaster(params[0])
533 a8083063 Iustin Pop
534 3ecf6786 Iustin Pop
  @staticmethod
535 3ecf6786 Iustin Pop
  def perspective_node_leave_cluster(params):
536 3ecf6786 Iustin Pop
    """Cleanup after leaving a cluster.
537 3ecf6786 Iustin Pop
538 3ecf6786 Iustin Pop
    """
539 a8083063 Iustin Pop
    return backend.LeaveCluster()
540 a8083063 Iustin Pop
541 3ecf6786 Iustin Pop
  @staticmethod
542 3ecf6786 Iustin Pop
  def perspective_node_volumes(params):
543 3ecf6786 Iustin Pop
    """Query the list of all logical volume groups.
544 3ecf6786 Iustin Pop
545 3ecf6786 Iustin Pop
    """
546 dcb93971 Michael Hanselmann
    return backend.NodeVolumes()
547 dcb93971 Michael Hanselmann
548 56aa9fd5 Iustin Pop
  @staticmethod
549 56aa9fd5 Iustin Pop
  def perspective_node_demote_from_mc(params):
550 56aa9fd5 Iustin Pop
    """Demote a node from the master candidate role.
551 56aa9fd5 Iustin Pop
552 56aa9fd5 Iustin Pop
    """
553 56aa9fd5 Iustin Pop
    return backend.DemoteFromMC()
554 56aa9fd5 Iustin Pop
555 56aa9fd5 Iustin Pop
556 a8083063 Iustin Pop
  # cluster --------------------------
557 a8083063 Iustin Pop
558 3ecf6786 Iustin Pop
  @staticmethod
559 3ecf6786 Iustin Pop
  def perspective_version(params):
560 3ecf6786 Iustin Pop
    """Query version information.
561 3ecf6786 Iustin Pop
562 3ecf6786 Iustin Pop
    """
563 a8083063 Iustin Pop
    return constants.PROTOCOL_VERSION
564 a8083063 Iustin Pop
565 3ecf6786 Iustin Pop
  @staticmethod
566 3ecf6786 Iustin Pop
  def perspective_upload_file(params):
567 3ecf6786 Iustin Pop
    """Upload a file.
568 3ecf6786 Iustin Pop
569 3ecf6786 Iustin Pop
    Note that the backend implementation imposes strict rules on which
570 3ecf6786 Iustin Pop
    files are accepted.
571 3ecf6786 Iustin Pop
572 3ecf6786 Iustin Pop
    """
573 a8083063 Iustin Pop
    return backend.UploadFile(*params)
574 a8083063 Iustin Pop
575 4e071d3b Iustin Pop
  @staticmethod
576 4e071d3b Iustin Pop
  def perspective_master_info(params):
577 4e071d3b Iustin Pop
    """Query master information.
578 4e071d3b Iustin Pop
579 4e071d3b Iustin Pop
    """
580 4e071d3b Iustin Pop
    return backend.GetMasterInfo()
581 a8083063 Iustin Pop
582 6ddc95ec Michael Hanselmann
  @staticmethod
583 6ddc95ec Michael Hanselmann
  def perspective_write_ssconf_files(params):
584 6ddc95ec Michael Hanselmann
    """Write ssconf files.
585 6ddc95ec Michael Hanselmann
586 6ddc95ec Michael Hanselmann
    """
587 03d1dba2 Michael Hanselmann
    (values,) = params
588 03d1dba2 Michael Hanselmann
    return backend.WriteSsconfFiles(values)
589 6ddc95ec Michael Hanselmann
590 a8083063 Iustin Pop
  # os -----------------------
591 a8083063 Iustin Pop
592 3ecf6786 Iustin Pop
  @staticmethod
593 3ecf6786 Iustin Pop
  def perspective_os_diagnose(params):
594 3ecf6786 Iustin Pop
    """Query detailed information about existing OSes.
595 3ecf6786 Iustin Pop
596 3ecf6786 Iustin Pop
    """
597 821d1bd1 Iustin Pop
    return [os_obj.ToDict() for os_obj in backend.DiagnoseOS()]
598 a8083063 Iustin Pop
599 3ecf6786 Iustin Pop
  @staticmethod
600 3ecf6786 Iustin Pop
  def perspective_os_get(params):
601 3ecf6786 Iustin Pop
    """Query information about a given OS.
602 3ecf6786 Iustin Pop
603 3ecf6786 Iustin Pop
    """
604 a8083063 Iustin Pop
    name = params[0]
605 a8083063 Iustin Pop
    try:
606 dfa96ded Guido Trotter
      os_obj = backend.OSFromDisk(name)
607 a8083063 Iustin Pop
    except errors.InvalidOS, err:
608 dfa96ded Guido Trotter
      os_obj = objects.OS.FromInvalidOS(err)
609 dfa96ded Guido Trotter
    return os_obj.ToDict()
610 a8083063 Iustin Pop
611 a8083063 Iustin Pop
  # hooks -----------------------
612 a8083063 Iustin Pop
613 3ecf6786 Iustin Pop
  @staticmethod
614 3ecf6786 Iustin Pop
  def perspective_hooks_runner(params):
615 3ecf6786 Iustin Pop
    """Run hook scripts.
616 3ecf6786 Iustin Pop
617 3ecf6786 Iustin Pop
    """
618 a8083063 Iustin Pop
    hpath, phase, env = params
619 a8083063 Iustin Pop
    hr = backend.HooksRunner()
620 a8083063 Iustin Pop
    return hr.RunHooks(hpath, phase, env)
621 a8083063 Iustin Pop
622 8d528b7c Iustin Pop
  # iallocator -----------------
623 8d528b7c Iustin Pop
624 8d528b7c Iustin Pop
  @staticmethod
625 8d528b7c Iustin Pop
  def perspective_iallocator_runner(params):
626 8d528b7c Iustin Pop
    """Run an iallocator script.
627 8d528b7c Iustin Pop
628 8d528b7c Iustin Pop
    """
629 8d528b7c Iustin Pop
    name, idata = params
630 8d528b7c Iustin Pop
    iar = backend.IAllocatorRunner()
631 8d528b7c Iustin Pop
    return iar.Run(name, idata)
632 8d528b7c Iustin Pop
633 06009e27 Iustin Pop
  # test -----------------------
634 06009e27 Iustin Pop
635 06009e27 Iustin Pop
  @staticmethod
636 06009e27 Iustin Pop
  def perspective_test_delay(params):
637 06009e27 Iustin Pop
    """Run test delay.
638 06009e27 Iustin Pop
639 06009e27 Iustin Pop
    """
640 06009e27 Iustin Pop
    duration = params[0]
641 06009e27 Iustin Pop
    return utils.TestDelay(duration)
642 06009e27 Iustin Pop
643 4e071d3b Iustin Pop
  # file storage ---------------
644 4e071d3b Iustin Pop
645 a5d7fb43 Manuel Franceschini
  @staticmethod
646 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_create(params):
647 a5d7fb43 Manuel Franceschini
    """Create the file storage directory.
648 a5d7fb43 Manuel Franceschini
649 a5d7fb43 Manuel Franceschini
    """
650 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
651 a5d7fb43 Manuel Franceschini
    return backend.CreateFileStorageDir(file_storage_dir)
652 a5d7fb43 Manuel Franceschini
653 a5d7fb43 Manuel Franceschini
  @staticmethod
654 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_remove(params):
655 a5d7fb43 Manuel Franceschini
    """Remove the file storage directory.
656 a5d7fb43 Manuel Franceschini
657 a5d7fb43 Manuel Franceschini
    """
658 a5d7fb43 Manuel Franceschini
    file_storage_dir = params[0]
659 a5d7fb43 Manuel Franceschini
    return backend.RemoveFileStorageDir(file_storage_dir)
660 a5d7fb43 Manuel Franceschini
661 a5d7fb43 Manuel Franceschini
  @staticmethod
662 a5d7fb43 Manuel Franceschini
  def perspective_file_storage_dir_rename(params):
663 a5d7fb43 Manuel Franceschini
    """Rename the file storage directory.
664 a5d7fb43 Manuel Franceschini
665 a5d7fb43 Manuel Franceschini
    """
666 a5d7fb43 Manuel Franceschini
    old_file_storage_dir = params[0]
667 a5d7fb43 Manuel Franceschini
    new_file_storage_dir = params[1]
668 a5d7fb43 Manuel Franceschini
    return backend.RenameFileStorageDir(old_file_storage_dir,
669 a5d7fb43 Manuel Franceschini
                                        new_file_storage_dir)
670 a5d7fb43 Manuel Franceschini
671 4e071d3b Iustin Pop
  # jobs ------------------------
672 4e071d3b Iustin Pop
673 ca52cdeb Michael Hanselmann
  @staticmethod
674 7f30777b Michael Hanselmann
  @_RequireJobQueueLock
675 ca52cdeb Michael Hanselmann
  def perspective_jobqueue_update(params):
676 ca52cdeb Michael Hanselmann
    """Update job queue.
677 ca52cdeb Michael Hanselmann
678 ca52cdeb Michael Hanselmann
    """
679 ca52cdeb Michael Hanselmann
    (file_name, content) = params
680 7f30777b Michael Hanselmann
    return backend.JobQueueUpdate(file_name, content)
681 ca52cdeb Michael Hanselmann
682 ca52cdeb Michael Hanselmann
  @staticmethod
683 f1f3f45c Michael Hanselmann
  @_RequireJobQueueLock
684 ca52cdeb Michael Hanselmann
  def perspective_jobqueue_purge(params):
685 ca52cdeb Michael Hanselmann
    """Purge job queue.
686 ca52cdeb Michael Hanselmann
687 ca52cdeb Michael Hanselmann
    """
688 ca52cdeb Michael Hanselmann
    return backend.JobQueuePurge()
689 ca52cdeb Michael Hanselmann
690 af5ebcb1 Michael Hanselmann
  @staticmethod
691 af5ebcb1 Michael Hanselmann
  @_RequireJobQueueLock
692 af5ebcb1 Michael Hanselmann
  def perspective_jobqueue_rename(params):
693 af5ebcb1 Michael Hanselmann
    """Rename a job queue file.
694 af5ebcb1 Michael Hanselmann
695 af5ebcb1 Michael Hanselmann
    """
696 dd875d32 Michael Hanselmann
    # TODO: What if a file fails to rename?
697 dd875d32 Michael Hanselmann
    return [backend.JobQueueRename(old, new) for old, new in params]
698 af5ebcb1 Michael Hanselmann
699 5d672980 Iustin Pop
  @staticmethod
700 5d672980 Iustin Pop
  def perspective_jobqueue_set_drain(params):
701 5d672980 Iustin Pop
    """Set/unset the queue drain flag.
702 5d672980 Iustin Pop
703 5d672980 Iustin Pop
    """
704 5d672980 Iustin Pop
    drain_flag = params[0]
705 5d672980 Iustin Pop
    return backend.JobQueueSetDrainFlag(drain_flag)
706 5d672980 Iustin Pop
707 5d672980 Iustin Pop
708 6217e295 Iustin Pop
  # hypervisor ---------------
709 6217e295 Iustin Pop
710 6217e295 Iustin Pop
  @staticmethod
711 6217e295 Iustin Pop
  def perspective_hypervisor_validate_params(params):
712 6217e295 Iustin Pop
    """Validate the hypervisor parameters.
713 6217e295 Iustin Pop
714 6217e295 Iustin Pop
    """
715 6217e295 Iustin Pop
    (hvname, hvparams) = params
716 6217e295 Iustin Pop
    return backend.ValidateHVParams(hvname, hvparams)
717 6217e295 Iustin Pop
718 a8083063 Iustin Pop
719 a8083063 Iustin Pop
def ParseOptions():
720 a8083063 Iustin Pop
  """Parse the command line options.
721 a8083063 Iustin Pop
722 c41eea6e Iustin Pop
  @return: (options, args) as from OptionParser.parse_args()
723 a8083063 Iustin Pop
724 a8083063 Iustin Pop
  """
725 a8083063 Iustin Pop
  parser = OptionParser(description="Ganeti node daemon",
726 a8083063 Iustin Pop
                        usage="%prog [-f] [-d]",
727 a8083063 Iustin Pop
                        version="%%prog (ganeti) %s" %
728 a8083063 Iustin Pop
                        constants.RELEASE_VERSION)
729 a8083063 Iustin Pop
730 a8083063 Iustin Pop
  parser.add_option("-f", "--foreground", dest="fork",
731 a8083063 Iustin Pop
                    help="Don't detach from the current terminal",
732 a8083063 Iustin Pop
                    default=True, action="store_false")
733 a8083063 Iustin Pop
  parser.add_option("-d", "--debug", dest="debug",
734 a8083063 Iustin Pop
                    help="Enable some debug messages",
735 a8083063 Iustin Pop
                    default=False, action="store_true")
736 a8083063 Iustin Pop
  options, args = parser.parse_args()
737 a8083063 Iustin Pop
  return options, args
738 a8083063 Iustin Pop
739 a8083063 Iustin Pop
740 8adbffaa Iustin Pop
def EnsureRuntimeEnvironment():
741 8adbffaa Iustin Pop
  """Ensure our run-time environment is complete.
742 8adbffaa Iustin Pop
743 8adbffaa Iustin Pop
  Currently this creates directories which could be missing, either
744 8adbffaa Iustin Pop
  due to directories being on a tmpfs mount, or due to incomplete
745 8adbffaa Iustin Pop
  packaging.
746 8adbffaa Iustin Pop
747 8adbffaa Iustin Pop
  """
748 817a030d Guido Trotter
  dirs = [(val, constants.RUN_DIRS_MODE) for val in constants.SUB_RUN_DIRS]
749 8adbffaa Iustin Pop
  dirs.append((constants.LOG_OS_DIR, 0750))
750 f2ffd244 Guido Trotter
  dirs.append((constants.LOCK_DIR, 1777))
751 8adbffaa Iustin Pop
  for dir_name, dir_mode in dirs:
752 8adbffaa Iustin Pop
    if not os.path.exists(dir_name):
753 8adbffaa Iustin Pop
      try:
754 8adbffaa Iustin Pop
        os.mkdir(dir_name, dir_mode)
755 8adbffaa Iustin Pop
      except EnvironmentError, err:
756 8adbffaa Iustin Pop
        if err.errno != errno.EEXIST:
757 8adbffaa Iustin Pop
          print ("Node setup wrong, cannot create directory '%s': %s" %
758 8adbffaa Iustin Pop
                 (dir_name, err))
759 8adbffaa Iustin Pop
          sys.exit(5)
760 8adbffaa Iustin Pop
    if not os.path.isdir(dir_name):
761 8adbffaa Iustin Pop
      print ("Node setup wrong, '%s' is not a directory" % dir_name)
762 8adbffaa Iustin Pop
      sys.exit(5)
763 8adbffaa Iustin Pop
764 8adbffaa Iustin Pop
765 a8083063 Iustin Pop
def main():
766 3ecf6786 Iustin Pop
  """Main function for the node daemon.
767 3ecf6786 Iustin Pop
768 3ecf6786 Iustin Pop
  """
769 25d6d12a Michael Hanselmann
  global queue_lock
770 25d6d12a Michael Hanselmann
771 a8083063 Iustin Pop
  options, args = ParseOptions()
772 f362096f Iustin Pop
  utils.debug = options.debug
773 7d88772a Iustin Pop
774 7d88772a Iustin Pop
  if options.fork:
775 7d88772a Iustin Pop
    utils.CloseFDs()
776 7d88772a Iustin Pop
777 a8083063 Iustin Pop
  for fname in (constants.SSL_CERT_FILE,):
778 a8083063 Iustin Pop
    if not os.path.isfile(fname):
779 a8083063 Iustin Pop
      print "config %s not there, will not run." % fname
780 a8083063 Iustin Pop
      sys.exit(5)
781 a8083063 Iustin Pop
782 a8083063 Iustin Pop
  try:
783 8594f271 Michael Hanselmann
    port = utils.GetNodeDaemonPort()
784 a8083063 Iustin Pop
  except errors.ConfigurationError, err:
785 a8083063 Iustin Pop
    print "Cluster configuration incomplete: '%s'" % str(err)
786 a8083063 Iustin Pop
    sys.exit(5)
787 a8083063 Iustin Pop
788 8adbffaa Iustin Pop
  EnsureRuntimeEnvironment()
789 0214b0c0 Iustin Pop
790 a8083063 Iustin Pop
  # become a daemon
791 a8083063 Iustin Pop
  if options.fork:
792 8f765069 Iustin Pop
    utils.Daemonize(logfile=constants.LOG_NODESERVER)
793 a8083063 Iustin Pop
794 99e88451 Iustin Pop
  utils.WritePidFile(constants.NODED_PID)
795 cc28af80 Michael Hanselmann
  try:
796 82d9caef Iustin Pop
    utils.SetupLogging(logfile=constants.LOG_NODESERVER, debug=options.debug,
797 82d9caef Iustin Pop
                       stderr_logging=not options.fork)
798 cc28af80 Michael Hanselmann
    logging.info("ganeti node daemon startup")
799 73d927a2 Guido Trotter
800 eafd8762 Michael Hanselmann
    # Read SSL certificate
801 eafd8762 Michael Hanselmann
    ssl_params = http.HttpSslParams(ssl_key_path=constants.SSL_CERT_FILE,
802 eafd8762 Michael Hanselmann
                                    ssl_cert_path=constants.SSL_CERT_FILE)
803 eafd8762 Michael Hanselmann
804 cc28af80 Michael Hanselmann
    # Prepare job queue
805 cc28af80 Michael Hanselmann
    queue_lock = jstore.InitAndVerifyQueue(must_lock=False)
806 a8083063 Iustin Pop
807 cc28af80 Michael Hanselmann
    mainloop = daemon.Mainloop()
808 eafd8762 Michael Hanselmann
    server = NodeHttpServer(mainloop, "", port,
809 eafd8762 Michael Hanselmann
                            ssl_params=ssl_params, ssl_verify_peer=True)
810 cc28af80 Michael Hanselmann
    server.Start()
811 cc28af80 Michael Hanselmann
    try:
812 cc28af80 Michael Hanselmann
      mainloop.Run()
813 cc28af80 Michael Hanselmann
    finally:
814 cc28af80 Michael Hanselmann
      server.Stop()
815 73d927a2 Guido Trotter
  finally:
816 99e88451 Iustin Pop
    utils.RemovePidFile(constants.NODED_PID)
817 73d927a2 Guido Trotter
818 a8083063 Iustin Pop
819 3ecf6786 Iustin Pop
if __name__ == '__main__':
820 a8083063 Iustin Pop
  main()