~blake-rouse/maas/is-importing-2.1

« back to all changes in this revision

Viewing changes to src/provisioningserver/plugin.py

  • Committer: Julian Edwards
  • Date: 2012-01-23 18:02:19 UTC
  • mto: This revision was merged to the branch mainline in revision 53.
  • Revision ID: julian.edwards@canonical.com-20120123180219-59j52mfv1ssstzc1
start the TAP for the provisioning server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2012 Canonical Ltd.  This software is licensed under the
 
2
# GNU Affero General Public License version 3 (see the file LICENSE).
 
3
 
 
4
from __future__ import (
 
5
    print_function,
 
6
    unicode_literals,
 
7
    )
 
8
 
 
9
"""Twisted Application Plugin code for the MaaS provisioning server"""
 
10
 
 
11
import setproctitle # TODO b-d: python-setproctitle
 
12
import signal
 
13
import sys
 
14
 
 
15
import oops
 
16
from oops_datedir_repo import DateDirRepo
 
17
from oops_twisted import (
 
18
    Config as oops_config,
 
19
    defer_publisher,
 
20
    OOPSObserver,
 
21
    )
 
22
from twisted.application.service import (
 
23
    IServiceMaker,
 
24
    )
 
25
from twisted.internet import reactor
 
26
from twisted.plugin import IPlugin
 
27
from twisted.python import (
 
28
    log,
 
29
    usage,
 
30
    )
 
31
from twisted.python.logfile import LogFile
 
32
from twisted.python.log import (
 
33
    addObserver,
 
34
    FileLogObserver,
 
35
    )
 
36
# TODO b-d: python-twisted
 
37
from zope.interface import implements
 
38
# TODO b-d: python-zope.interface
 
39
 
 
40
 
 
41
__metaclass__ = type
 
42
__all__ = []
 
43
 
 
44
 
 
45
def getRotatableLogFileObserver(filename):
 
46
    """Setup a L{LogFile} for the given application."""
 
47
    if filename != '-':
 
48
        logfile = LogFile.fromFullPath(
 
49
            filename, rotateLength=None, defaultMode=0644)
 
50
        def signal_handler(sig, frame):
 
51
            reactor.callFromThread(logfile.reopen)
 
52
        signal.signal(signal.SIGUSR1, signal_handler)
 
53
    else:
 
54
        logfile = sys.stdout
 
55
    return FileLogObserver(logfile)
 
56
 
 
57
 
 
58
def setUpOOPSHandler(options, logfile):
 
59
    """Add OOPS handling based on the passed command line options."""
 
60
    config = oops_config()
 
61
 
 
62
    # Add the oops publisher that writes files in the configured place
 
63
    # if the command line option was set.
 
64
 
 
65
    if options["oops-dir"]:
 
66
        repo = DateDirRepo(options["oops-dir"])
 
67
        config.publishers.append(
 
68
            defer_publisher(oops.publish_new_only(repo.publish)))
 
69
 
 
70
    if options["oops-reporter"]:
 
71
        config.template['reporter'] = options["oops-reporter"]
 
72
 
 
73
    observer = OOPSObserver(config, logfile.emit)
 
74
    addObserver(observer.emit)
 
75
    return observer
 
76
 
 
77
 
 
78
class Options(usage.Options):
 
79
    """Command line options for the provisioning server."""
 
80
 
 
81
    optParameters = [
 
82
        ["logfile", "l", "provisioningserver.log", "Logfile name."],
 
83
        ["brokerport", "p", 5672, "Broker port"],
 
84
        ["brokerhost", "h", '127.0.0.1', "Broker host"],
 
85
        ["brokeruser", "u", None, "Broker user"],
 
86
        ["brokerpassword", "a", None, "Broker password"],
 
87
        ["brokervhost", "v", '/', "Broker vhost"],
 
88
        ["oops-dir", "r", None, "Where to write OOPS reports"],
 
89
        ["oops-reporter", "o", "MAAS-PS", "String identifying this service."],
 
90
        ]
 
91
 
 
92
    def postOptions(self):
 
93
        for arg in ('brokeruser', 'brokerpassword'):
 
94
            if not self[arg]:
 
95
                raise usage.UsageError("--%s must be specified." % arg)
 
96
        for int_arg in ('brokerport'):
 
97
            try:
 
98
                self[int_arg] = int(self[int_arg])
 
99
            except (TypeError, ValueError):
 
100
                raise usage.UsageError("--%s must be an integer." % int_arg)
 
101
        if not self["oops-reporter"] and self["oops-dir"]:
 
102
            raise usage.UsageError(
 
103
                "A reporter must be supplied to identify reports "
 
104
                "from this service from other OOPS reports.")
 
105
 
 
106
class ProvisioningServiceMaker(object):
 
107
    """Create a service for the Twisted plugin."""
 
108
 
 
109
    implements(IServiceMaker, IPlugin)
 
110
 
 
111
    def __init__(self, name, description):
 
112
        self.tapname = name
 
113
        self.description = description
 
114
 
 
115
    def makeService(self, options):
 
116
        """Construct a service."""
 
117
        # Required to hide the command line options that include a password.
 
118
        setproctitle.setproctitle("maas provisioning service")
 
119
 
 
120
        logfile = getRotatableLogFileObserver(options["logfile"])
 
121
        setUpOOPSHandler(options, logfile)
 
122
 
 
123
        broker_port = options["brokerport"]
 
124
        broker_host = options["brokerhost"]
 
125
        broker_user = options["brokeruser"]
 
126
        broker_password = options["brokerpassword"]
 
127
        broker_vhost = options["brokervhost"]
 
128
 
 
129
        # TODO: Create services here, e.g.
 
130
        # service1 = thing
 
131
        # service2 = thing2
 
132
        # services = MultiService()
 
133
        # services.addService(service1)
 
134
        # services.addService(service2)
 
135
        # return services