Merge lp:~vila/uci-engine/tr-new-api into lp:uci-engine

Proposed by Vincent Ladeuil
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: 707
Merged at revision: 705
Proposed branch: lp:~vila/uci-engine/tr-new-api
Merge into: lp:uci-engine
Prerequisite: lp:~vila/uci-engine/new-tr-api-lander
Diff against target: 190 lines (+99/-2)
4 files modified
test_runner/tstrun/run_worker.py (+2/-0)
test_runner/tstrun/testbed.py (+42/-1)
test_runner/tstrun/tests/test_testbed.py (+42/-0)
test_runner/tstrun/tests/test_worker.py (+13/-1)
To merge this branch: bzr merge lp:~vila/uci-engine/tr-new-api
Reviewer Review Type Date Requested Status
Paul Larson Approve
Martin Pitt (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+227542@code.launchpad.net

Commit message

Handle the ppa list parameter in the test runner request API.

Description of the change

Implement the new test runner API: handle the ppa list.

This keeps migrating the test runner API without breaking backwards compatibility:

- https://code.launchpad.net/~vila/uci-engine/new-tr-api-lander/+merge/227510 was allowing the lander to be upgraded without upgrading the test runner,
- this one allows the test runnner to be upgraded without the image builder being upgraded.

I had some doubts for the later about using add-apt-repository twice but I had to do that anyway in this proposal to address a nasty bug: by default, add-apt-repository comments out the deb-src line. The fallout was that the binary packages were properly installed from the ppa but not the source package.

It's hard to notice but I was lucky enough to check just the source version being installed across precise/saucy/trusty from 'run-tests test_runner.tstrun.tests.test_worker.TestWorkerHandleRequest.test_handle_request_'

This also allowed me to remove one call to 'apt-get upgrade' which will make pitti happier (there is an ongoing discussion about minimizing the apt-get update/upgrade calls for the testbeds as this is a costly operation).

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:702
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1127/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1127/rebuild

review: Approve (continuous-integration)
Revision history for this message
Vincent Ladeuil (vila) wrote :

Note to self: apt-get upgrade was handled more robustly by the image builder and the test runner should copy that from https://code.launchpad.net/~pwlars/uci-engine/unmodified-imagebuild/+merge/227557

Revision history for this message
Paul Larson (pwlars) wrote :

This looks ok to me, but of course I'd still like us to do some more testing with it tomorrow. Note: I have a new branch for the image builder that uses a versioned API. If we break compatibility here in the test runner also, would you like to do something similar so that we already establish a way of upgrading to new API versions in the test runner code also?

review: Needs Information
Revision history for this message
Martin Pitt (pitti) wrote :

I have some inline comments. Setting "needs fixing" as we really need a fallback for apt-get update, otherwise you'll get unhappy really soon :/

review: Needs Fixing
Revision history for this message
Vincent Ladeuil (vila) wrote :

Agreed, see inline replies.

Revision history for this message
Vincent Ladeuil (vila) wrote :

> This looks ok to me, but of course I'd still like us to do some more testing
> with it tomorrow. Note: I have a new branch for the image builder that uses a
> versioned API. If we break compatibility here in the test runner also, would
> you like to do something similar so that we already establish a way of
> upgrading to new API versions in the test runner code also?

I don't have a clear picture on the upgrade story, I'd be more inclined, as a first step, to describe what we're doing here for the test runner and the image builder, and how we upgrade a deployment *before* going down the versioned API route.

But yeah, I should probably split out the lander part, the test runner itself only accept an additional parameter that I can make optional without having to version the API I think.

Let's talk ! ;)

Revision history for this message
Vincent Ladeuil (vila) wrote :

@Martin: apt-get update and PPAs apt lines double handling are now fixed.

lp:~vila/uci-engine/tr-new-api updated
703. By Vincent Ladeuil

Make apt-get safer by retrying on failure.

704. By Vincent Ladeuil

Define a config variable for the apt-get update timeouts and avoid spawing a nova instance for the related tests (safe_apt_get_update() called on the instance is covered by other tests).

705. By Vincent Ladeuil

Fix pep8 issues.

706. By Vincent Ladeuil

Clarify how we enable the PPAs and do it once instead of catching up with cloud-init.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:706
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1148/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1148/rebuild

review: Approve (continuous-integration)
Revision history for this message
Paul Larson (pwlars) wrote :

I tried this along with my imagebuild merged together, and was able to get a ticket through. It resulted in a failed test, which was actually intentional on my part because I wanted to be really sure it was getting the new package.

lp:~vila/uci-engine/tr-new-api updated
707. By Vincent Ladeuil

--enable-source was added to add-apt-repository after precise.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:707
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1154/
Executed test runs:

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/uci-engine-ci/1154/rebuild

review: Approve (continuous-integration)
Revision history for this message
Martin Pitt (pitti) wrote :

Heh, that's a rather thorough way to apt-get update, but why not :-) LGTM now, thanks!

review: Approve
Revision history for this message
Paul Larson (pwlars) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'test_runner/tstrun/run_worker.py'
2--- test_runner/tstrun/run_worker.py 2014-07-15 09:47:45 +0000
3+++ test_runner/tstrun/run_worker.py 2014-07-23 10:47:55 +0000
4@@ -126,6 +126,7 @@
5 progress_queue = params['progress_trigger']
6 series = params['series']
7 image_id = params['image_id']
8+ ppa_list = params['ppa_list']
9 package_list = params['package_list']
10
11 results = {}
12@@ -142,6 +143,7 @@
13 conf = testbed.vms_config_from_auth_config(tb_name, auth_conf)
14 conf.set('vm.image', image_id)
15 conf.set('vm.release', series)
16+ conf.set('vm.ppas', ','.join(ppa_list))
17 base_dir = conf.get('vm.vms_dir')
18 if not os.path.exists(base_dir):
19 os.makedirs(base_dir)
20
21=== modified file 'test_runner/tstrun/testbed.py'
22--- test_runner/tstrun/testbed.py 2014-07-11 14:44:33 +0000
23+++ test_runner/tstrun/testbed.py 2014-07-23 10:47:55 +0000
24@@ -84,6 +84,21 @@
25 help_string='''The base image to run the tests.'''))
26 register(config.PathOption('vm.ssh_key_path', default='~/.ssh/id_rsa',
27 help_string='''The ssh key for the testbed.'''))
28+register(options.ListOption('vm.apt_get.update.timeouts',
29+ default='15.0, 90.0, 240.0',
30+ help_string='''apt-get update timeouts in seconds.
31+
32+When apt-get update fails on hash sum mismatches, retry after the specified
33+timeouts. More values mean more retries.
34+'''))
35+register(options.ListOption('vm.ppas',
36+ default=None,
37+ help_string='''PPAs to be added to the testbed.
38+
39+This works around cloud-init not activating the deb-src line and not providing
40+a way to do so. This is intended to be fixed in uci-vms so vm.apt_sources can
41+be used again.
42+'''))
43
44
45 logging.basicConfig(level=logging.INFO)
46@@ -127,7 +142,6 @@
47 self.floating_ip = None
48 self.nova = self.build_nova_client()
49 self.test_bed_key_path = None
50- self.conf.set('vm.update', 'True')
51 self.conf.set('vm.ssh_authorized_keys',
52 self.conf.get('vm.ssh_key_path') + '.pub')
53 # No need to reboot a nova instance
54@@ -192,6 +206,33 @@
55 self.instance.add_floating_ip(self.floating_ip)
56 self.wait_for_ip()
57 self.wait_for_cloud_init()
58+ ppas = self.conf.get('vm.ppas')
59+ if ppas:
60+ cmd = ['sudo', 'add-apt-repository']
61+ if self.conf.get('vm.release') > 'precise':
62+ cmd.append('--enable-source')
63+ for ppa in ppas:
64+ self.ssh(*(cmd + [ppa]))
65+ # Now we can apt-get update (doing it earlier would lead to the wrong
66+ # source package to be installed).
67+ self.safe_apt_get_update()
68+
69+ def apt_get_update(self):
70+ return self.ssh('sudo', 'apt-get', 'update')
71+
72+ def safe_apt_get_update(self):
73+ for timeout in self.conf.get('vm.apt_get.update.timeouts'):
74+ proc, out, err = self.apt_get_update()
75+ if proc.returncode == 0:
76+ # We're done
77+ return
78+ else:
79+ msg = ('apt-get update failed, wait {}s'
80+ 'stdout:\n{}\n'
81+ 'stderr:\n{}\n')
82+ log.info(msg.format(timeout, out, err))
83+ time.sleep(float(timeout))
84+ raise TestBedException('apt-get update never succeeded')
85
86 def update_instance(self):
87 # MISSINGTEST: What if the instance disappear ? (could be approximated
88
89=== modified file 'test_runner/tstrun/tests/test_testbed.py'
90--- test_runner/tstrun/tests/test_testbed.py 2014-07-12 13:30:40 +0000
91+++ test_runner/tstrun/tests/test_testbed.py 2014-07-23 10:47:55 +0000
92@@ -123,3 +123,45 @@
93 out=subprocess.PIPE, err=subprocess.PIPE)
94 self.assertEqual(0, proc.returncode)
95 self.assertEqual('ubuntu\n', out)
96+
97+ def test_apt_get_update_retries(self):
98+ tb = testbed.TestBed(self.conf)
99+ self.conf.set('vm.image', self.get_image_id())
100+ self.conf.set('vm.apt_get.update.timeouts', '0.1, 0.1')
101+ self.nb_calls = 0
102+
103+ class Proc(object):
104+ returncode = 0
105+
106+ def failing_update():
107+ self.nb_calls += 1
108+ if self.nb_calls > 1:
109+ return Proc(), 'stdout success', 'stderr success'
110+ else:
111+ # Fake a failed apt-get update
112+ proc = Proc()
113+ proc.returncode = 1
114+ return proc, 'stdout error', 'stderr error'
115+
116+ tb.apt_get_update = failing_update
117+ tb.safe_apt_get_update()
118+ self.assertEqual(2, self.nb_calls)
119+
120+ def test_apt_get_update_fails(self):
121+ tb = testbed.TestBed(self.conf)
122+ self.conf.set('vm.image', self.get_image_id())
123+ self.conf.set('vm.apt_get.update.timeouts', '0.1, 0.1, 0.1')
124+
125+ def failing_update():
126+ class Proc(object):
127+ pass
128+
129+ proc = Proc()
130+ proc.returncode = 1
131+ return proc, 'stdout', 'stderr'
132+
133+ tb.apt_get_update = failing_update
134+ with self.assertRaises(testbed.TestBedException) as cm:
135+ tb.safe_apt_get_update()
136+ self.assertEqual('apt-get update never succeeded',
137+ unicode(cm.exception))
138
139=== modified file 'test_runner/tstrun/tests/test_worker.py'
140--- test_runner/tstrun/tests/test_worker.py 2014-07-15 09:47:45 +0000
141+++ test_runner/tstrun/tests/test_worker.py 2014-07-23 10:47:55 +0000
142@@ -22,7 +22,10 @@
143 assertions,
144 )
145 from ucivms.tests import fixtures as vms_fixtures
146-from ci_utils import amqp_utils
147+from ci_utils import (
148+ amqp_utils,
149+ unit_config,
150+)
151 from ci_utils.testing import (
152 features,
153 fixtures,
154@@ -57,6 +60,12 @@
155
156 self.ds_factory = create_data_store
157
158+ def get_ppa_list(self):
159+ # We're testing only the test runner so there is no ppa assigned to the
160+ # ticket, only the master ppa is relevant.
161+ conf = unit_config.get_auth_config()
162+ return [conf.get('master_ppa')]
163+
164 def assertTestRun(self, params):
165 worker = run_worker.TestRunnerWorker(self.ds_factory)
166 self.queue.publish(params)
167@@ -76,6 +85,7 @@
168 series='precise',
169 image_id=('Ubuntu 12.04.4 LTS (amd64 20140613)'
170 ' - CI Engineering'),
171+ ppa_list=self.get_ppa_list(),
172 package_list=['libpng'])
173 returns = self.assertTestRun(params)
174 (retcode, results) = returns[0]
175@@ -94,6 +104,7 @@
176 series='saucy',
177 image_id=('Ubuntu Server 13.10 (amd64 20140409.1)'
178 ' - Partner Image'),
179+ ppa_list=self.get_ppa_list(),
180 package_list=['libpng'])
181 returns = self.assertTestRun(params)
182 (retcode, results) = returns[0]
183@@ -111,6 +122,7 @@
184 series='trusty',
185 image_id=('Ubuntu Server 14.04 LTS (amd64 20140607.1)'
186 ' - Partner Image'),
187+ ppa_list=self.get_ppa_list(),
188 package_list=['libpng'])
189 returns = self.assertTestRun(params)
190 (retcode, results) = returns[0]

Subscribers

People subscribed via source and target branches