Merge lp:~cjwatson/launchpad-buildd/sbuild-schroot into lp:launchpad-buildd

Proposed by Colin Watson on 2017-07-18
Status: Merged
Merged at revision: 250
Proposed branch: lp:~cjwatson/launchpad-buildd/sbuild-schroot
Merge into: lp:launchpad-buildd
Diff against target: 309 lines (+76/-60)
9 files modified
MANIFEST.in (+0/-1)
bin/sbuild-package (+0/-27)
bin/sudo-wrapper (+0/-4)
debian/changelog (+1/-0)
debian/control (+1/-1)
debian/launchpad-buildd.install (+0/-1)
lpbuildd/binarypackage.py (+30/-3)
lpbuildd/tests/test_binarypackage.py (+26/-6)
sbuildrc (+18/-17)
To merge this branch: bzr merge lp:~cjwatson/launchpad-buildd/sbuild-schroot
Reviewer Review Type Date Requested Status
William Grant code 2017-07-18 Approve on 2017-08-03
Review via email: mp+327634@code.launchpad.net

Commit Message

Configure sbuild to use schroot sessions rather than sudo.

Description of the Change

This is closer to how Debian buildds behave and to how developers typically run sbuild interactively, so should further reduce the number of Launchpad-specific failures; and although we have to spend about the same number of lines of code on setup, I think less of it is about working around peculiar idiosyncrasies. It also has the substantial benefit of the inactivity timeout actually working properly, so a build that leaves processes hanging around will eventually be reaped automatically rather than having to be cancelled manually.

The diff of the "User Environment" reported by sbuild is as follows:

 APT_CONFIG=/var/lib/sbuild/apt.conf
 DEB_BUILD_OPTIONS=noautodbgsym parallel=4
-HOME=/home/buildd
+HOME=/sbuild-nonexistent
 LANG=C.UTF-8
 LC_ALL=C.UTF-8
 LOGNAME=buildd
-MAIL=/var/mail/buildd
-OLDPWD=/
-PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
-PWD=/<<PKGBUILDDIR>>
+PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
+SCHROOT_ALIAS_NAME=build-PACKAGEBUILD-37
+SCHROOT_CHROOT_NAME=build-PACKAGEBUILD-37
+SCHROOT_COMMAND=env
+SCHROOT_GID=2501
+SCHROOT_GROUP=buildd
+SCHROOT_SESSION_ID=build-PACKAGEBUILD-37
+SCHROOT_UID=2001
+SCHROOT_USER=buildd
 SHELL=/bin/sh
-SUDO_COMMAND=/usr/sbin/chroot /<<CHROOT>> su buildd -s /bin/sh -c cd '/<<PKGBUILDDIR>>' && 'env'
-SUDO_GID=2501
-SUDO_UID=2001
-SUDO_USER=buildd
 TERM=unknown
 USER=buildd
-USERNAME=root
+V=1

Of these:

 * The SUDO_* and SCHROOT_* changes are natural.
 * Dropping MAIL, OLDPWD, and PWD seems correct (shells will set PWD later anyway).
 * Dropping /usr/local/games from PATH should be harmless.
 * sudo sets USERNAME, but it's rather non-standard and there's no obvious reason why it bothers, and in any case its value was arguably wrong here.
 * I'd intended to set V=1 way back in launchpad-buildd 125 but it was eaten by the environment filter and I didn't notice.
 * The change in HOME might possibly cause some problems, since it's now a nonexistent directory. However, this matches Debian so it might just as easily cause some progressions, and I think it's more correct this way.

To post a comment you must log in.
Colin Watson (cjwatson) :
William Grant (wgrant) :
review: Approve (code)
229. By Colin Watson on 2017-08-03

Simplify using install(1).

230. By Colin Watson on 2017-08-03

