Merge lp:~doanac/ubuntu-ci-services-itself/imgbuild-kernel-fixes into lp:ubuntu-ci-services-itself

Proposed by Andy Doan
Status: Merged
Approved by: Andy Doan
Approved revision: 404
Merged at revision: 409
Proposed branch: lp:~doanac/ubuntu-ci-services-itself/imgbuild-kernel-fixes
Merge into: lp:ubuntu-ci-services-itself
Diff against target: 144 lines (+40/-13)
3 files modified
image-builder/imagebuilder/cloud_image.py (+32/-11)
image-builder/imagebuilder/tests/test_modify_cloud_image.py (+5/-2)
juju-deployer/configs/unit_config.yaml.tmpl (+3/-0)
To merge this branch: bzr merge lp:~doanac/ubuntu-ci-services-itself/imgbuild-kernel-fixes
Reviewer Review Type Date Requested Status
Paul Larson Approve
PS Jenkins bot (community) continuous-integration Approve
Evan (community) Approve
Review via email: mp+211178@code.launchpad.net

Commit message

image-builder: fixes required to get kernel testing working

Description of the change

This fixes the issues I've discovered in the image-builder. The whole diff is small, but it might make more sense to read each commit on its own to see *why* I made these chages.

To post a comment you must log in.
Revision history for this message
Evan (ev) wrote :

57 + _chrooted(chroot, 'apt-get install -y {}'.format(' '.join(pkglist)))

We have all the apt keys imported and the cache updated, yes? I'm typing this from my iPad, otherwise I'd check myself.

139 +image_size: 4G

Can we have a comment documenting what this does and why it's set to 4G?

Otherwise +1. Good stuff.

Have you checked with Paul on why we had those dpkg's options set in the first place?

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

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

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

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

> Have you checked with Paul on why we had those dpkg's options set in the first
> place?
Yes, those were set to get around grub wanting to give an interactive prompt to decide what to do about the config file. From what Andy and I discussed earlier on IRC, it should be ok to remove them since he has 'etc/default/grub.d/99-ci-eng.cfg' getting created and used, but I'm working on testing it now using this branch.

404. By Andy Doan

document the 4G size in our unit_config

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

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

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

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

