~launchpad-pqm/launchpad/devel

10637.3.1 by Guilherme Salgado
Use the default python version instead of a hard-coded version
1
#! /usr/bin/python
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
2
#
8687.15.10 by Karl Fogel
Add the copyright header block to top-level files.
3
# Copyright 2009 Canonical Ltd.  This software is licensed under the
4
# GNU Affero General Public License version 3 (see the file LICENSE).
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
5
6
import os
7
import grp
8
import pwd
9
import sys
10
import errno
7064.1.4 by Barry Warsaw
Response to Francis's review.
11
import socket
4897.4.6 by Barry Warsaw
The first step toward a comprehensive Launchpad/Mailman integration test.
12
import tempfile
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
13
import subprocess
14
4002.5.26 by Barry Warsaw
Branch fixes based on salgado's review.
15
from canonical.config import config
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
16
from canonical.launchpad.mailman.config import (
7064.1.4 by Barry Warsaw
Response to Francis's review.
17
    configure_prefix, configure_siteowner)
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
18
from canonical.launchpad.mailman.monkeypatches import monkey_patch
7465.5.1 by Gary Poster
integrate lazr.config and lazr.delegates
19
from lazr.config import as_username_groupname
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
20
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
21
basepath = [part for part in sys.path if part]
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
22
23
24
def build_mailman():
25
    # Build and install Mailman if it is enabled and not yet built.
5863.9.7 by Curtis Hovey
Refacortings per review.
26
    if not config.mailman.build:
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
27
        # There's nothing to do.
5415.1.1 by Barry Warsaw
If there is no <mailman> or <mailman-build> section, there's nothing to build, so return immediately.
28
        return 0
5863.9.7 by Curtis Hovey
Refacortings per review.
29
    mailman_path = configure_prefix(config.mailman.build_prefix)
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
30
    mailman_bin = os.path.join(mailman_path, 'bin')
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
31
    var_dir = os.path.abspath(config.mailman.build_var_dir)
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
32
33
    # If we can import the package, we assume Mailman is properly built and
34
    # installed.  This does not catch re-installs that might be necessary
35
    # should our copy in sourcecode be updated.  Do that manually.
36
    sys.path.append(mailman_path)
37
    try:
38
        import Mailman
39
    except ImportError:
40
        pass
41
    else:
42
        return 0
43
9328.1.2 by Max Bowsher
Make comment more detailed.
44
    # sys.path_importer_cache is a mapping of elements of sys.path to importer
45
    # objects used to handle them. In Python2.5+ when an element of sys.path is
46
    # found to not exist on disk, a NullImporter is created and cached - this
47
    # causes Python to never bother re-inspecting the disk for that path
48
    # element. We must clear that cache element so that our second attempt to
49
    # import MailMan after building it will actually check the disk.
9328.1.1 by Max Bowsher
Clear the mailman_path from sys.path_importer_cache after a failed import - otherwise Python >= 2.5 won't look again at a directory it has already determined does not exist.
50
    del sys.path_importer_cache[mailman_path]
51
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
52
    # Make sure the target directories exist and have the correct
53
    # permissions, otherwise configure will complain.
7064.1.4 by Barry Warsaw
Response to Francis's review.
54
    user, group = as_username_groupname(config.mailman.build_user_group)
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
55
    # Now work backwards to get the uid and gid
5373.2.8 by Barry Warsaw
Solve a few other problems related to staging's Mailman configs.
56
    try:
57
        uid = pwd.getpwnam(user).pw_uid
58
    except KeyError:
59
        print >> sys.stderr, 'No user found:', user
60
        sys.exit(1)
61
    try:
62
        gid = grp.getgrnam(group).gr_gid
63
    except KeyError:
64
        print >> sys.stderr, 'No group found:', group
65
        sys.exit(1)
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
66
67
    # Ensure that the var_dir exists, is owned by the user:group, and has
68
    # the necessary permissions.  Set the mode separately after the
69
    # makedirs() call because some platforms ignore mkdir()'s mode (though
70
    # I think Linux does not ignore it -- better safe than sorry).
71
    try:
72
        os.makedirs(var_dir)
73
    except OSError, e:
4002.5.26 by Barry Warsaw
Branch fixes based on salgado's review.
74
        if e.errno != errno.EEXIST:
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
75
            raise
76
    os.chown(var_dir, uid, gid)
77
    os.chmod(var_dir, 02775)
78
79
    mailman_source = os.path.join('sourcecode', 'mailman')
7064.1.4 by Barry Warsaw
Response to Francis's review.
80
    if config.mailman.build_host_name:
81
        build_host_name = config.mailman.build_host_name
82
    else:
83
        build_host_name = socket.getfqdn()
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
84
5427.2.1 by Barry Warsaw
Correct a bald-faced lie. Mailman's buildout for Launchpad /does/ need to set
85
    # Build and install the Mailman software.  Note that we don't care about
86
    # --with-cgi-gid because we're not going to use that Mailman subsystem.
9641.1.13 by Gary Poster
try a work-around for Hardy Heron dislike of scripts as executables in shebang lines. Also revert to using a shell script for bin/py rather than a Python script.
87
    executable = os.path.abspath('bin/py')
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
88
    configure_args = (
89
        './configure',
90
        '--prefix', mailman_path,
91
        '--with-var-prefix=' + var_dir,
9641.1.13 by Gary Poster
try a work-around for Hardy Heron dislike of scripts as executables in shebang lines. Also revert to using a shell script for bin/py rather than a Python script.
92
        '--with-python=' + executable,
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
93
        '--with-username=' + user,
94
        '--with-groupname=' + group,
5427.2.1 by Barry Warsaw
Correct a bald-faced lie. Mailman's buildout for Launchpad /does/ need to set
95
        '--with-mail-gid=' + group,
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
96
        '--with-mailhost=' + build_host_name,
97
        '--with-urlhost=' + build_host_name,
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
98
        )
9641.1.13 by Gary Poster
try a work-around for Hardy Heron dislike of scripts as executables in shebang lines. Also revert to using a shell script for bin/py rather than a Python script.
99
    # Configure.
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
100
    retcode = subprocess.call(configure_args, cwd=mailman_source)
101
    if retcode:
102
        print >> sys.stderr, 'Could not configure Mailman:'
103
        sys.exit(retcode)
9641.1.13 by Gary Poster
try a work-around for Hardy Heron dislike of scripts as executables in shebang lines. Also revert to using a shell script for bin/py rather than a Python script.
104
    # Make.
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
105
    retcode = subprocess.call(('make',), cwd=mailman_source)
106
    if retcode:
107
        print >> sys.stderr, 'Could not make Mailman.'
108
        sys.exit(retcode)
9641.1.13 by Gary Poster
try a work-around for Hardy Heron dislike of scripts as executables in shebang lines. Also revert to using a shell script for bin/py rather than a Python script.
109
    # We have a brief interlude before we install.  Hardy will not
110
    # accept a script as the executable for the shebang line--it will
111
    # treat the file as a shell script instead. The ``bin/by``
112
    # executable that we specified in '--with-python' above is a script
113
    # so this behavior causes problems for us. Our work around is to
114
    # prefix the ``bin/py`` script with ``/usr/bin/env``, which makes
115
    # Hardy happy.  We need to do this before we install because the
116
    # installation will call Mailman's ``bin/update``, which is a script
117
    # that needs this fix.
118
    build_dir = os.path.join(mailman_source, 'build')
119
    original = '#! %s\n' % (executable,)
120
    modified = '#! /usr/bin/env %s\n' % (executable,)
121
    for (dirpath, dirnames, filenames) in os.walk(build_dir):
122
        for filename in filenames:
123
            filename = os.path.join(dirpath, filename)
124
            f = open(filename, 'r')
125
            if f.readline() == original:
126
                rest = f.read()
127
                f.close()
128
                f = open(filename, 'w')
129
                f.write(modified)
130
                f.write(rest)
131
            f.close()
132
    # Now we actually install.
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
133
    retcode = subprocess.call(('make', 'install'), cwd=mailman_source)
134
    if retcode:
