Statistics
| Branch: | Tag: | Revision:

root / daemons / ganeti-noded @ 0623d351

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