I've been testing this over the weekend, and it's working well for me +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'image-builder/imagebuilder/cloud_image.py'
2--- image-builder/imagebuilder/cloud_image.py 2014-03-15 13:37:37 +0000
3+++ image-builder/imagebuilder/cloud_image.py 2014-03-15 23:16:04 +0000
4@@ -19,7 +19,6 @@
5 import os
6 import re
7 import shutil
8-import string
9 import subprocess
10 import textwrap
11 import time
12@@ -80,22 +79,30 @@
13 log.info('Running command in image: {0}'.format(cmd))
14 if type(cmd) is not list:
15 cmd = cmd.split(' ')
16- output = subprocess.check_output(['chroot', chroot] + cmd)
17+ output = subprocess.check_output(
18+ ['chroot', chroot] + cmd, stderr=subprocess.STDOUT)
19 if output:
20 log.info(output)
21
22
23 def _apt_get_update(chroot):
24- # apt-get update isn't always reliable give it 3 tries:
25- for x in (2, 1, 0):
26+ # apt-get update isn't always reliable, give it a few tries
27+ retries = 5
28+ for x in range(retries):
29 try:
30 _chrooted(chroot, "/usr/bin/apt-get update")
31 break
32 except subprocess.CalledProcessError as e:
33- if x == 0:
34+ x += 1
35+ if x == retries:
36 raise e
37 else:
38- log.info('apt-get update failed, retrying %d more times', x)
39+ # retry delays will be 1, 16, 81, 256, 625
40+ # ie about 1s, 16s, 1.5m, 4m, 10m
41+ timeout = x * x * x * x
42+ fmt = 'apt-get update failed, wait %ds and try %d more times'
43+ log.info(fmt, timeout, retries - x)
44+ time.sleep(timeout)
45
46
47 def _setup_ppas(chroot, repos, series, status_cb):
48@@ -124,11 +131,7 @@
49 '''
50 status_cb('Adding requested packages to the image...')
51 os.environ['DEBIAN_FRONTEND'] = 'noninteractive'
52- _chrooted(chroot,
53- ['/bin/bash', '-c',
54- ('/usr/bin/apt-get -o Dpkg::Options::=\"--force-confdef\" '
55- '-o Dpkg::Options::=\"--force-confold\" install -y '
56- '{pkglist}'.format(pkglist=string.join(pkglist, " ")))])
57+ _chrooted(chroot, 'apt-get install -y {}'.format(' '.join(pkglist)))
58 _chrooted(chroot, "/usr/bin/apt-get clean")
59
60 #create a big null data file and remove it to make it more compressable
61@@ -144,6 +147,19 @@
62 os.unlink(zerofile)
63
64
65+def _setup_grub(mountpoint, status_cb):
66+ '''ensure grub uses the proper rootfs
67+
68+ When installing kernels grub will reconfigure but set the wrong root
69+ device to boot from. This ensures its probed correctly
70+ '''
71+ status_cb('ensuring grub uses proper rootfs')
72+ path = os.path.join(mountpoint, 'etc/default/grub.d/99-ci-eng.cfg')
73+ with open(path, 'w') as f:
74+ f.write('LINUX_ROOT_DEVICE="LABEL=cloudimg-rootfs"\n')
75+ f.write('GRUB_DEVICE="LABEL=cloudimg-rootfs"\n')
76+
77+
78 def _download(url, path):
79 urlpath = urlparse.urlsplit(url).path
80 filename = os.path.basename(urlpath)
81@@ -166,6 +182,9 @@
82
83 class CloudImage(object):
84 def __init__(self, image_path, tmpdir):
85+ image_size = ci_utils.unit_config.get('image_size')
86+ log.info('resizing image to be %s', image_size)
87+ subprocess.check_call(['qemu-img', 'resize', image_path, image_size])
88 self.mountpoint = self._mount_image(image_path, tmpdir)
89
90 def __enter__(self):
91@@ -241,6 +260,8 @@
92 with CloudImage(image_path, tmpdir) as mountpoint:
93 status_cb('updating image %s...' % image)
94
95+ _setup_grub(mountpoint, status_cb)
96+
97 _setup_ppas(mountpoint, repos, series, status_cb)
98
99 _run_chroot_cmds(mountpoint, packages, status_cb)
100
101=== modified file 'image-builder/imagebuilder/tests/test_modify_cloud_image.py'
102--- image-builder/imagebuilder/tests/test_modify_cloud_image.py 2014-03-15 03:22:48 +0000
103+++ image-builder/imagebuilder/tests/test_modify_cloud_image.py 2014-03-15 23:16:04 +0000
104@@ -43,14 +43,16 @@
105 expected = ['deb foo_url precise main', 'deb-src foo_url precise main']
106 self.assertListEqual(expected, deblines)
107
108+ @mock.patch('time.sleep')
109 @mock.patch('imagebuilder.cloud_image._chrooted')
110- def test_apt_get_update_fails(self, chrooted):
111+ def test_apt_get_update_fails(self, chrooted, sleep):
112 chrooted.side_effect = subprocess.CalledProcessError(1, 'cmd', 'out')
113 with self.assertRaises(subprocess.CalledProcessError):
114 cloud_image._apt_get_update('/blah')
115
116+ @mock.patch('time.sleep')
117 @mock.patch('imagebuilder.cloud_image._chrooted')
118- def test_apt_get_update_retries(self, chrooted):
119+ def test_apt_get_update_retries(self, chrooted, sleep):
120 '''ensure it can apt-get update works after retrying'''
121 chrooted.side_effect = [
122 subprocess.CalledProcessError(1, 'cmd', 'out'),
123@@ -59,6 +61,7 @@
124 ]
125 cloud_image._apt_get_update('/blah')
126 self.assertEqual(3, chrooted.call_count)
127+ self.assertEqual(2, sleep.call_count)
128
129 @mock.patch('imagebuilder.cloud_image.launchpad')
130 @mock.patch('imagebuilder.cloud_image._chrooted')
131
132=== modified file 'juju-deployer/configs/unit_config.yaml.tmpl'
133--- juju-deployer/configs/unit_config.yaml.tmpl 2014-03-14 23:53:04 +0000
134+++ juju-deployer/configs/unit_config.yaml.tmpl 2014-03-15 23:16:04 +0000
135@@ -21,6 +21,9 @@
136
137 # for ticket system
138 base_image: "http://cloud-images.ubuntu.com/releases/13.10/release-20131015/ubuntu-13.10-server-cloudimg-amd64-disk1.img"
139+# Cloud images are 2G. We need more space for the packages that might
140+# be added with tickets.
141+image_size: 4G
142 series: saucy
143 master_ppa: $CI_MASTER_PPA
144 tr_flavors:

Subscribers

People subscribed via source and target branches