~free.ekanayaka/landscape-client/lucid-1.5.4-0ubuntu0.10.04.0

« back to all changes in this revision

Viewing changes to landscape/deployment.py

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2010-06-28 18:07:18 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100628180718-vytyqgbtkiirv5sb
Tags: 1.5.2.1-0ubuntu0.10.04.0
Filter duplicate network interfaces in get_active_interfaces (LP: #597000)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import signal
2
1
import os
3
2
import sys
4
 
import pwd
5
3
 
6
4
from logging import (getLevelName, getLogger,
7
 
                     FileHandler, StreamHandler, Formatter, info)
 
5
                     FileHandler, StreamHandler, Formatter)
8
6
 
9
7
from optparse import OptionParser
10
8
from ConfigParser import ConfigParser, NoSectionError
11
9
 
12
 
import dbus.glib # Side-effects rule!
13
 
 
14
 
from twisted.application.service import Application, Service
15
 
from twisted.application.app import startApplication
16
 
 
17
10
from landscape import VERSION
18
11
from landscape.lib.persist import Persist
19
 
from landscape.lib.dbus_util import get_bus
20
 
from landscape.lib import bpickle_dbus
21
 
from landscape.log import rotate_logs
22
 
from landscape.reactor import TwistedReactor
23
12
 
24
13
from landscape.upgraders import UPGRADE_MANAGERS
25
14
 
162
151
            if not getattr(self, option):
163
152
                sys.exit("error: must specify --%s "
164
153
                         "or the '%s' directive in the config file."
165
 
                         % (option.replace('_','-'), option))
166
 
 
167
 
        if self.bus not in ("session", "system"):
168
 
            sys.exit("error: bus must be one of 'session' or 'system'")
 
154
                         % (option.replace('_', '-'), option))
169
155
 
170
156
    def _load_external_options(self):
171
157
        """Hook for loading options from elsewhere (e.g. for --import)."""
234
220
        @return: An L{OptionParser} preset with options that all
235
221
            landscape-related programs accept. These include
236
222
              - C{config} (C{None})
237
 
              - C{bus} (C{system})
238
223
        """
239
224
        parser = OptionParser(version=VERSION)
240
225
        parser.add_option("-c", "--config", metavar="FILE",
241
226
                          help="Use config from this file (any command line "
242
227
                               "options override settings from the file) "
243
228
                               "(default: '/etc/landscape/client.conf').")
244
 
        parser.add_option("--bus", default="system",
245
 
                          help="Which DBUS bus to use. One of 'session' "
246
 
                               "or 'system' (default: 'system').")
247
229
        return parser
248
230
 
249
231
    def get_config_filename(self):
279
261
    This contains all simple data, some of it calculated.
280
262
    """
281
263
 
282
 
    @property
283
 
    def hashdb_filename(self):
284
 
        return os.path.join(self.data_path, "hash.db")
285
 
 
286
264
    def make_parser(self):
287
265
        """Parser factory for supported options.
288
266
 
308
286
        parser.add_option("--log-level", default="info",
309
287
                          help="One of debug, info, warning, error or "
310
288
                               "critical.")
311
 
        parser.add_option("--ignore-sigint", action="store_true", default=False,
312
 
                          help="Ignore interrupt signals.")
313
 
        parser.add_option("--ignore-sigusr1", action="store_true", default=False,
314
 
                          help="Ignore SIGUSR1 signal to rotate logs.")
 
289
        parser.add_option("--ignore-sigint", action="store_true",
 
290
                          default=False, help="Ignore interrupt signals.")
 
291
        parser.add_option("--ignore-sigusr1", action="store_true",
 
292
                          default=False, help="Ignore SIGUSR1 signal to "
 
293
                                              "rotate logs.")
315
294
 
316
295
        return parser
317
296
 
 
297
    @property
 
298
    def sockets_path(self):
 
299
        """Return the path to the directory where Unix sockets are created."""
 
300
        return os.path.join(self.data_path, "sockets")
 
301
 
318
302
 
319
303
def get_versioned_persist(service):
320
304
    """Get a L{Persist} database with upgrade rules applied.
330
314
        upgrade_manager.initialize(persist)
331
315
    persist.save(service.persist_filename)
332
316
    return persist
333
 
 
334
 
 
335
 
