Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ b726aff0

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