1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
1 |
#!/usr/bin/python3
|
705.1.1
by Brian Murray
first draft of phased-updater |
2 |
|
3 |
# Copyright (C) 2013 Canonical Ltd.
|
|
4 |
# Author: Brian Murray <brian.murray@canonical.com>
|
|
5 |
||
6 |
# This program is free software: you can redistribute it and/or modify
|
|
7 |
# it under the terms of the GNU General Public License as published by
|
|
8 |
# the Free Software Foundation; version 3 of the License.
|
|
9 |
#
|
|
10 |
# This program is distributed in the hope that it will be useful,
|
|
11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
# GNU General Public License for more details.
|
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU General Public License
|
|
16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17 |
||
18 |
'''Increment the Phased-Update-Percentage for a package
|
|
19 |
||
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
20 |
Check to see whether or not there is a regression (new crash bucket or
|
834.1.1
by Brian Murray
phased-updater: only add version to web_link if it wasn't provided |
21 |
increase in rate of errors about a package) using errors.ubuntu.com and if
|
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
22 |
not increment the Phased-Update-Percentage for the package.
|
705.1.38
by Brian Murray
for stopped updates show the percentage the update was stopped at and link to the binary publishing history |
23 |
Additionally, generate an html report regarding state of phasing of
|
24 |
packages and email uploaders regarding issues with their uploads.
|
|
705.1.1
by Brian Murray
first draft of phased-updater |
25 |
'''
|
26 |
||
27 |
||
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
28 |
import apt |
1027.2.1
by Brian Murray
phased-updater: using codes.open and a utf-8 encoding in case signer's have unicode in their name. |
29 |
import codecs |
705.1.4
by Brian Murray
implement whitelist support |
30 |
import csv |
705.1.1
by Brian Murray
first draft of phased-updater |
31 |
import datetime |
1100.1.1
by Brian Murray
phased-updater: workaround LP timing out when we call getPublishedBinaries() |
32 |
import lazr |
705.1.45
by Brian Murray
switched from print to logging |
33 |
import logging |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
34 |
import os |
705.1.1
by Brian Murray
first draft of phased-updater |
35 |
import simplejson as json |
36 |
import time |
|
37 |
||
705.1.9
by Brian Murray
display the number of days since the update was published |
38 |
from collections import defaultdict, OrderedDict |
892.1.1
by Brian Murray
phased-updater: use the launchpad changes file to find an email address to notify about a stopped phased update |
39 |
from email import utils |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
40 |
from functools import cmp_to_key |
705.1.25
by Brian Murray
add in support for other launchpad instances, add % sign to update percentage |
41 |
from optparse import OptionParser |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
42 |
from urllib.parse import quote |
43 |
from urllib.request import urlopen |
|
705.1.4
by Brian Murray
implement whitelist support |
44 |
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
45 |
import lputils |
46 |
||
705.1.1
by Brian Murray
first draft of phased-updater |
47 |
from launchpadlib.launchpad import Launchpad |
48 |
||
757
by Stéphane Graber
Fix all PEP-8 warnings. |
49 |
|
705.1.37
by Brian Murray
create a function for determing a launchpad user's email address |
50 |
def get_primary_email(lp_user): |
51 |
try: |
|
52 |
lp_user_email = lp_user.preferred_email_address.email |
|
53 |
except ValueError as e: |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
54 |
if 'server-side permission' in str(e): |
705.1.45
by Brian Murray
switched from print to logging |
55 |
logging.info("%s has hidden their email addresses" % |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
56 |
lp_user.web_link) |
705.1.37
by Brian Murray
create a function for determing a launchpad user's email address |
57 |
return '' |
705.1.45
by Brian Murray
switched from print to logging |
58 |
logging.info("Error accessing %s's preferred email address: %s" % |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
59 |
(lp_user.web_link, e.message)) |
705.1.37
by Brian Murray
create a function for determing a launchpad user's email address |
60 |
return '' |
61 |
return lp_user_email |
|
62 |
||
757
by Stéphane Graber
Fix all PEP-8 warnings. |
63 |
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
64 |
def set_pup(current_pup, new_pup, release, suite, src_pkg): |
65 |
options.series = release |
|
66 |
options.suite = suite |
|
67 |
options.pocket = 'Updates' |
|
68 |
options.version = None |
|
69 |
source = lputils.find_latest_published_source(options, src_pkg) |
|
959
by William Grant
Fix a few missed cases that should be skipping ddebs. One never manipulates a ddeb directly. |
70 |
publications = [ |
71 |
binary for binary in source.getPublishedBinaries() |
|
72 |
if not binary.is_debug] |
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
73 |
|
74 |
for pub in publications: |
|
964
by Colin Watson
phased-updater: Don't override if latest publication isn't Published |
75 |
if pub.status != 'Published': |
76 |
continue
|
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
77 |
pub.changeOverride(new_phased_update_percentage=new_pup) |
78 |
if new_pup != 0: |
|
79 |
logging.info('Incremented p-u-p for %s %s from %s%% to %s%%' % |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
80 |
(suite, pub.binary_package_name, |
81 |
current_pup, new_pup)) |
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
82 |
else: |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
83 |
logging.info('Set p-u-p to 0%% from %s%% for %s %s' % |
84 |
(current_pup, suite, pub.binary_package_name)) |
|
85 |
||
705.1.28
by Brian Murray
implemented setting of phased_update_percentage to 0 or incrementing it |
86 |
|
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
87 |
def generate_html_report(releases, buckets): |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
88 |
import tempfile |
89 |
import shutil |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
90 |
with tempfile.NamedTemporaryFile(mode='w') as report: |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
91 |
report.write('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" |
705.1.1
by Brian Murray
first draft of phased-updater |
92 |
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
93 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
94 |
<head>
|
|
95 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
96 |
<title>Released Ubuntu SRUs</title>
|
|
97 |
<style type="text/css">
|
|
98 |
body { background: #CCCCB0; color: black; }
|
|
99 |
a { text-decoration: none; }
|
|
100 |
table { border-collapse: collapse; border-style: solid none;
|
|
101 |
border-width: 3px; margin-bottom: 3ex; empty-cells: show; }
|
|
102 |
table th { text-align: left; border-style: none none dotted none;
|
|
103 |
border-width: 1px; padding-right: 10px; }
|
|
104 |
table td { text-align: left; border-style: none none dotted none;
|
|
105 |
border-width: 1px; padding-right: 10px; }
|
|
106 |
.noborder { border-style: none; }
|
|
107 |
a { color: blue; }
|
|
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
108 |
a:visited { color: black; }
|
705.1.1
by Brian Murray
first draft of phased-updater |
109 |
</style>
|
110 |
</head>
|
|
111 |
<body>
|
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
112 |
<h1>Phasing %sUbuntu Stable Release Updates</h1> |
113 |
''' % ('', 'and Released ')[options.fully_phased]) |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
114 |
report.write( |
115 |
'<p>Generated: %s by ' |
|
116 |
'<a href="http://bazaar.launchpad.net/'
|
|
117 |
'~ubuntu-archive/ubuntu-archive-tools/trunk/annotate/head%%3A/' |
|
118 |
'phased-updater">phased-updater</a></p>' % |
|
1073
by Colin Watson
Report ISO dates. |
119 |
time.strftime('%F %T UTC', time.gmtime())) |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
120 |
report.write('''<p>A <a |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
121 |
href="https://wiki.ubuntu.com/StableReleaseUpdates">stable release
|
122 |
update</a> is either being phased (update percentage is not 0%) or phasing has
|
|
123 |
been stopped (update percentage is 0%) for the following packages and releases.
|
|
124 |
<p>The phasing stops if there is either an increased rate of crashes or an
|
|
125 |
error has been found that has only been seen with the SRU'ed version of the
|
|
126 |
package.<p>
|
|
127 |
<a href="https://wiki.ubuntu.com/StableReleaseUpdates#Phasing">Learn more</a>
|
|
128 |
about investigating halted phased updates.''') |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
129 |
for release in releases: |
130 |
rname = release.name |
|
131 |
if not buckets[rname]: |
|
132 |
continue
|
|
133 |
report.write('''<h3>%s</h3>\n''' % rname) |
|
134 |
report.write('''<table>\n''') |
|
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
135 |
report.write('''<tr> |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
136 |
<th>Package</th>
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
137 |
<th>Version (signer, creator)</th>
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
138 |
<th>Update Percentage</th>
|
139 |
<th>Rate Increase</th>
|
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
140 |
<th>Errors</th>
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
141 |
<th>Days</th>
|
142 |
</tr>''') |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
143 |
for spph_link in buckets[rname]: |
144 |
# need to reload the pub_source information
|
|
145 |
pub_source = launchpad.load(spph_link) |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
146 |
pkg = pub_source.source_package_name |
147 |
version = pub_source.source_package_version |
|
767.2.1
by Brian Murray
phased-updater: identify security updates |
148 |
# Identify security updates
|
149 |
if options.fully_phased: |
|
150 |
sec_pubs = [(ps.source_package_name, |
|
151 |
ps.source_package_version) |
|
152 |
for ps in archive.getPublishedSources( |
|
153 |
distro_series=release, pocket='Security', |
|
154 |
source_name=pkg, version=version, |
|
155 |
exact_match=True)] |
|
156 |
if (pkg, version) in sec_pubs: |
|
157 |
version += ' (security)' |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
158 |
age = (datetime.datetime.now() - |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
159 |
pub_source.date_published.replace(tzinfo=None)).days |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
160 |
update_percentage = buckets[rname][spph_link].get('pup', 100) |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
161 |
if not options.fully_phased and update_percentage == 100: |
162 |
continue
|
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
163 |
signer = str(pub_source.package_signer).split('~')[-1] |
164 |
uploaders = '<a href="%s/~%s">%s</a>' % \ |
|
165 |
(LP_BASE_URL, signer, signer) |
|
166 |
if pub_source.package_creator \ |
|
167 |
and pub_source.package_creator != pub_source.package_signer: |
|
168 |
creator = str(pub_source.package_creator).split('~')[-1] |
|
169 |
uploaders += ', <a href="%s/~%s">%s</a>' % \ |
|
170 |
(LP_BASE_URL, creator, creator) |
|
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
171 |
lpurl = '%s/ubuntu/+source/%s/' % (LP_BASE_URL, pkg) |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
172 |
report.write('''<tr> |
173 |
<td><a href="%s">%s</a></td> |
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
174 |
<td><a href="%s">%s</a> (%s)</td>\n''' % |
175 |
(lpurl, pkg, lpurl + version, version, uploaders)) |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
176 |
report.write(' <td>') |
177 |
if update_percentage == 0: |
|
178 |
binary_pub = pub_source.getPublishedBinaries()[0] |
|
179 |
arch = binary_pub.distro_arch_series.architecture_tag |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
180 |
bpph_url = ('%s/ubuntu/%s/%s/%s' % |
181 |
(LP_BASE_URL, rname, arch, |
|
182 |
binary_pub.binary_package_name)) |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
183 |
report.write('<a href="%s">%s%% of users' % |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
184 |
(bpph_url, update_percentage)) |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
185 |
previous_pup = \ |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
186 |
buckets[rname][spph_link]['previous_pup'] |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
187 |
if previous_pup != 0: |
188 |
report.write(' (was %s%%)</a>' % previous_pup) |
|
705.1.13
by Brian Murray
sort releases, use real_new_bucket, print a has in the html report |
189 |
else: |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
190 |
report.write('</a>') |
191 |
else: |
|
192 |
report.write('%s%% of users' % update_percentage) |
|
193 |
report.write('</td>\n') |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
194 |
if 'rate' in buckets[rname][spph_link]: |
195 |
data = buckets[rname][spph_link]['rate'] |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
196 |
report.write(' <td><a href="%s">+%s</a></td>\n' % |
197 |
(data[1], data[0])) |
|
198 |
else: |
|
199 |
report.write(' <td></td>\n') |
|
200 |
report.write(' <td>') |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
201 |
if 'buckets' in buckets[rname][spph_link]: |
839.1.1
by Brian Murray
phased-updater: if there are no problems with a source package upload, don't check the signer etc, and if the package has no signer (like with a copy from debian) stop trying to create an email |
202 |
# TODO: it'd be great if these were sorted
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
203 |
for bucket in buckets[rname][spph_link]['buckets']: |
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
204 |
if 'problem' in bucket: |
205 |
# create a short version of the problem's hash
|
|
206 |
phash = bucket.replace( |
|
207 |
'https://errors.ubuntu.com/problem/', '')[0:6] |
|
208 |
report.write('<a href="%s">%s</a> ' % (bucket, |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
209 |
phash)) |
1400.2.3
by Brian Murray
phased-updater: check to see who set the phased_update_percentage and respect it |
210 |
elif 'force-stop' in bucket: |
211 |
report.write('The phasing of this update was ' |
|
212 |
'manually stopped by an AA.') |
|
705.1.43
by Brian Murray
change html report to be a tmpfile which is then copied to the correct location |
213 |
else: |
214 |
report.write('<a href="%s">problem</a> ' % bucket) |
|
215 |
else: |
|
216 |
report.write('') |
|
217 |
report.write('</td>\n') |
|
218 |
report.write(' <td>%s</td>\n' % age) |
|
219 |
report.write('</tr>\n') |
|
220 |
report.write('''</table>\n''') |
|
221 |
report.write('''</body>\n''') |
|
222 |
report.write('''</html>''') |
|
223 |
report.flush() |
|
939.1.1
by Brian Murray
phased-updater: include a link to the html report showing phasing progress when e-mailing people. |
224 |
shutil.copy2(report.name, '%s/%s' % (os.getcwd(), REPORT_FILE)) |
225 |
os.chmod('%s/%s' % (os.getcwd(), REPORT_FILE), 0o644) |
|
705.1.1
by Brian Murray
first draft of phased-updater |
226 |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
227 |
|
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
228 |
def create_email_notifications(releases, spph_buckets): |
705.1.5
by Brian Murray
create email using email package from python |
229 |
import smtplib |
230 |
from email.mime.text import MIMEText |
|
763
by Colin Watson
phased-updater: allow phased-updates-emails.txt to be missing |
231 |
notifications = defaultdict(list) |
232 |
try: |
|
1027.2.1
by Brian Murray
phased-updater: using codes.open and a utf-8 encoding in case signer's have unicode in their name. |
233 |
with codecs.open(NOTIFICATIONS, 'r', encoding='utf-8') as notify_file: |
234 |
for line in notify_file.readlines(): |
|
235 |
line = line.strip('\n').split(', ') |
|
763
by Colin Watson
phased-updater: allow phased-updates-emails.txt to be missing |
236 |
# LP name, problem, pkg_version
|
1027.2.2
by Brian Murray
address reviewer feedback |
237 |
person = line[0] |
1027.2.1
by Brian Murray
phased-updater: using codes.open and a utf-8 encoding in case signer's have unicode in their name. |
238 |
problem = line[1] |
239 |
pkg = line[2] |
|
240 |
pkg_version = line[3] |
|
763
by Colin Watson
phased-updater: allow phased-updates-emails.txt to be missing |
241 |
notifications[person].append((problem, pkg, pkg_version)) |
242 |
except IOError: |
|
243 |
pass
|
|
793.1.1
by Brian Murray
phased-updater: add my email address as reply-to and include myself in the cc's |
244 |
bdmurray_mail = 'brian@ubuntu.com' |
705.1.50
by Brian Murray
conditionally pluralize email body and format log as sru-report does |
245 |
b_body = ('Your upload of %s version %s to %s has resulted in %s' |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
246 |
'error%s[1] that %s first reported about this version of the ' |
705.1.50
by Brian Murray
conditionally pluralize email body and format log as sru-report does |
247 |
'package. The error%s follow%s:\n\n' |
705.1.22
by Brian Murray
make email code slightly less redundant |
248 |
'%s\n\n') |
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
249 |
i_body = ('Your upload of %s version %s to %s has resulted in an ' |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
250 |
'increased daily rate of errors[1] for the package compared '
|
705.1.36
by Brian Murray
protect against hidden email addresses and clarify some text |
251 |
'to the previous two weeks. For problems currently being '
|
252 |
'reported about the package see:\n\n' |
|
1184.1.1
by Brian Murray
phased-updater: switch from period of day to week |
253 |
'%s&period=week\n\n') |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
254 |
remedy = ('The current status of the phasing of all stable release ' |
255 |
'updates, including yours, is available at:\n\n' |
|
939.1.2
by Brian Murray
phased-updater: add and extra \n |
256 |
'http://people.canonical.com/~ubuntu-archive/%s\n\n' |
939.1.1
by Brian Murray
phased-updater: include a link to the html report showing phasing progress when e-mailing people. |
257 |
'Further phasing of this update has been stopped until the '
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
258 |
'errors have either been fixed or determined[2] to not be a '
|
259 |
'result of this stable release update. In the event of '
|
|
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
260 |
'the latter please let a member of the Ubuntu Stable Release '
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
261 |
'Updates team[3] know so that phasing of the update can '
|
262 |
'proceed.\n\n' |
|
263 |
'[1] Request access to the Ubuntu Error Tracker at '
|
|
264 |
'https://forms.canonical.com/reports/.\n' |
|
265 |
'[2] Learn more about investigating at '
|
|
266 |
'https://wiki.ubuntu.com/StableReleaseUpdates#Phasing\n' |
|
267 |
'[3] https://launchpad.net/~ubuntu-sru' % |
|
268 |
(REPORT_FILE)) |
|
705.1.11
by Brian Murray
improve email formatting |
269 |
for release in releases: |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
270 |
rname = release.name |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
271 |
for spph_link in spph_buckets[rname]: |
272 |
# need to reload the pub_source information
|
|
273 |
pub_source = launchpad.load(spph_link) |
|
274 |
update_percentage = spph_buckets[rname][spph_link].get('pup', 100) |
|
764.2.1
by Brian Murray
phased-updater: do not send emails about fully phased updates |
275 |
# never send emails about updates that are fully phased
|
276 |
if update_percentage == 100: |
|
277 |
continue
|
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
278 |
if 'buckets' not in spph_buckets[rname][spph_link] and \ |
279 |
'rate' not in spph_buckets[rname][spph_link]: |
|
839.1.1
by Brian Murray
phased-updater: if there are no problems with a source package upload, don't check the signer etc, and if the package has no signer (like with a copy from debian) stop trying to create an email |
280 |
continue
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
281 |
signer = pub_source.package_signer |
839.1.1
by Brian Murray
phased-updater: if there are no problems with a source package upload, don't check the signer etc, and if the package has no signer (like with a copy from debian) stop trying to create an email |
282 |
# copies of packages from debian won't have a signer
|
283 |
if not signer: |
|
284 |
continue
|
|
705.1.22
by Brian Murray
make email code slightly less redundant |
285 |
# not an active user of Launchpad
|
286 |
if not signer.is_valid: |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
287 |
logging.info('%s not mailed as they are not a valid LP user' % |
288 |
signer) |
|
705.1.22
by Brian Murray
make email code slightly less redundant |
289 |
continue
|
965.1.1
by Brian Murray
phased-updater: set signer_name to nothing to prevent a traceback. |
290 |
signer_email = get_primary_email(signer) |
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
291 |
signer_name = signer.name |
292 |
# use the changes file as a backup method for determining email addresses
|
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
293 |
changes_file_url = pub_source.changesFileUrl() |
1228.1.1
by Brian Murray
phased-updater: set a default value for changer_name and changer_email |
294 |
changer_name = '' |
295 |
changer_email = '' |
|
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
296 |
try: |
892.1.1
by Brian Murray
phased-updater: use the launchpad changes file to find an email address to notify about a stopped phased update |
297 |
changes_file = urlopen(changes_file_url) |
298 |
for line in changes_file.readlines(): |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
299 |
line = line.decode('utf-8').strip() |
892.1.1
by Brian Murray
phased-updater: use the launchpad changes file to find an email address to notify about a stopped phased update |
300 |
if line.startswith('Changed-By:'): |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
301 |
changer = line.lstrip('Changed-By: ') |
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
302 |
changer_name, changer_email = utils.parseaddr(changer.strip()) |
892.1.1
by Brian Murray
phased-updater: use the launchpad changes file to find an email address to notify about a stopped phased update |
303 |
break
|
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
304 |
except IOError: |
305 |
pass
|
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
306 |
creator = pub_source.package_creator |
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
307 |
creator_email = '' |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
308 |
pkg = pub_source.source_package_name |
309 |
version = pub_source.source_package_version |
|
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
310 |
if not signer_email and signer_name == creator.name: |
311 |
if not changer_email: |
|
312 |
logging.info("No contact email found for %s %s %s" % |
|
313 |
(rname, pkg, version)) |
|
314 |
continue
|
|
315 |
signer_email = changer_email |
|
316 |
logging.info("Used changes file to find contact email for %s %s %s" % |
|
766.1.3
by Brian Murray
be more verbose about why an email address was looked up and skipped |
317 |
(rname, pkg, version)) |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
318 |
if 'buckets' in spph_buckets[rname][spph_link]: |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
319 |
# see if they've been emailed about the bucket before
|
320 |
notices = [] |
|
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
321 |
if signer_name in notifications: |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
322 |
notices = notifications[signer_name] |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
323 |
for notice, notified_pkg, notified_version in notices: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
324 |
if notice in spph_buckets[rname][spph_link]['buckets']: |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
325 |
if (notified_pkg != pkg and |
326 |
notified_version != version): |
|
705.1.42
by Brian Murray
to the email notifications file also write and read the package version which the notification was about |
327 |
continue
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
328 |
spph_buckets[rname][spph_link]['buckets'].remove(notice) |
329 |
if len(spph_buckets[rname][spph_link]['buckets']) == 0: |
|
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
330 |
continue
|
794
by Steve Langasek
Merge lp:~brian-murray/ubuntu-archive-tools/phased-updater-notify-bdmurray |
331 |
receivers = [bdmurray_mail] |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
332 |
quantity = len(spph_buckets[rname][spph_link]['buckets']) |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
333 |
msg = MIMEText( |
334 |
b_body % (pkg, version, rname, ('an ', '')[quantity != 1], |
|
335 |
('', 's')[quantity != 1], |
|
336 |
('was', 'were')[quantity != 1], |
|
337 |
('', 's')[quantity != 1], |
|
338 |
('s', '')[quantity != 1], |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
339 |
'\n'.join(spph_buckets[rname][spph_link]['buckets'])) |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
340 |
+ remedy) |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
341 |
subject = '[%s/%s] Package Phasing Stopped' % (rname, pkg) |
705.1.45
by Brian Murray
switched from print to logging |
342 |
msg['Subject'] = subject |
705.1.22
by Brian Murray
make email code slightly less redundant |
343 |
msg['From'] = EMAIL_SENDER |
793.1.1
by Brian Murray
phased-updater: add my email address as reply-to and include myself in the cc's |
344 |
msg['Reply-To'] = bdmurray_mail |
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
345 |
receivers.append(signer_email) |
346 |
msg['To'] = signer_email |
|
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
347 |
if creator != signer and creator.is_valid: |
348 |
creator_email = get_primary_email(creator) |
|
349 |
# fall back to the email found in the changes file
|
|
350 |
if not creator_email: |
|
351 |
creator_email = changer_email |
|
352 |
receivers.append(creator_email) |
|
353 |
msg['Cc'] = '%s' % changer_email |
|
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
354 |
smtp = smtplib.SMTP('localhost') |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
355 |
smtp.sendmail(EMAIL_SENDER, receivers, |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
356 |
msg.as_string()) |
975.2.1
by Brian Murray
resolve Traceback regarding unicode when using signer information from changes file |
357 |
smtp.quit() |
705.1.45
by Brian Murray
switched from print to logging |
358 |
logging.info('%s mailed about %s' % (receivers, subject)) |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
359 |
# add signer, problem, pkg, version to notifications csv file
|
1027.2.1
by Brian Murray
phased-updater: using codes.open and a utf-8 encoding in case signer's have unicode in their name. |
360 |
with codecs.open(NOTIFICATIONS, 'a', encoding='utf-8') as notify_file: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
361 |
for bucket in spph_buckets[rname][spph_link]['buckets']: |
975.2.1
by Brian Murray
resolve Traceback regarding unicode when using signer information from changes file |
362 |
notify_file.write('%s, %s, %s, %s\n' % \ |
1027.2.2
by Brian Murray
address reviewer feedback |
363 |
(signer_name, bucket, |
1026.1.1
by Brian Murray
phased-updater: utils.parseaddr returns a string so no encoding / decoding is needed. |
364 |
pkg, version)) |
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
365 |
if changer_email: |
366 |
notify_file.write('%s, %s, %s, %s\n' % \ |
|
367 |
(creator.name, bucket, |
|
368 |
pkg, version)) |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
369 |
if 'rate' in spph_buckets[rname][spph_link]: |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
370 |
# see if they have been emailed about the increased rate
|
371 |
# for this package version before
|
|
372 |
notices = [] |
|
373 |
if signer_name in notifications: |
|
374 |
notices = notifications[signer_name] |
|
375 |
if ('increased-rate', pkg, version) in notices: |
|
376 |
continue
|
|
794
by Steve Langasek
Merge lp:~brian-murray/ubuntu-archive-tools/phased-updater-notify-bdmurray |
377 |
receivers = [bdmurray_mail] |
827.1.1
by Brian Murray
phased-updater: urlquote the package version so the link in emails will work |
378 |
msg = MIMEText(i_body % (pkg, quote(version), rname, |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
379 |
spph_buckets[rname][spph_link]['rate'][1]) |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
380 |
+ remedy) |
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
381 |
subject = '[%s/%s] Package Phasing Stopped' % (rname, pkg) |
705.1.45
by Brian Murray
switched from print to logging |
382 |
msg['Subject'] = subject |
705.1.22
by Brian Murray
make email code slightly less redundant |
383 |
msg['From'] = EMAIL_SENDER |
793.1.1
by Brian Murray
phased-updater: add my email address as reply-to and include myself in the cc's |
384 |
msg['Reply-To'] = bdmurray_mail |
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
385 |
receivers.append(signer_email) |
386 |
msg['To'] = signer_email |
|
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
387 |
if creator != signer and creator.is_valid: |
388 |
# fall back to the email found in the changes file
|
|
389 |
if not creator_email: |
|
390 |
creator_email = changer_email |
|
391 |
receivers.append(creator_email) |
|
392 |
msg['Cc'] = '%s' % creator_email |
|
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
393 |
smtp = smtplib.SMTP('localhost') |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
394 |
smtp.sendmail(EMAIL_SENDER, receivers, |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
395 |
msg.as_string()) |
975.2.1
by Brian Murray
resolve Traceback regarding unicode when using signer information from changes file |
396 |
smtp.quit() |
705.1.45
by Brian Murray
switched from print to logging |
397 |
logging.info('%s mailed about %s' % (receivers, subject)) |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
398 |
# add signer, increased-rate, pkg, version to
|
399 |
# notifications csv
|
|
1027.2.1
by Brian Murray
phased-updater: using codes.open and a utf-8 encoding in case signer's have unicode in their name. |
400 |
with codecs.open(NOTIFICATIONS, 'a', encoding='utf-8') as notify_file: |
705.1.49
by Brian Murray
additionally record package name to notifications file so that uploaders are emailed multiple times about an increased package crash rate |
401 |
notify_file.write('%s, increased-rate, %s, %s\n' % |
1027.2.2
by Brian Murray
address reviewer feedback |
402 |
(signer_name, pkg, version)) |
1114.1.1
by Brian Murray
phased-updater: if looking up an email address in LP fails, really fall back to using the changes file. |
403 |
if creator_email: |
404 |
notify_file.write('%s, increased-rate, %s, %s\n' % |
|
405 |
(creator.name, pkg, version)) |
|
705.1.1
by Brian Murray
first draft of phased-updater |
406 |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
407 |
|
705.1.16
by Brian Murray
phased-updater: remove new_buckets function that used first_appearance |
408 |
def new_buckets(archive, release, src_pkg, version): |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
409 |
# can't use created_since here because it have may been uploaded
|
410 |
# before the release date
|
|
411 |
spph = archive.getPublishedSources(distro_series=release, |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
412 |
source_name=src_pkg, exact_match=True) |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
413 |
pubs = [(ph.date_published, ph.source_package_version) for ph in spph |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
414 |
if ph.status != 'Deleted' and ph.pocket != 'Backports' |
415 |
and ph.pocket != 'Proposed' |
|
705.1.24
by Brian Murray
display the phased_update_percentage for binary packages which have no errors but are phasing |
416 |
and ph.date_published is not None] |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
417 |
pubs = sorted(pubs) |
418 |
# it is possible for the same version to appear multiple times
|
|
419 |
numbers = set([pub[1] for pub in pubs]) |
|
1322.1.1
by Brian Murray
phased-updater: improve email, and creator and signer to the report, link to investigative tips |
420 |
versions = sorted(numbers, key=cmp_to_key(apt.apt_pkg.version_compare)) |
705.1.13
by Brian Murray
sort releases, use real_new_bucket, print a has in the html report |
421 |
# it never appeared in release e.g. cedarview-drm-drivers in precise
|
422 |
try: |
|
423 |
previous_version = versions[-2] |
|
424 |
except IndexError: |
|
705.1.19
by Brian Murray
multiple improvements |
425 |
return False |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
426 |
new_version = versions[-1] |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
427 |
new_buckets_url = '%spackage-version-new-buckets/?format=json&' % \ |
813.2.2
by Brian Murray
phased-updater: switch back to using errors instead of a local version of it |
428 |
(BASE_ERRORS_URL) + \ |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
429 |
'package=%s&previous_version=%s&new_version=%s' % \ |
430 |
(quote(src_pkg), quote(previous_version), quote(new_version)) |
|
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
431 |
try: |
432 |
new_buckets_file = urlopen(new_buckets_url) |
|
433 |
except IOError: |
|
434 |
return 'error' |
|
952.1.1
by Brian Murray
phased-updater: return True for rate increase or new crashes if we don't receive a 200 response from the Error Tracker |
435 |
# If we don't receive an OK response from the Error Tracker we should not
|
436 |
# increment the phased-update-percentage.
|
|
437 |
if new_buckets_file.getcode() != 200: |
|
745.1.1
by Brian Murray
also handled 502 error codes |
438 |
logging.error('HTTP error retrieving %s' % new_buckets_url) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
439 |
return 'error' |
966.1.1
by Brian Murray
Handle a traceback when decoding json from errors.u.c. |
440 |
try: |
441 |
new_buckets_data = json.load(new_buckets_file) |
|
442 |
except json.decoder.JSONDecodeError: |
|
443 |
logging.error('Error getting new buckets at %s' % new_buckets_url) |
|
444 |
return 'error' |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
445 |
if 'error_message' in list(new_buckets_data.keys()): |
705.1.45
by Brian Murray
switched from print to logging |
446 |
logging.error('Error getting new buckets at %s' % new_buckets_url) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
447 |
return 'error' |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
448 |
if len(new_buckets_data['objects']) == 0: |
705.1.19
by Brian Murray
multiple improvements |
449 |
return False |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
450 |
buckets = [] |
451 |
for bucket in new_buckets_data['objects']: |
|
791.1.1
by Brian Murray
phased-updater: ignore package install failures |
452 |
# Do not consider package install failures until they have more
|
1020.1.1
by Brian Murray
phased-updater: skip buckets regarding already installed and configured errors again |
453 |
# information added to the instances.
|
791.1.1
by Brian Murray
phased-updater: ignore package install failures |
454 |
if bucket['function'].startswith('package:'): |
455 |
continue
|
|
1020.1.1
by Brian Murray
phased-updater: skip buckets regarding already installed and configured errors again |
456 |
# 16.04's duplicate signature for ProblemType: Package doesn't
|
457 |
# start with 'package:' so check for strings in the bucket.
|
|
458 |
if 'is already installed and configured' in bucket['function']: |
|
459 |
logging.info('Skipped already installed bucket %s' % |
|
460 |
bucket['web_link']) |
|
461 |
continue
|
|
705.1.44
by Brian Murray
do not try again if there is an error getting the json file from errors |
462 |
# Skip failed buckets as they don't have useful tracebacks
|
813.1.1
by Brian Murray
phased-updater: disable rate increase checking while new errors API is being rolled out |
463 |
if bucket['function'].startswith('failed:'): |
705.1.45
by Brian Murray
switched from print to logging |
464 |
logging.info('Skipped failed to retrace bucket %s' % |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
465 |
bucket['web_link']) |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
466 |
continue
|
1052.1.1
by Brian Murray
confirm that the package version has crash reports for the release the SRU appears in |
467 |
# check to see if the version appears for the affected release
|
468 |
versions_url = '%sversions/?format=json&id=%s' % \ |
|
469 |
((BASE_ERRORS_URL) , quote(bucket['function'].encode('utf-8'))) |
|
470 |
try: |
|
471 |
versions_data_file = urlopen(versions_url) |
|
472 |
except IOError: |
|
473 |
logging.error('Error getting release versions at %s' % versions_url) |
|
474 |
# don't return an error because its better to have a false positive
|
|
475 |
# in this case
|
|
476 |
buckets.append(bucket['web_link']) |
|
477 |
continue
|
|
478 |
try: |
|
479 |
versions_data = json.load(versions_data_file) |
|
480 |
except json.decoder.JSONDecodeError: |
|
481 |
logging.error('Error getting release versions at %s' % versions_url) |
|
482 |
# don't return an error because its better to have a false positive
|
|
483 |
# in this case
|
|
484 |
buckets.append(bucket['web_link']) |
|
485 |
continue
|
|
1057.1.1
by Brian Murray
phased-updater: resolve a traceback when errors is unresponsive |
486 |
if 'error_message' in versions_data: |
487 |
# don't return an error because its better to have a false positive
|
|
488 |
# in this case
|
|
489 |
buckets.append(bucket['web_link']) |
|
490 |
continue
|
|
1052.1.1
by Brian Murray
confirm that the package version has crash reports for the release the SRU appears in |
491 |
# -1 means that release isn't affected
|
492 |
if len([vd[release.name] for vd in versions_data['objects'] \ |
|
493 |
if vd['version'] == new_version and vd[release.name] != -1]) == 0: |
|
494 |
continue
|
|
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
495 |
buckets.append(bucket['web_link']) |
788.1.1
by Brian Murray
phased-updater: skip already installed and configured package install failures |
496 |
logging.info('Details (new buckets): %s' % new_buckets_url) |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
497 |
return buckets |
705.1.1
by Brian Murray
first draft of phased-updater |
498 |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
499 |
|
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
500 |
def package_previous_version(release, src_pkg, version): |
501 |
# return previous package version from updates or release and
|
|
502 |
# the publication date of the current package version
|
|
503 |
ubuntu = launchpad.distributions['ubuntu'] |
|
504 |
primary = ubuntu.getArchive(name='primary') |
|
505 |
current_version_date = None |
|
506 |
previous_version = None |
|
813.2.4
by Brian Murray
phased-updater: add in a comment regarding ordering of getPublishedSources |
507 |
# Archive.getPublishedSources returns results ordered by
|
508 |
# (name, id) where the id number is autocreated, subsequently
|
|
509 |
# the newest package versions are returned first
|
|
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
510 |
for spph in primary.getPublishedSources(source_name=src_pkg, |
511 |
distro_series=release, |
|
512 |
exact_match=True): |
|
513 |
if spph.pocket == 'Proposed': |
|
514 |
continue
|
|
515 |
if spph.status == 'Deleted': |
|
516 |
continue
|
|
517 |
if spph.source_package_version == version: |
|
518 |
if not current_version_date: |
|
519 |
current_version_date = spph.date_published.date() |
|
520 |
elif spph.date_published.date() > current_version_date: |
|
521 |
current_version_date = spph.date_published.date() |
|
522 |
if spph.pocket == 'Updates' and spph.status == 'Superseded': |
|
523 |
return (spph.source_package_version, current_version_date) |
|
524 |
if spph.pocket == 'Release' and spph.status == 'Published': |
|
525 |
return (spph.source_package_version, current_version_date) |
|
526 |
return (None, None) |
|
527 |
||
528 |
||
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
529 |
def crash_rate_increase(release, src_pkg, version, last_pup): |
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
530 |
pvers, date = package_previous_version(release, src_pkg, version) |
531 |
date = str(date).replace('-', '') |
|
532 |
if not pvers: |
|
533 |
# joyent-mdata-client was put in updates w/o being in the release
|
|
534 |
# pocket
|
|
535 |
return False |
|
536 |
release_name = 'Ubuntu ' + release.version |
|
813.2.2
by Brian Murray
phased-updater: switch back to using errors instead of a local version of it |
537 |
rate_url = BASE_ERRORS_URL + 'package-rate-of-crashes/?format=json' + \ |
948.1.1
by Brian Murray
phased-updater: utilize API ability to subtract crashes from -proposed users in rate of crashes check |
538 |
'&exclude_proposed=True' + \ |
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
539 |
'&release=%s&package=%s&old_version=%s&new_version=%s&phased_update_percentage=%s&date=%s' % \ |
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
540 |
(quote(release_name), quote(src_pkg), quote(pvers), quote(version), |
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
541 |
last_pup, date) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
542 |
try: |
543 |
rate_file = urlopen(rate_url) |
|
544 |
except IOError: |
|
545 |
return 'error' |
|
952.1.1
by Brian Murray
phased-updater: return True for rate increase or new crashes if we don't receive a 200 response from the Error Tracker |
546 |
# If we don't receive an OK response from the Error Tracker we should not
|
547 |
# increment the phased-update-percentage.
|
|
548 |
if rate_file.getcode() != 200: |
|
745.1.1
by Brian Murray
also handled 502 error codes |
549 |
logging.error('HTTP error retrieving %s' % rate_url) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
550 |
return 'error' |
966.1.1
by Brian Murray
Handle a traceback when decoding json from errors.u.c. |
551 |
try: |
552 |
rate_data = json.load(rate_file) |
|
553 |
except json.decoder.JSONDecodeError: |
|
554 |
logging.error('Error getting rate at %s' % rate_url) |
|
555 |
return 'error' |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
556 |
if 'error_message' in list(rate_data.keys()): |
705.1.45
by Brian Murray
switched from print to logging |
557 |
logging.error('Error getting rate at %s' % rate_url) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
558 |
return 'error' |
818.1.4
by Brian Murray
modify comment and change where logging occurs |
559 |
logging.info('Details (rate increase): %s' % rate_url) |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
560 |
# this may not be useful if the buckets creating the increase have
|
561 |
# failed to retrace
|
|
705.1.1
by Brian Murray
first draft of phased-updater |
562 |
for data in rate_data['objects']: |
563 |
if data['increase']: |
|
705.1.33
by Brian Murray
resolve issue with rate of crashes query, and create a no act switch so pup is not changed |
564 |
previous_amount = data['previous_average'] |
818.1.4
by Brian Murray
modify comment and change where logging occurs |
565 |
# this may happen if there were no crashes reported about
|
566 |
# the previous version of the package
|
|
818.1.3
by Brian Murray
phased-updater: deal with the case where an increase is seen because there is not data for the previous version of the package |
567 |
if not previous_amount: |
568 |
logging.info('No previous crash data found for %s %s' % |
|
569 |
(src_pkg, pvers)) |
|
834.1.1
by Brian Murray
phased-updater: only add version to web_link if it wasn't provided |
570 |
previous_amount = 0 |
705.1.34
by Brian Murray
update rate increase calculation to deal with new output format from errors |
571 |
if 'difference' in data: |
572 |
increase = data['difference'] |
|
573 |
elif 'this_count' in data: |
|
574 |
# 2013-06-17 this can be negative due to the portion of the
|
|
575 |
# day math (we take the average crashes and multiple them by
|
|
576 |
# the fraction of hours that have passed so far in the day)
|
|
577 |
current_amount = data['this_count'] |
|
578 |
increase = current_amount - previous_amount |
|
766.1.4
by Brian Murray
always set the rate_increase to false so that phasing is not stopped because of it |
579 |
logging.info('[%s/%s] increase: %s, previous_avg: %s' % |
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
580 |
(release_name.replace('Ubuntu ', ''), src_pkg, |
581 |
increase, previous_amount)) |
|
834.1.1
by Brian Murray
phased-updater: only add version to web_link if it wasn't provided |
582 |
if '&version=' not in data['web_link']: |
583 |
link = data['web_link'] + '&version=%s' % version |
|
584 |
else: |
|
585 |
link = data['web_link'] |
|
788.1.1
by Brian Murray
phased-updater: skip already installed and configured package install failures |
586 |
logging.info('Details (rate increase): %s' % link) |
705.1.33
by Brian Murray
resolve issue with rate of crashes query, and create a no act switch so pup is not changed |
587 |
return(increase, link) |
705.1.1
by Brian Murray
first draft of phased-updater |
588 |
|
757
by Stéphane Graber
Fix all PEP-8 warnings. |
589 |
|
705.1.1
by Brian Murray
first draft of phased-updater |
590 |
def main(): |
705.1.22
by Brian Murray
make email code slightly less redundant |
591 |
# TODO: make email code less redundant
|
705.1.35
by Brian Murray
clarify what the report is about |
592 |
# TODO: modify HTTP_USER_AGENT (both versions of urllib)
|
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
593 |
# TODO: Open bugs for regressions when false positives reduced
|
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
594 |
options.archive = archive |
705.1.1
by Brian Murray
first draft of phased-updater |
595 |
|
705.1.6
by Brian Murray
rename whitelist to overrides |
596 |
overrides = defaultdict(list) |
766.1.1
by Brian Murray
phased-updater: provide a way to override an increased rate of crashes, if a phased-update is being restarted start it from the highest p-u-p |
597 |
rate_overrides = [] |
705.1.6
by Brian Murray
rename whitelist to overrides |
598 |
override_file = csv.reader(open(OVERRIDES, 'r')) |
599 |
for row in override_file: |
|
771
by Colin Watson
phased-updater: handle short rows in override file (e.g. blank lines) |
600 |
if len(row) < 3: |
601 |
continue
|
|
705.1.4
by Brian Murray
implement whitelist support |
602 |
# package, version, problem
|
603 |
if row[0].startswith('#'): |
|
604 |
continue
|
|
605 |
package = row[0].strip() |
|
606 |
version = row[1].strip() |
|
607 |
problem = row[2].strip() |
|
766.1.1
by Brian Murray
phased-updater: provide a way to override an increased rate of crashes, if a phased-update is being restarted start it from the highest p-u-p |
608 |
if problem == 'increased-rate': |
609 |
rate_overrides.append((package, version)) |
|
610 |
else: |
|
611 |
overrides[(package, version)].append(problem) |
|
705.1.4
by Brian Murray
implement whitelist support |
612 |
|
705.1.10
by Brian Murray
switched to one report for all releases |
613 |
releases = [] |
614 |
for series in ubuntu.series: |
|
615 |
if series.active: |
|
616 |
if series.status == 'Active Development': |
|
617 |
continue
|
|
618 |
releases.append(series) |
|
705.1.13
by Brian Murray
sort releases, use real_new_bucket, print a has in the html report |
619 |
releases.reverse() |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
620 |
issues = {} |
705.1.10
by Brian Murray
switched to one report for all releases |
621 |
for release in releases: |
1100.1.1
by Brian Murray
phased-updater: workaround LP timing out when we call getPublishedBinaries() |
622 |
# We can't use release.datereleased because some SRUs are 0 day
|
623 |
cdate = release.date_created |
|
705.1.10
by Brian Murray
switched to one report for all releases |
624 |
rname = release.name |
705.1.33
by Brian Murray
resolve issue with rate of crashes query, and create a no act switch so pup is not changed |
625 |
rvers = release.version |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
626 |
issues[rname] = OrderedDict() |
1400.2.3
by Brian Murray
phased-updater: check to see who set the phased_update_percentage and respect it |
627 |
# XXX - precise and trusty are ESM
|
628 |
if rname in ('precise', 'trusty'): |
|
705.1.10
by Brian Murray
switched to one report for all releases |
629 |
continue
|
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
630 |
pub_sources = archive.getPublishedSources( |
1100.1.1
by Brian Murray
phased-updater: workaround LP timing out when we call getPublishedBinaries() |
631 |
created_since_date=cdate, |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
632 |
order_by_date=True, |
705.1.10
by Brian Murray
switched to one report for all releases |
633 |
pocket='Updates', status='Published', distro_series=release) |
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
634 |
for pub_source in pub_sources: |
705.1.10
by Brian Murray
switched to one report for all releases |
635 |
src_pkg = pub_source.source_package_name |
636 |
version = pub_source.source_package_version |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
637 |
spph_link = pub_source.self_link |
813.2.1
by Brian Murray
phased-updater: switch to using new crash rate api on the error tracker |
638 |
pbs = None |
1100.1.1
by Brian Murray
phased-updater: workaround LP timing out when we call getPublishedBinaries() |
639 |
try: |
640 |
pbs = [pb for pb in pub_source.getPublishedBinaries() |
|
641 |
if pb.phased_update_percentage is not None] |
|
642 |
# workaround for LP: #1695113
|
|
643 |
except lazr.restfulclient.errors.ServerError as e: |
|
644 |
if 'HTTP Error 503' in str(e): |
|
645 |
logging.info('Skipping 503 Error for %s' % src_pkg) |
|
646 |
pass
|
|
796.1.1
by Brian Murray
don't query errors for packages which don't have a phased_update_percentage |
647 |
if not pbs: |
799
by Colin Watson
regularise indentation |
648 |
continue
|
766.1.2
by Brian Murray
updated based on reviewer feedback |
649 |
if pbs: |
650 |
# the p-u-p is currently the same for all binary packages
|
|
651 |
last_pup = pbs[0].phased_update_percentage |
|
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
652 |
else: |
653 |
last_pup = None |
|
1038.1.1
by Brian Murray
Don't set max_pup to None because we try and add it to an int. |
654 |
max_pup = 0 |
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
655 |
if last_pup == 0: |
1400.1.1
by Brian Murray
phased-updater: create a dictionary with info about packages which shouldn't phase |
656 |
for allpb in archive.getPublishedBinaries( |
657 |
exact_match=True, pocket='Updates', |
|
658 |
binary_name=pbs[0].binary_package_name): |
|
659 |
if allpb.distro_arch_series.distroseries == release: |
|
660 |
if allpb.phased_update_percentage > 0: |
|
661 |
max_pup = allpb.phased_update_percentage |
|
662 |
break
|
|
1400.2.3
by Brian Murray
phased-updater: check to see who set the phased_update_percentage and respect it |
663 |
if pbs[0].creator_link: |
664 |
creator = pbs[0].creator_link.split('/')[-1] |
|
665 |
else: |
|
666 |
creator = '~ubuntu-archive-robot' |
|
667 |
# the phasing was manually set to 0 by someone
|
|
668 |
if creator != '~ubuntu-archive-robot': |
|
669 |
logging.info('Not considering %s as it was manually stopped' % src_pkg) |
|
670 |
# these all need to be set for the html report
|
|
671 |
issues[rname][spph_link] = {} |
|
672 |
issues[rname][spph_link]['buckets'] = ['force-stop'] |
|
673 |
issues[rname][spph_link]['max_pup'] = max_pup |
|
674 |
issues[rname][spph_link]['previous_pup'] = max_pup |
|
675 |
issues[rname][spph_link]['pup'] = last_pup |
|
676 |
continue
|
|
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
677 |
if max_pup and last_pup == 0: |
678 |
rate_increase = crash_rate_increase(release, src_pkg, version, max_pup) |
|
679 |
else: |
|
680 |
rate_increase = crash_rate_increase(release, src_pkg, version, last_pup) |
|
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
681 |
problems = new_buckets(archive, release, src_pkg, version) |
682 |
# In the event that there as an error connecting to errors.ubuntu.com then
|
|
683 |
# neither increase nor stop the phased-update.
|
|
684 |
if rate_increase == 'error' or problems == 'error': |
|
685 |
logging.info("Skipping %s due to failure to get data from Errors." % src_pkg) |
|
686 |
continue
|
|
687 |
if problems: |
|
688 |
if (src_pkg, version) in overrides: |
|
689 |
not_overrode = set(problems).difference( |
|
690 |
set(overrides[(src_pkg, version)])) |
|
691 |
if len(not_overrode) > 0: |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
692 |
issues[rname][spph_link] = {} |
693 |
issues[rname][spph_link]['buckets'] = not_overrode |
|
964.1.1
by Brian Murray
Improve error handling when communicating with errors.u.c. |
694 |
else: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
695 |
issues[rname][spph_link] = {} |
696 |
issues[rname][spph_link]['buckets'] = problems |
|
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
697 |
if rate_increase and (src_pkg, version) not in rate_overrides: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
698 |
if spph_link not in issues[rname]: |
699 |
issues[rname][spph_link] = {} |
|
700 |
issues[rname][spph_link]['rate'] = rate_increase |
|
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
701 |
if pbs: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
702 |
if spph_link not in issues[rname]: |
703 |
issues[rname][spph_link] = {} |
|
929.1.1
by Brian Murray
phased-updater: enable rate of crash checking again and utilize phased-update-percentage in comparing rate of crashes. |
704 |
# phasing has stopped so check what the max value was
|
705 |
if last_pup == 0: |
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
706 |
issues[rname][spph_link]['max_pup'] = max_pup |
707 |
issues[rname][spph_link]['pup'] = last_pup |
|
705.1.28
by Brian Murray
implemented setting of phased_update_percentage to 0 or incrementing it |
708 |
suite = rname + '-updates' |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
709 |
if spph_link not in issues[rname]: |
705.1.24
by Brian Murray
display the phased_update_percentage for binary packages which have no errors but are phasing |
710 |
continue
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
711 |
elif ('rate' not in issues[rname][spph_link] and |
712 |
'buckets' not in issues[rname][spph_link] and |
|
766.1.2
by Brian Murray
updated based on reviewer feedback |
713 |
pbs): |
705.1.28
by Brian Murray
implemented setting of phased_update_percentage to 0 or incrementing it |
714 |
# there is not an error so increment the phasing
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
715 |
current_pup = issues[rname][spph_link]['pup'] |
796.1.5
by Brian Murray
phased-updater: be sure to restart at max_pup |
716 |
# if this is an update that is restarting we want to start at
|
717 |
# the same percentage the stoppage happened at
|
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
718 |
if 'max_pup' in issues[rname][spph_link]: |
719 |
current_pup = issues[rname][spph_link]['max_pup'] |
|
705.1.38
by Brian Murray
for stopped updates show the percentage the update was stopped at and link to the binary publishing history |
720 |
new_pup = current_pup + PUP_INCREMENT |
1380.1.1
by Dimitri John Ledkov
Implement slow phasing for secureboot-db. |
721 |
if src_pkg in SLOW_PACKAGES: |
722 |
new_pup = current_pup + PUP_SLOW_INCREMENT |
|
705.1.46
by Brian Murray
rename long option for -n and add switch for emailing developers |
723 |
if not options.no_act: |
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
724 |
set_pup(current_pup, new_pup, release, suite, src_pkg) |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
725 |
issues[rname][spph_link]['pup'] = new_pup |
766.1.2
by Brian Murray
updated based on reviewer feedback |
726 |
elif pbs: |
705.1.52
by Brian Murray
move a comment |
727 |
# there is an error and pup is not None so stop the phasing
|
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
728 |
current_pup = issues[rname][spph_link]['pup'] |
729 |
if 'max_pup' in issues[rname][spph_link]: |
|
730 |
issues[rname][spph_link]['previous_pup'] = \ |
|
731 |
issues[rname][spph_link]['max_pup'] |
|
818.1.2
by Brian Murray
phased-updater: fix another traceback |
732 |
else: |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
733 |
issues[rname][spph_link]['previous_pup'] = \ |
818.1.2
by Brian Murray
phased-updater: fix another traceback |
734 |
current_pup
|
705.1.38
by Brian Murray
for stopped updates show the percentage the update was stopped at and link to the binary publishing history |
735 |
new_pup = 0 |
705.1.46
by Brian Murray
rename long option for -n and add switch for emailing developers |
736 |
if (not options.no_act and |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
737 |
issues[rname][spph_link]['pup'] != 0): |
705.1.55
by Brian Murray
directly call changeOverride in the Launchpad API rather than using subprocess to call change-override |
738 |
set_pup(current_pup, new_pup, release, suite, src_pkg) |
1374.1.1
by Brian Murray
phased-updater: transition from python2 to python3 |
739 |
issues[rname][spph_link]['pup'] = new_pup |
705.1.31
by Brian Murray
do not set pup to 0 if it is already 0, fix line length issues |
740 |
generate_html_report(releases, issues) |
705.1.46
by Brian Murray
rename long option for -n and add switch for emailing developers |
741 |
if options.email: |
742 |
create_email_notifications(releases, issues) |
|
705.1.1
by Brian Murray
first draft of phased-updater |
743 |
|
744 |
if __name__ == '__main__': |
|
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
745 |
start_time = time.time() |
705.1.1
by Brian Murray
first draft of phased-updater |
746 |
BASE_ERRORS_URL = 'https://errors.ubuntu.com/api/1.0/' |
705.1.7
by Brian Murray
create code for using errors api package-version-new-buckets |
747 |
LOCAL_ERRORS_URL = 'http://10.0.3.182/api/1.0/' |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
748 |
LP_BASE_URL = 'https://launchpad.net' |
705.1.6
by Brian Murray
rename whitelist to overrides |
749 |
OVERRIDES = 'phased-updates-overrides.txt' |
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
750 |
NOTIFICATIONS = 'phased-updates-emails.txt' |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
751 |
EMAIL_SENDER = 'brian.murray@ubuntu.com' |
705.1.30
by Brian Murray
send output of change-override to devnull |
752 |
PUP_INCREMENT = 10 |
1380.1.1
by Dimitri John Ledkov
Implement slow phasing for secureboot-db. |
753 |
SLOW_PACKAGES = {'secureboot-db'} |
754 |
PUP_SLOW_INCREMENT = 1 |
|
939.1.1
by Brian Murray
phased-updater: include a link to the html report showing phasing progress when e-mailing people. |
755 |
REPORT_FILE = 'phased-updates.html' |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
756 |
parser = OptionParser(usage="usage: %prog [options]") |
705.1.25
by Brian Murray
add in support for other launchpad instances, add % sign to update percentage |
757 |
parser.add_option( |
758 |
"-l", "--launchpad", dest="launchpad_instance", default="production") |
|
705.1.33
by Brian Murray
resolve issue with rate of crashes query, and create a no act switch so pup is not changed |
759 |
parser.add_option( |
705.1.46
by Brian Murray
rename long option for -n and add switch for emailing developers |
760 |
"-n", "--no-act", default=False, action="store_true", |
705.1.33
by Brian Murray
resolve issue with rate of crashes query, and create a no act switch so pup is not changed |
761 |
help="do not modify phased update percentages") |
705.1.46
by Brian Murray
rename long option for -n and add switch for emailing developers |
762 |
parser.add_option( |
763 |
"-e", "--email", default=False, action="store_true", |
|
764 |
help="send email notifications to uploaders") |
|
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
765 |
parser.add_option( |
766 |
"-f", "--fully-phased", default=False, action="store_true", |
|
767 |
help="show packages which have been fully phased") |
|
705.1.25
by Brian Murray
add in support for other launchpad instances, add % sign to update percentage |
768 |
options, args = parser.parse_args() |
705.1.48
by Brian Murray
remove testing code add switch for showing updates that have been fully phased |
769 |
if options.launchpad_instance != 'production': |
770 |
LP_BASE_URL = 'https://%s.launchpad.net' % options.launchpad_instance |
|
767.2.1
by Brian Murray
phased-updater: identify security updates |
771 |
if options.email and options.fully_phased: |
772 |
parser.error("Sending emails and fully phased updates are mutually \ |
|
773 |
exclusive.") |
|
705.1.12
by Brian Murray
create an increased rate of crashes email, use one dictionary for problem and rate information |
774 |
launchpad = Launchpad.login_with( |
705.1.25
by Brian Murray
add in support for other launchpad instances, add % sign to update percentage |
775 |
'phased-updater', options.launchpad_instance, version='devel') |
705.1.45
by Brian Murray
switched from print to logging |
776 |
logging.basicConfig(filename='phased-updates.log', |
757
by Stéphane Graber
Fix all PEP-8 warnings. |
777 |
format='%(asctime)s - %(levelname)s - %(message)s', |
778 |
level=logging.INFO) |
|
705.1.47
by Brian Murray
log start and end times |
779 |
logging.info('Starting phased-updater') |
767.2.1
by Brian Murray
phased-updater: identify security updates |
780 |
ubuntu = launchpad.distributions['ubuntu'] |
781 |
archive = ubuntu.getArchive(name='primary') |
|
705.1.1
by Brian Murray
first draft of phased-updater |
782 |
main() |
705.1.14
by Brian Murray
keep track of emails sent by the phased-updater |
783 |
end_time = time.time() |
705.1.47
by Brian Murray
log start and end times |
784 |
logging.info("Elapsed time was %g seconds" % (end_time - start_time)) |