class LandscapeService(Service, object):
336
 
    """Utility superclass for defining Landscape services.
337
 
 
338
 
    This sets up the reactor, bpickle/dbus integration, a Persist object, and
339
 
    connects to the bus when started.
340
 
 
341
 
    @ivar reactor: a L{TwistedReactor} object.
342
 
    @cvar service_name: The lower-case name of the service. This is used to
343
 
        generate the bpickle filename.
344
 
    """
345
 
    reactor_factory = TwistedReactor
346
 
    persist_filename = None
347
 
 
348
 
    def __init__(self, config):
349
 
        self.config = config
350
 
        bpickle_dbus.install()
351
 
        self.reactor = self.reactor_factory()
352
 
        if self.persist_filename:
353
 
            self.persist = get_versioned_persist(self)
354
 
        if not (self.config is not None and self.config.ignore_sigusr1):
355
 
            signal.signal(signal.SIGUSR1, lambda signal, frame: rotate_logs())
356
 
 
357
 
    def startService(self):
358
 
        """Extend L{twisted.application.service.IService.startService}.
359
 
 
360
 
        Create a a new DBus connection (normally using a C{SystemBus}) and
361
 
        save it in the public L{self.bus} instance variable.
362
 
        """
363
 
        Service.startService(self)
364
 
        self.bus = get_bus(self.config.bus)
365
 
        info("%s started on '%s' bus with config %s" % (
366
 
                self.service_name.capitalize(), self.config.bus,
367
 
                self.config.get_config_filename()))
368
 
 
369
 
    def stopService(self):
370
 
        Service.stopService(self)
371
 
        info("%s stopped on '%s' bus with config %s" % (
372
 
                self.service_name.capitalize(), self.config.bus,
373
 
                self.config.get_config_filename()))
374
 
 
375
 
 
376
 
def assert_unowned_bus_name(bus, bus_name):
377
 
    dbus_object = bus.get_object("org.freedesktop.DBus",
378
 
                                 "/org/freedesktop/DBus")
379
 
    if dbus_object.NameHasOwner(bus_name,
380
 
                                dbus_interface="org.freedesktop.DBus"):
381
 
        sys.exit("error: DBus name %s is owned. "
382
 
                 "Is the process already running?" % bus_name)
383
 
 
384
 
 
385
 
_required_users = {
386
 
    "broker": "landscape",
387
 
    "monitor": "landscape",
388
 
    "manager": "root"}
389
 
 
390
 
 
391
 
def run_landscape_service(configuration_class, service_class, args, bus_name):
392
 
    """Run a Landscape service.
393
 
 
394
 
    The function will instantiate the given L{LandscapeService} subclass
395
 
    and attach the resulting service object to a Twisted C{Application}.
396
 
 
397
 
    After that it will start the Twisted L{Application} and call the
398
 
    L{TwistedReactor.run} method of the L{LandscapeService}'s reactor.
399
 
 
400
 
    @param configuration_class: The service-specific subclass of L{Configuration} used
401
 
        to parse C{args} and build the C{service_class} object.
402
 
    @param service_class: The L{LandscapeService} subclass to create and start.
403
 
    @param args: Command line arguments.
404
 
    @param bus_name: A bus name used to verify if the service is already
405
 
        running.
406
 
    """
407
 
    from landscape.reactor import install
408
 
    install()
409
 
 
410
 
    # Let's consider adding this:
411
 
#     from twisted.python.log import startLoggingWithObserver, PythonLoggingObserver
412
 
#     startLoggingWithObserver(PythonLoggingObserver().emit, setStdout=False)
413
 
 
414
 
    configuration = configuration_class()
415
 
    configuration.load(args)
416
 
 
417
 
    if configuration.bus == "system":
418
 
        required_user = _required_users[service_class.service_name]
419
 
        if required_user != pwd.getpwuid(os.getuid())[0]:
420
 
            sys.exit(
421
 
                "When using the system bus, landscape-%s must be run as %s."
422
 
                % (service_class.service_name, required_user))
423
 
 
424
 
    init_logging(configuration, service_class.service_name)
425
 
 
426
 
    assert_unowned_bus_name(get_bus(configuration.bus), bus_name)
427
 
 
428
 
    application = Application("landscape-%s" % (service_class.service_name,))
429
 
    service = service_class(configuration)
430
 
    service.setServiceParent(application)
431
 
 
432
 
    startApplication(application, False)
433
 
 
434
 
    if configuration.ignore_sigint:
435
 
        signal.signal(signal.SIGINT, signal.SIG_IGN)
436
 
 
437
 
    service.reactor.run()