Merge trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'MANIFEST.in'
2--- MANIFEST.in 2017-07-25 22:11:19 +0000
3+++ MANIFEST.in 2017-08-03 13:13:28 +0000
4@@ -12,7 +12,6 @@
5 include bin/scan-for-processes
6 include bin/slave-prep
7 include bin/snap-git-proxy
8-include bin/sudo-wrapper
9 include bin/test_buildd_generatetranslationtemplates
10 include bin/test_buildd_recipe
11 include bin/umount-chroot
12
13=== modified file 'bin/sbuild-package'
14--- bin/sbuild-package 2017-07-25 22:11:19 +0000
15+++ bin/sbuild-package 2017-08-03 13:13:28 +0000
16@@ -19,33 +19,6 @@
17
18 exec 2>&1
19
20-# Keep this in sync with sbuild/lib/Buildd.pm.
21-unset LANG
22-unset LANGUAGE
23-unset LC_CTYPE
24-unset LC_NUMERIC
25-unset LC_TIME
26-unset LC_COLLATE
27-unset LC_MONETARY
28-unset LC_MESSAGES
29-unset LC_PAPER
30-unset LC_NAME
31-unset LC_ADDRESS
32-unset LC_TELEPHONE
33-unset LC_MEASUREMENT
34-unset LC_IDENTIFICATION
35-unset LC_ALL
36-unset DISPLAY
37-unset TERM
38-
39-# Force values for these, since otherwise sudo/pam_env may fill in unwanted
40-# values from /etc/default/locale.
41-export LANG=C.UTF-8 LC_ALL=C.UTF-8 LANGUAGE=
42-
43-# A number of build systems (e.g. automake, Linux) use this as an indication
44-# that they should be more verbose.
45-export V=1
46-
47 # On multi-guest PPA hosts, the per-guest overlay sometimes gets out of
48 # sync, and we notice this by way of a corrupted .sbuildrc. We aren't going
49 # to be able to build anything in this situation, so immediately return
50
51=== removed file 'bin/sudo-wrapper'
52--- bin/sudo-wrapper 2017-07-25 22:11:19 +0000
53+++ bin/sudo-wrapper 1970-01-01 00:00:00 +0000
54@@ -1,4 +0,0 @@
55-#! /bin/sh
56-set -e
57-
58-exec sudo -E "$@"
59
60=== modified file 'debian/changelog'
61--- debian/changelog 2017-08-03 12:14:34 +0000
62+++ debian/changelog 2017-08-03 13:13:28 +0000
63@@ -14,6 +14,7 @@
64 and to have unit tests.
65 * Rewrite override-sources-list in Python, allowing it to have unit tests.
66 * Rewrite add-trusted-keys in Python, allowing it to have unit tests.
67+ * Configure sbuild to use schroot sessions rather than sudo.
68
69 -- Colin Watson <cjwatson@ubuntu.com> Tue, 25 Jul 2017 23:07:58 +0100
70
71
72=== modified file 'debian/control'
73--- debian/control 2017-07-28 14:08:52 +0000
74+++ debian/control 2017-08-03 13:13:28 +0000
75@@ -10,7 +10,7 @@
76 Architecture: all
77 Depends: python-lpbuildd (=${source:Version}), python, debootstrap, dpkg-dev,
78 file, bzip2, sudo, ntpdate, adduser, apt-transport-https, lsb-release,
79- pristine-tar, python-apt, sbuild, ${misc:Depends}
80+ pristine-tar, python-apt, sbuild, schroot, ${misc:Depends}
81 Description: Launchpad buildd slave
82 This is the launchpad buildd slave package. It contains everything needed to
83 get a launchpad buildd going apart from the database manipulation required to
84
85=== modified file 'debian/launchpad-buildd.install'
86--- debian/launchpad-buildd.install 2017-07-25 22:11:19 +0000
87+++ debian/launchpad-buildd.install 2017-08-03 13:13:28 +0000
88@@ -15,7 +15,6 @@
89 bin/scan-for-processes usr/share/launchpad-buildd/slavebin
90 bin/slave-prep usr/share/launchpad-buildd/slavebin
91 bin/snap-git-proxy usr/share/launchpad-buildd/slavebin
92-bin/sudo-wrapper usr/share/launchpad-buildd/slavebin
93 bin/umount-chroot usr/share/launchpad-buildd/slavebin
94 bin/unpack-chroot usr/share/launchpad-buildd/slavebin
95 bin/update-debian-chroot usr/share/launchpad-buildd/slavebin
96
97=== modified file 'lpbuildd/binarypackage.py'
98--- lpbuildd/binarypackage.py 2017-07-28 13:25:55 +0000
99+++ lpbuildd/binarypackage.py 2017-08-03 13:13:28 +0000
100@@ -1,12 +1,14 @@
101 # Copyright 2009-2016 Canonical Ltd. This software is licensed under the
102 # GNU Affero General Public License version 3 (see the file LICENSE).
103
104-from __future__ import absolute_import
105+from __future__ import absolute_import, print_function
106
107 from collections import defaultdict
108 import os
109 import re
110 import subprocess
111+import tempfile
112+from textwrap import dedent
113 import traceback
114
115 import apt_pkg
116@@ -99,6 +101,10 @@
117 return os.path.join(
118 self.home, "build-" + self._buildid, 'chroot-autobuild')
119
120+ @property
121+ def schroot_config_path(self):
122+ return os.path.join('/etc/schroot/chroot.d', 'build-' + self._buildid)
123+
124 def initiate(self, files, chroot, extra_args):
125 """Initiate a build with a given set of files and chroot."""
126
127@@ -121,6 +127,25 @@
128
129 def doRunBuild(self):
130 """Run the sbuild process to build the package."""
131+ with tempfile.NamedTemporaryFile(mode="w") as schroot_file:
132+ # Use the "plain" chroot type because we do the necessary setup
133+ # and teardown ourselves: it's easier to do this the same way
134+ # for all build types.
135+ print(dedent('''\
136+ [build-{buildid}]
137+ description=build-{buildid}
138+ groups=sbuild,root
139+ root-groups=sbuild,root
140+ type=plain
141+ directory={chroot_path}
142+ ''').format(
143+ buildid=self._buildid, chroot_path=self.chroot_path),
144+ file=schroot_file, end='')
145+ schroot_file.flush()
146+ subprocess.check_call(
147+ ['sudo', 'install', '-o', 'root', '-g', 'root', '-m', '0644',
148+ schroot_file.name, self.schroot_config_path])
149+
150 currently_building_path = os.path.join(
151 self.chroot_path, 'CurrentlyBuilding')
152 currently_building_contents = (
153@@ -137,10 +162,9 @@
154
155 args = ["sbuild-package", self._buildid, self.arch_tag]
156 args.append(self.suite)
157- args.extend(["-c", "chroot:autobuild"])
158+ args.extend(["-c", "chroot:build-%s" % self._buildid])
159 args.append("--arch=" + self.arch_tag)
160 args.append("--dist=" + self.suite)
161- args.append("--purge=never")
162 args.append("--nolog")
163 if self.arch_indep:
164 args.append("-A")
165@@ -399,5 +423,8 @@
166
167 def iterateReap_SBUILD(self, success):
168 """Finished reaping after sbuild run."""
169+ # Ignore errors from tearing down schroot configuration.
170+ subprocess.call(['sudo', 'rm', '-f', self.schroot_config_path])
171+
172 self._state = DebianBuildState.UMOUNT
173 self.doUnmounting()
174
175=== modified file 'lpbuildd/tests/test_binarypackage.py'
176--- lpbuildd/tests/test_binarypackage.py 2017-07-28 13:57:47 +0000
177+++ lpbuildd/tests/test_binarypackage.py 2017-08-03 13:13:28 +0000
178@@ -3,12 +3,15 @@
179
180 __metaclass__ = type
181
182+from functools import partial
183 import os
184 import shutil
185+import subprocess
186 import tempfile
187 from textwrap import dedent
188
189 from debian.deb822 import PkgRelation
190+from fixtures import MonkeyPatch
191 from testtools import TestCase
192 from testtools.matchers import (
193 Contains,
194@@ -59,6 +62,19 @@
195 return 0
196
197
198+class DisableSudo(MonkeyPatch):
199+
200+ def __init__(self):
201+ super(DisableSudo, self).__init__(
202+ 'subprocess.call', partial(self.call_patch, subprocess.call))
203+
204+ def call_patch(self, old_call, cmd, *args, **kwargs):
205+ if cmd[0] == 'sudo':
206+ return 0
207+ else:
208+ return old_call(cmd, *args, **kwargs)
209+
210+
211 def write_file(path, content):
212 if not os.path.isdir(os.path.dirname(path)):
213 os.makedirs(os.path.dirname(path))
214@@ -70,6 +86,7 @@
215 """Run BinaryPackageBuildManager through its iteration steps."""
216 def setUp(self):
217 super(TestBinaryPackageBuildManagerIteration, self).setUp()
218+ self.useFixture(DisableSudo())
219 self.working_dir = tempfile.mkdtemp()
220 self.addCleanup(lambda: shutil.rmtree(self.working_dir))
221 slave_dir = os.path.join(self.working_dir, 'slave')
222@@ -110,8 +127,9 @@
223 BinaryPackageBuildState.SBUILD,
224 [
225 'sharepath/slavebin/sbuild-package', 'sbuild-package',
226- self.buildid, 'i386', 'warty', '-c', 'chroot:autobuild',
227- '--arch=i386', '--dist=warty', '--purge=never', '--nolog',
228+ self.buildid, 'i386', 'warty',
229+ '-c', 'chroot:build-' + self.buildid,
230+ '--arch=i386', '--dist=warty', '--nolog',
231 'foo_1.dsc',
232 ], final=True)
233 self.assertFalse(self.slave.wasCalled('chrootFail'))
234@@ -179,8 +197,9 @@
235 self.assertState(
236 BinaryPackageBuildState.SBUILD,
237 ['sharepath/slavebin/sbuild-package', 'sbuild-package',
238- self.buildid, 'i386', 'warty', '-c', 'chroot:autobuild',
239- '--arch=i386', '--dist=warty', '--purge=never', '--nolog',
240+ self.buildid, 'i386', 'warty',
241+ '-c', 'chroot:build-' + self.buildid,
242+ '--arch=i386', '--dist=warty', '--nolog',
243 'foo_1.dsc'],
244 env_matcher=Not(Contains('DEB_BUILD_OPTIONS')), final=True)
245 self.assertFalse(self.slave.wasCalled('chrootFail'))
246@@ -207,8 +226,9 @@
247 self.assertState(
248 BinaryPackageBuildState.SBUILD,
249 ['sharepath/slavebin/sbuild-package', 'sbuild-package',
250- self.buildid, 'i386', 'warty', '-c', 'chroot:autobuild',
251- '--arch=i386', '--dist=warty', '--purge=never', '--nolog',
252+ self.buildid, 'i386', 'warty',
253+ '-c', 'chroot:build-' + self.buildid,
254+ '--arch=i386', '--dist=warty', '--nolog',
255 'foo_1.dsc'],
256 env_matcher=ContainsDict(
257 {'DEB_BUILD_OPTIONS': Equals('noautodbgsym')}),
258
259=== modified file 'sbuildrc'
260--- sbuildrc 2017-04-26 12:24:32 +0000
261+++ sbuildrc 2017-08-03 13:13:28 +0000
262@@ -16,29 +16,30 @@
263
264 $resolve_alternatives = 1;
265
266-# Also let LANG through to subprocesses, or sudo will set it to
267-# /etc/default/locale on the host, which probably doesn't exist in the
268-# chroot. sbuild-package invokes sbuild with LANG=C, which is what we
269-# want.
270+$build_environment = {
271+ # sbuild sets LC_ALL=C.UTF-8 by default, so setting LANG as well should
272+ # be redundant, but do so anyway for compatibility.
273+ 'LANG' => 'C.UTF-8',
274+ # It's not clear how much sense this makes, but sudo set this as a
275+ # fallback default, so keep it for compatibility.
276+ 'TERM' => 'unknown',
277+ # A number of build systems (e.g. automake, Linux) use this as an
278+ # indication that they should be more verbose.
279+ 'V' => '1',
280+};
281+
282+# We want to expose almost nothing from the buildd environment.
283+# DEB_BUILD_OPTIONS is set by sbuild-package.
284 $environment_filter = [
285- '^PATH$',
286- '^DEB(IAN|SIGN)?_[A-Z_]+$',
287- '^(C(PP|XX)?|LD|F)FLAGS(_APPEND)?$',
288- '^USER(NAME)?$',
289- '^LOGNAME$',
290- '^HOME$',
291- '^TERM$',
292- '^SHELL$',
293- '^LANG$'];
294+ '^DEB_BUILD_OPTIONS$',
295+ ];
296
297-# We need to use "sudo -E" so that the above environment variables are
298-# allowed through.
299-$sudo = "/usr/share/launchpad-buildd/slavebin/sudo-wrapper";
300+# We're just going to throw the chroot away anyway.
301+$purge_build_deps = 'never';
302
303 # After that time (in minutes) of inactivity a build is terminated.
304 # Activity
305 # is measured by output to the log file.
306 $stalled_pkg_timeout = 150;
307
308-$chroot_mode="sudo";
309 $sbuild_mode="buildd";

Subscribers

People subscribed via source and target branches

to all changes: