2733
by Canonical.com Patch Queue Manager
Upload processor. r=stevea |
1 |
#!/usr/bin/env python
|
2 |
"""Upload processor.
|
|
3 |
||
4 |
Given a bunch of context information and a bunch of files, process them as
|
|
5 |
an upload to a distro/whatever within the launchpad.
|
|
6 |
"""
|
|
7 |
||
8 |
import _pythonpath |
|
9 |
||
10 |
import os |
|
11 |
import sys |
|
12 |
||
13 |
from optparse import OptionParser |
|
14 |
from email import message_from_string |
|
15 |
||
16 |
from zope.component import getUtility |
|
17 |
||
18 |
from canonical.lp import initZopeless |
|
19 |
from canonical.config import config |
|
20 |
from canonical.launchpad.scripts import (execute_zcml_for_scripts, |
|
21 |
logger, logger_options) |
|
22 |
from canonical.launchpad.mail import sendmail |
|
23 |
from canonical.encoding import ascii_smash |
|
24 |
||
25 |
from contrib.glock import GlobalLock |
|
26 |
||
27 |
from canonical.archivepublisher.nascentupload import NascentUpload, UploadError |
|
28 |
from canonical.archivepublisher.uploadpolicy import ( |
|
29 |
findPolicyByOptions, policy_options, UploadPolicyError) |
|
30 |
||
31 |
def main(): |
|
32 |
# Parse command-line arguments
|
|
33 |
parser = OptionParser() |
|
34 |
logger_options(parser) |
|
35 |
policy_options(parser) |
|
36 |
||
37 |
parser.add_option("-N", "--dry-run", action="store_true", |
|
38 |
dest="dryrun", metavar="DRY_RUN", default=False, |
|
39 |
help="Whether to treat this as a dry-run or not.") |
|
40 |
global options |
|
41 |
(options, args) = parser.parse_args() |
|
42 |
||
43 |
global log |
|
44 |
log = logger(options, "process-upload") |
|
45 |
||
46 |
if len(args) != 1: |
|
47 |
log.error("Need to be given exactly one non-option argument. " |
|
48 |
"Namely the fsroot for the upload.") |
|
49 |
return 1 |
|
50 |
||
51 |
fsroot = args[0] |
|
52 |
||
53 |
log.debug("Acquiring lock") |
|
54 |
lock = GlobalLock('/var/lock/launchpad-process-upload.lock') |
|
55 |
lock.acquire(blocking=True) |
|
56 |
||
57 |
log.debug("Initialising connection.") |
|
58 |
global ztm |
|
59 |
ztm = initZopeless(dbuser=config.uploader.dbuser) |
|
60 |
||
61 |
execute_zcml_for_scripts() |
|
62 |
||
63 |
try: |
|
64 |
if not os.path.isdir(fsroot): |
|
65 |
raise ValueError("%s is not a directory" % fsroot) |
|
66 |
log.info("Finding policy.") |
|
67 |
policy = findPolicyByOptions(options) |
|
68 |
||
69 |
uploads = [] |
|
70 |
||
71 |
for root, dirs, files in os.walk(fsroot): |
|
72 |
assert(len(dirs) == 0) |
|
73 |
for filename in files: |
|
74 |
if filename.endswith(".changes"): |
|
75 |
uploads.append( |
|
76 |
NascentUpload(policy, fsroot, filename, log)) |
|
77 |
||
78 |
for upload in uploads: |
|
79 |
process_upload(upload) |
|
80 |
||
81 |
finally: |
|
82 |
log.debug("Rolling back any remaining transactions.") |
|
83 |
ztm.abort() |
|
84 |
log.debug("Releasing lock") |
|
85 |
lock.release() |
|
86 |
||
87 |
return 0 |
|
88 |
||
89 |
def send_mails(mails): |
|
90 |
"""Send the mails provided using the launchpad mail infrastructure."""
|
|
91 |
for mail_text in mails: |
|
92 |
mail_message = message_from_string(ascii_smash(mail_text)) |
|
93 |
if mail_message['To'] is None: |
|
94 |
log.debug("Unable to parse message for rejection!") |
|
95 |
log.debug("This will cause the sendmail() to assert.") |
|
96 |
print repr(mail_text) |
|
97 |
mail_message['X-Katie'] = "Launchpad actually" |
|
98 |
if options.dryrun: |
|
99 |
log.info("Would be sending a mail:") |
|
100 |
log.info(" Subject: %s" % mail_message['Subject']) |
|
101 |
log.info(" Recipients: %s" % mail_message['To']) |
|
102 |
log.info(" Body:") |
|
103 |
for line in mail_message.get_payload().split("\n"): |
|
104 |
log.info(line) |
|
105 |
sendmail(mail_message) |
|
106 |
||
107 |
def process_upload(upload): |
|
108 |
"""Process an upload as provided."""
|
|
109 |
ztm.begin() |
|
110 |
log.info("Processing upload %s" % upload.changes_filename) |
|
111 |
try: |
|
112 |
try: |
|
113 |
upload.process() |
|
114 |
except UploadPolicyError, e: |
|
115 |
upload.reject("UploadPolicyError made it out to the main loop: " |
|
116 |
"%s " % e) |
|
117 |
except UploadError, e: |
|
118 |
upload.reject("UploadError made it out to the main loop: %s" % e) |
|
119 |
if upload.rejected: |
|
120 |
mails = upload.do_reject() |
|
121 |
ztm.abort() |
|
122 |
send_mails(mails) |
|
123 |
else: |
|
2756
by Canonical.com Patch Queue Manager
Queue-Accepted processor and some upload tweaks to fit it. r=stevea |
124 |
successful, mails = upload.do_accept() |
125 |
if not successful: |
|
126 |
log.info("Rejection during accept. Aborting partial accept.") |
|
127 |
ztm.abort() |
|
2733
by Canonical.com Patch Queue Manager
Upload processor. r=stevea |
128 |
send_mails(mails) |
129 |
if options.dryrun: |
|
130 |
log.info("Dry run, aborting the transaction for this upload.") |
|
131 |
ztm.abort() |
|
132 |
else: |
|
2756
by Canonical.com Patch Queue Manager
Queue-Accepted processor and some upload tweaks to fit it. r=stevea |
133 |
log.info("Committing the transaction and any mails associated" |
134 |
"with this upload.") |
|
2733
by Canonical.com Patch Queue Manager
Upload processor. r=stevea |
135 |
ztm.commit() |
136 |
finally: |
|
137 |
ztm.abort() |
|
138 |
||
139 |
if __name__ == '__main__': |
|
140 |
sys.exit(main()) |
|
141 |