Merge lp:~gandelman-a/cloud-archive-utils/metabug into lp:cloud-archive-utils

Proposed by Adam Gandelman on 2014-01-03
Status: Work in progress
Proposed branch: lp:~gandelman-a/cloud-archive-utils/metabug
Merge into: lp:cloud-archive-utils
Diff against target: 322 lines (+211/-13)
4 files modified
bin/cloud-archive-metabug (+95/-0)
bin/cloud-archive-sru-released (+3/-1)
cloudarchive/common.py (+20/-0)
cloudarchive/utils.py (+93/-12)
To merge this branch: bzr merge lp:~gandelman-a/cloud-archive-utils/metabug
Reviewer Review Type Date Requested Status
Ubuntu Cloud Archive Team 2014-01-03 Pending
Review via email: mp+200362@code.launchpad.net

Description of the change

Adds a new utilitiy script: cloud-archive-metabug, which can be used to quickly open SRU tracking bugs ala Bug #1262788

Updates version constants for new Ubuntu/OS releases and adds some utility mappings.l

To post a comment you must log in.
18. By Adam Gandelman on 2014-01-03

Rebase on trunk, do not login to LP anonymously

Unmerged revisions

18. By Adam Gandelman on 2014-01-03

Rebase on trunk, do not login to LP anonymously

17. By Adam Gandelman on 2014-01-03

Adds cloud-archive-metabug script, updates existing version constants and adds a few more

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'bin/cloud-archive-metabug'
2--- bin/cloud-archive-metabug 1970-01-01 00:00:00 +0000
3+++ bin/cloud-archive-metabug 2014-01-03 00:54:05 +0000
4@@ -0,0 +1,95 @@
5+#!/usr/bin/python
6+
7+import optparse
8+import sys
9+
10+from ubuntutools.logger import Logger
11+
12+from cloudarchive import utils, common
13+
14+
15+MSG_TEMPLATE = """
16+This is a meta-bug used for tracking progress of the OpenStack
17+%(os_vers)s %(os_series)s stable updates to %(packages_list)s
18+in Ubuntu %(ubuntu_series)s %(ubuntu_vers)s and the Ubuntu Cloud Archive.
19+"""
20+
21+
22+def die(msg):
23+ Logger.error(msg)
24+ sys.exit(1)
25+
26+
27+def create_new_metabug(packages, os_vers):
28+ '''Creates a new meta bug report affecting a single package
29+ and populates with message'''
30+ p1 = packages[0]
31+ packages_list = ', '.join([p.capitalize() for p in packages])
32+ os_series = utils.openstack_series(os_vers)
33+ ubuntu_series = utils.ubuntu_series(os_series).capitalize()
34+ ubuntu_vers = utils.ubuntu_version(ubuntu_series)
35+ Logger.normal('Creating new bug report initially targetting %s' % p1)
36+ msg = MSG_TEMPLATE % locals()
37+ # TODO: Create and return the bug
38+
39+
40+if __name__ == '__main__':
41+ usage = 'usage: %prog [options] [projects]'
42+ parser = optparse.OptionParser(usage=usage)
43+ parser.add_option('-b', '--bug',
44+ help='Existing bug # to update',
45+ dest='bug_no', action='store')
46+ parser.add_option('-v', '--version',
47+ help='OpenStack Stable version (ie, 2013.1.2)',
48+ dest='os_version', action='store')
49+ (opts, args) = parser.parse_args()
50+
51+ if not opts.os_version:
52+ die('Must specify an OpenStack stable version')
53+ elif not args:
54+ die('Must specify a comma-separated list of packages to target')
55+
56+ packages = [a.strip() for a in args[0].split(',')]
57+ os_vers = opts.os_version
58+ os_series = utils.openstack_series(os_vers)
59+ ubuntu_series = utils.ubuntu_series(os_series)
60+
61+ Logger.normal(
62+ 'Meta-bug will target %s/%s affecting: %s' %
63+ (ubuntu_series, os_series, ' '.join(packages)))
64+
65+ if not opts.bug_no:
66+ bug = create_new_metabug(packages, os_vers)
67+ else:
68+ bug = utils.get_bug(opts.bug_no)
69+
70+ for p in packages:
71+ affects_package = False
72+ has_task = False
73+ found = False
74+
75+ for task in utils.affected_packages(bug):
76+ if task.name != p:
77+ found = False
78+ continue
79+
80+ # ensure metabug tasks are invalidated against ubuntu dev rel.
81+ if task.series == common.UBUNTU_DEV:
82+ if task.status != 'Invalid':
83+ utils.set_task_status(task.lp_task, status='Invalid')
84+ affects_package = True
85+
86+ if task.series == ubuntu_series:
87+ if task.status != 'Confirmed':
88+ utils.set_task_status(task.lp_task, status='Confirmed')
89+ has_task = True
90+
91+ if not affects_package:
92+ utils.create_task(
93+ bug=bug, package=p, series=common.UBUNTU_DEV, status='Invalid')
94+
95+ if not has_task:
96+ utils.create_task(
97+ bug=bug, package=p, series=ubuntu_series, status='Confirmed')
98+
99+ utils.set_cloud_archive_task_status(bug, 'Confirmed')
100
101=== modified file 'bin/cloud-archive-sru-released'
102--- bin/cloud-archive-sru-released 2013-07-01 20:47:20 +0000
103+++ bin/cloud-archive-sru-released 2014-01-03 00:54:05 +0000
104@@ -61,4 +61,6 @@
105 sys.exit(0)
106
107 utils.set_cloud_archive_task_status(lp_bug, status='Fix Released')
108- utils.post_message(bug=lp_bug, message=msg)
109+ utils.post_message(
110+ bug=lp_bug, message=msg,
111+ subject='Fix Released in the Ubuntu Cloud Archive')
112
113=== modified file 'cloudarchive/common.py'
114--- cloudarchive/common.py 2013-12-03 21:50:47 +0000
115+++ cloudarchive/common.py 2014-01-03 00:54:05 +0000
116@@ -22,6 +22,15 @@
117 "icehouse",
118 ]
119
120+
121+OS_VERSION = {
122+ "2012.2": "folsom",
123+ "2013.1": "grizzly",
124+ "2013.2": "havana",
125+ "2014.1": "icehouse",
126+}
127+
128+
129 SOURCE_RELEASE = {
130 "folsom": "quantal",
131 "grizzly": "raring",
132@@ -30,11 +39,22 @@
133 }
134
135 UBUNTU_SERIES = [
136+ 'precise',
137+ 'quantal',
138 'raring',
139 'saucy',
140 'trusty',
141 ]
142
143+
144+UBUNTU_VERSION = {
145+ '12.04': 'precise',
146+ '12.10': 'quantal',
147+ '13.04': 'raring',
148+ '13.10': 'saucy',
149+ '14.04': 'trust',
150+}
151+
152 UBUNTU_DEV = UBUNTU_SERIES[-1]
153 UBUNTU_STABLE = UBUNTU_SERIES[-2]
154
155
156=== modified file 'cloudarchive/utils.py'
157--- cloudarchive/utils.py 2013-12-03 19:49:46 +0000
158+++ cloudarchive/utils.py 2014-01-03 00:54:05 +0000
159@@ -1,18 +1,28 @@
160 import logging
161+import os
162 import re
163
164+from collections import namedtuple
165+
166 from apt_pkg import version_compare
167
168 from ubuntutools.logger import Logger
169-from common import SERIES, SOURCE_RELEASE, LTS_SERIES
170+from common import (
171+ SERIES, SOURCE_RELEASE, LTS_SERIES, OS_VERSION, UBUNTU_DEV, UBUNTU_VERSION)
172
173 from ubuntutools.lp.lpapicache import (Launchpad, Distribution,
174 PackageNotFoundException)
175
176+from lazr.restfulclient.errors import BadRequest
177+
178
179 def get_lp():
180+ if os.getenv('LP_STAGING'):
181+ service = 'staging'
182+ else:
183+ service = 'production'
184 if not Launchpad.logged_in:
185- Launchpad.login_anonymously()
186+ Launchpad.login(service=service)
187
188
189 def ubuntu_series(os_series):
190@@ -22,6 +32,17 @@
191 return SOURCE_RELEASE[r]
192
193
194+def ubuntu_version(ubuntu_series):
195+ '''Return the Ubuntu version number for a given series codename'''
196+ ubuntu_series = ubuntu_series.lower()
197+ for vers, codename in UBUNTU_VERSION.iteritems():
198+ if codename == ubuntu_series:
199+ return vers
200+ Logger.error(
201+ 'Could not determine Ubuntu version from series %s' % ubuntu_series)
202+ raise Exception
203+
204+
205 def lts_series(os_series):
206 '''Return the LTS cloud archive series for a given OpenStack Release'''
207 for u, o in LTS_SERIES.iteritems():
208@@ -29,6 +50,16 @@
209 return u
210
211
212+def openstack_series(os_version):
213+ '''Return OpenStack series name for a version string'''
214+ for vers, codename in OS_VERSION.iteritems():
215+ if os_version.startswith(vers):
216+ return codename
217+ Logger.error(
218+ 'Could not obtain OpenStack series for version: %s' % os_version)
219+ raise Exception
220+
221+
222 def query_ca_ppa(ppa='folsom-staging', owner='ubuntu-cloud-archive',
223 release=SERIES):
224 ''' Query a PPA for source packages and versions '''
225@@ -90,11 +121,58 @@
226
227 def affected_packages(bug):
228 '''Return a list of affected Ubuntu packages for given bug number'''
229- tgts = [task.target.name for task in bug.bug_tasks
230- if task.target.name != 'cloud-archive']
231+ bug_task = namedtuple('bug_task', 'name series status lp_task')
232+ tgts = []
233+ for task in bug.bug_tasks:
234+ tgt = task.target
235+ if (not hasattr(tgt, 'distribution') or
236+ tgt.distribution.name != 'ubuntu'):
237+ continue
238+ if not hasattr(tgt, 'distroseries'):
239+ # tasks affecting dev release have no distroseries
240+ tgts.append(
241+ bug_task(tgt.name, UBUNTU_DEV, task.status, task))
242+ else:
243+ tgts.append(
244+ bug_task(tgt.name, tgt.distroseries.name, task.status, task))
245 return list(set(tgts))
246
247
248+def set_task_status(task, status):
249+ Logger.normal(
250+ 'Setting status %s on %s' % (status, task.bug_target_display_name))
251+ task.status = status
252+ task.lp_save()
253+
254+
255+def create_task(bug, package, series=UBUNTU_DEV, status='Confirmed'):
256+ Logger.normal(
257+ 'Creating %s task affecting %s (%s) on (LP: %s).' %
258+ (status, package, series, bug.id))
259+ lp = get_lp()
260+ archive = lp.distributions['ubuntu']
261+ pkg = archive.getSourcePackage(name=package)
262+
263+ task = None
264+ try:
265+ task = bug.addTask(target=pkg)
266+ except BadRequest as e:
267+ if e.content.startswith('A fix for this bug has already been'):
268+ tsks = affected_packages(bug)
269+ for _package, _series, _status, _task in tsks:
270+ if _package == package and series == series:
271+ task = _task
272+ break
273+ else:
274+ raise e
275+
276+ if not task:
277+ Logger.error('Error adding task to bug')
278+ raise Exception
279+
280+ set_task_status(task, status)
281+
282+
283 def meta_bug_distribution(bug):
284 '''Return a list of Ubuntu releases a meta bug has been released to'''
285 bug_tasks = [bt for bt in bug.bug_tasks
286@@ -116,7 +194,7 @@
287 return sorted(rels).pop()
288
289
290-def post_message(bug, message):
291+def post_message(bug, message, subject=None):
292 '''Posts message to a bug'''
293 bug.newMessage(content=message,
294 subject='Fix Released in the Ubuntu Cloud Archive.')
295@@ -125,17 +203,20 @@
296
297 def set_cloud_archive_task_status(bug, status):
298 '''Sets status on a cloud archive bug task'''
299- bug_task = [bt for bt in bug.bug_tasks
300- if bt.bug_target_name == 'cloud-archive'].pop()
301+ tasks = [bt for bt in bug.bug_tasks
302+ if bt.bug_target_name == 'cloud-archive']
303
304- if not bug_task:
305- logging.error('Bug %s does not affect cloud archive, cant set status.')
306- raise Exception
307+ if tasks:
308+ bug_task = tasks.pop()
309+ else:
310+ lp = get_lp()
311+ ca = lp.projects['cloud-archive']
312+ bug_task = bug.addTask(target=ca)
313
314 bug_task.status = status
315 bug_task.lp_save()
316- logging.info('Status set on cloud-archive task (LP: #%s): %s.' %
317- (bug.id, status))
318+ Logger.normal('Status set on cloud-archive task (LP: #%s): %s.' %
319+ (bug.id, status))
320
321
322 def outdated_packages(os_release):

Subscribers

People subscribed via source and target branches