135
        print >> sys.stderr, 'Could not install Mailman.'
136
        sys.exit(retcode)
137
    # Try again to import the package.
138
    try:
7064.1.4 by Barry Warsaw
Response to Francis's review.
139
        # pylint: disable-msg=W0404
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
140
        import Mailman
141
    except ImportError:
142
        print >> sys.stderr, 'Could not import the Mailman package'
143
        return 1
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
144
145
    # Check to see if the site list exists.  The output can go to /dev/null
146
    # because we don't really care about it.  The site list exists if
147
    # config_list returns a zero exit status, otherwise it doesn't
148
    # (probably).  Before we can do this however, we must monkey patch
149
    # Mailman, otherwise mm_cfg.py won't be set up correctly.
150
    monkey_patch(mailman_path, config)
151
152
    import Mailman.mm_cfg
153
    retcode = subprocess.call(
154
        ('./config_list', '-o', '/dev/null',
155
         Mailman.mm_cfg.MAILMAN_SITE_LIST),
156
        cwd=mailman_bin,
157
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
158
159
    if retcode:
5863.9.7 by Curtis Hovey
Refacortings per review.
160
        addr, password = configure_siteowner(
161
            config.mailman.build_site_list_owner)
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
162
163
        # The site list does not yet exist, so create it now.
164
        retcode = subprocess.call(
165
            ('./newlist', '--quiet',
5863.9.1 by Curtis Hovey
Updated configs and code to used simple datatypes. Changes may still be needed aftert testing.
166
             '--emailhost=' + build_host_name,
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
167
             Mailman.mm_cfg.MAILMAN_SITE_LIST,
168
             addr, password),
169
            cwd=mailman_bin)
170
        if retcode:
171
            print >> sys.stderr, 'Could not create site list'
4483.4.25 by Barry Warsaw
Last round of changes in response to bac's comments (who took over in BjornT's
172
            return retcode
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
173
5046.3.2 by Barry Warsaw
Some modifications in response to Francis's comments.
174
    retcode = configure_site_list(
175
        mailman_bin, Mailman.mm_cfg.MAILMAN_SITE_LIST)
176
    if retcode:
177
        print >> sys.stderr, 'Could not configure site list'
178
        return retcode
179
180
    # Create a directory to hold the gzip'd tarballs for the directories of
181
    # deactivated lists.
182
    try:
183
        os.mkdir(os.path.join(Mailman.mm_cfg.VAR_PREFIX, 'backups'))
184
    except OSError, e:
185
        if e.errno != errno.EEXIST:
186
            raise
187
188
    return 0
189
190
191
def configure_site_list(mailman_bin, site_list_name):
192
    """Configure the site list.
193
194
    Currently, the only thing we want to set is to not advertise the site list.
195
    """
4897.4.6 by Barry Warsaw
The first step toward a comprehensive Launchpad/Mailman integration test.
196
    fd, config_file_name = tempfile.mkstemp()
197
    try:
198
        os.close(fd)
199
        config_file = open(config_file_name, 'w')
200
        try:
201
            print >> config_file, 'advertised = False'
202
        finally:
203
            config_file.close()
5046.3.2 by Barry Warsaw
Some modifications in response to Francis's comments.
204
        return subprocess.call(
205
            ('./config_list', '-i', config_file_name, site_list_name),
206
            cwd=mailman_bin)
4897.4.6 by Barry Warsaw
The first step toward a comprehensive Launchpad/Mailman integration test.
207
    finally:
208
        os.remove(config_file_name)
209
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
210
211
def main():
212
    # setting python paths
213
    program = sys.argv[0]
214
215
    src = 'lib'
216
    here = os.path.dirname(os.path.abspath(program))
217
    srcdir = os.path.join(here, src)
218
    sys.path = [srcdir, here] + basepath
219
    return build_mailman()
4002.5.31 by Barry Warsaw
Updates to the mmbuild branch based on feedback from SteveA and spiv over
220
4002.5.14 by Barry Warsaw
Changes to address jamesh's review comments.
221
222
223
if __name__ == '__main__':
224
    return_code = main()
225
    sys.exit(return_code)