~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#! /usr/bin/env python2.4
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Start script for Launchpad: loads configuration and starts the server.

$Id: z3.py 25266 2004-06-04 21:25:45Z jim $
"""
import sys

if sys.version_info < (2, 4, 0):
    print ("ERROR: Your python version is not supported by Launchpad."
            "Launchpad needs Python 2.4 or greater. You are running: " 
            + sys.version)
    sys.exit(1)

import os
import os.path
import atexit
import signal
import subprocess
import time
from zope.app.server.main import main
from configs import generate_overrides

basepath = filter(None, sys.path)

# Disgusting hack to use our extended config file schema rather than the
# Z3 one. TODO: Add command line options or other to Z3 to enable overriding
# this -- StuartBishop 20050406
from zdaemon.zdoptions import ZDOptions
ZDOptions.schemafile = os.path.abspath(os.path.join(
        os.path.dirname(__file__), 'lib', 'canonical',
        'config', 'schema.xml'))

def start_librarian():
    # Imported here as path is not set fully on module load
    from canonical.config import config

    # Don't run the Librarian if it wasn't asked for. We only want it
    # started up developer boxes really, as the production Librarian
    # doesn't use this startup script.
    if not config.librarian.server.launch:
        return

    if not os.path.isdir(config.librarian.server.root):
        os.makedirs(config.librarian.server.root, 0700)

    pidfile = os.path.join(config.librarian.server.root, 'librarian.pid')
    tacfile = os.path.abspath(os.path.join(
        os.path.dirname(__file__), 'daemons', 'librarian.tac'
        ))

    ver = '%d.%d' % sys.version_info[:2]
    args = [
        "twistd%s" % ver,
        "--no_save",
        "--nodaemon",
        "--python", tacfile,
        "--pidfile", pidfile,
        "--logfile", "-",
        "--prefix", "Librarian",
        ]

    if config.librarian.server.spew:
        args.append("--spew")

    librarian_process = subprocess.Popen(args, stdin=subprocess.PIPE)
    librarian_process.stdin.close()
    # I've left this off - we still check at termination and we can
    # avoid the startup delay. -- StuartBishop 20050525
    #time.sleep(1)
    #if librarian_process.poll() != None:
    #    raise RuntimeError(
    #            "Librarian did not start: %d" % librarian_process.returncode
    #            )
    def stop_librarian():
        if librarian_process.poll() is None:
            os.kill(librarian_process.pid, signal.SIGTERM)
            librarian_process.wait()
        else:
            print >> sys.stderr, "*** ERROR: Librarian died prematurely!"
            print >> sys.stderr, "***        Return code was %d" % (
                    librarian_process.returncode,
                    )
    atexit.register(stop_librarian)


def make_pidfile():
    """Create a pidfile so we can be killed easily.

    Registers an atexit callback to remove the file on termination.
    """
    pidfile = os.path.join(os.path.dirname(__file__), 'launchpad.pid')
    def nukepidfile():
        if os.path.exists(pidfile):
            os.unlink(pidfile)
    atexit.register(nukepidfile)
    f = open(pidfile, 'w')
    print >> f, str(os.getpid())
    f.close()


 
def run(argv=list(sys.argv)):

    # Sort ZCML overrides for our current config
    generate_overrides()

    # setting python paths
    program = argv[0]

    src = 'lib'
    here = os.path.dirname(os.path.abspath(program))
    srcdir = os.path.join(here, src)
    sys.path = [srcdir, here] + basepath

    # We really want to replace this with a generic startup harness.
    # However, this should last us until this is developed
    start_librarian()

    # Store our process id somewhere
    make_pidfile()

    main(argv[1:])
        

if __name__ == '__main__':
    run()