Merge lp:~tobijk/launchpad-buildd/launchpad-buildd-bionic into lp:launchpad-buildd

Proposed by Tobias Koch
Status: Merged
Merged at revision: 353
Proposed branch: lp:~tobijk/launchpad-buildd/launchpad-buildd-bionic
Merge into: lp:launchpad-buildd
Diff against target: 304 lines (+116/-37)
3 files modified
debian/changelog (+4/-0)
lpbuildd/target/lxd.py (+37/-7)
lpbuildd/target/tests/test_lxd.py (+75/-30)
To merge this branch: bzr merge lp:~tobijk/launchpad-buildd/launchpad-buildd-bionic
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Tobias Koch (community) Needs Resubmitting
Launchpad code reviewers Pending
Review via email: mp+354331@code.launchpad.net

Commit message

Update LXD backend to work with newer LXD versions.

Description of the change

This patch makes the buildd's LXD backend work on Bionic:

* Based on LXD version modify raw.lxc settings (some parameter names have changed)
* Fix a problem with header checks where uid and gid are set to 0, but need to be strings
* Explicitly specify a root device, which seems to be mandatory now

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote :

Thanks for working on this!

As well as the inline comments I've left, I'm pretty sure that this is going to need changes to the test suite.

review: Needs Fixing
Revision history for this message
Tobias Koch (tobijk) wrote :

Thanks a lot for the initial review! When you find the time, maybe you can skim over this and see if it is better now. I'll see what I can do about the tests.

Revision history for this message
Tobias Koch (tobijk) wrote :

@cjwatson, please review.

Revision history for this message
Colin Watson (cjwatson) :
review: Needs Fixing
348. By Colin Watson

[r=cjwatson] buildlivefs: support passing an IMAGE_TARGETS variable into the environment

This is needed for projects, such as ubuntu-cpc, that produce multiple
images as part of a single build, in order to be selective about which image
sets to produce.

349. By Colin Watson

[r=wgrant] Set SNAPCRAFT_BUILD_ENVIRONMENT=host when building snaps (LP: #1791201).

350. By Colin Watson

[r=wgrant] Call gatherResults in a different thread so that it doesn't block responses to XML-RPC requests.

351. By Colin Watson

releasing package launchpad-buildd version 165

Revision history for this message
Tobias Koch (tobijk) wrote :

@cjwatson, ready for re-review.

review: Needs Resubmitting
Revision history for this message
Tobias Koch (tobijk) wrote :

Is there a reason why only tests in lpbuildd/tests are run during package build?

352. By Colin Watson

Run all tests at package build time, not just those in lpbuildd.tests.

Revision history for this message
Colin Watson (cjwatson) wrote :

(The "Resubmit" vote is something that your reviewer might use to indicate that the MP needs to be entirely withdrawn and resubmitted, perhaps against a different branch. It isn't something you do when you've made revisions in response to a review.)

Regarding tests at package build time, oops; I've fixed that in trunk. Thanks for pointing it out.

353. By Tobias Koch

Update LXD backend to work with LXD 3.

Revision history for this message
Tobias Koch (tobijk) wrote :

@cjwatson, thanks for the clarification on the "resubmit". I'm not sure how you want the re-factoring on `raw_lxc_config` to look like, so maybe it's better if you just mold it to your liking. Thanks.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2018-10-25 09:04:12 +0000
3+++ debian/changelog 2018-10-25 09:55:10 +0000
4@@ -1,7 +1,11 @@
5 launchpad-buildd (166) UNRELEASED; urgency=medium
6
7+ [Colin Watson]
8 * Run all tests at package build time, not just those in lpbuildd.tests.
9
10+ [Tobias Koch]
11+ * Update LXD backend to work with LXD 3.
12+
13 -- Colin Watson <cjwatson@ubuntu.com> Thu, 25 Oct 2018 10:03:14 +0100
14
15 launchpad-buildd (165) xenial; urgency=medium
16
17=== modified file 'lpbuildd/target/lxd.py'
18--- lpbuildd/target/lxd.py 2018-06-12 23:23:13 +0000
19+++ lpbuildd/target/lxd.py 2018-10-25 09:55:10 +0000
20@@ -277,16 +277,30 @@
21 old_profile.delete()
22
23 raw_lxc_config = [
24- ("lxc.aa_profile", "unconfined"),
25 ("lxc.cap.drop", ""),
26 ("lxc.cap.drop", "sys_time sys_module"),
27 ("lxc.cgroup.devices.deny", ""),
28 ("lxc.cgroup.devices.allow", ""),
29 ("lxc.mount.auto", ""),
30 ("lxc.mount.auto", "proc:rw sys:rw"),
31- ("lxc.network.0.ipv4", ipv4_address),
32- ("lxc.network.0.ipv4.gateway", self.ipv4_network.ip),
33 ]
34+
35+ lxc_version = self._client.host_info["environment"]["driver_version"]
36+ major, minor = [int(v) for v in lxc_version.split(".")[0:2]]
37+
38+ if major >= 3:
39+ raw_lxc_config.extend([
40+ ("lxc.apparmor.profile", "unconfined"),
41+ ("lxc.net.0.ipv4.address", ipv4_address),
42+ ("lxc.net.0.ipv4.gateway", self.ipv4_network.ip),
43+ ])
44+ else:
45+ raw_lxc_config.extend([
46+ ("lxc.aa_profile", "unconfined"),
47+ ("lxc.network.0.ipv4", ipv4_address),
48+ ("lxc.network.0.ipv4.gateway", self.ipv4_network.ip),
49+ ])
50+
51 # Linux 4.4 on powerpc doesn't support all the seccomp bits that LXD
52 # needs.
53 if self.arch == "powerpc":
54@@ -296,7 +310,7 @@
55 "security.nesting": "true",
56 "raw.lxc": "".join(
57 "{key}={value}\n".format(key=key, value=value)
58- for key, value in raw_lxc_config),
59+ for key, value in sorted(raw_lxc_config)),
60 }
61 devices = {
62 "eth0": {
63@@ -306,6 +320,12 @@
64 "type": "nic",
65 },
66 }
67+ if major >= 3:
68+ devices["root"] = {
69+ "path": "/",
70+ "pool": "default",
71+ "type": "disk",
72+ }
73 self.client.profiles.create(self.profile_name, config, devices)
74
75 def start(self):
76@@ -341,7 +361,17 @@
77 hostname_file.flush()
78 os.fchmod(hostname_file.fileno(), 0o644)
79 self.copy_in(hostname_file.name, "/etc/hostname")
80- self.copy_in("/etc/resolv.conf", "/etc/resolv.conf")
81+
82+ resolv_conf = "/etc/resolv.conf"
83+
84+ if os.path.islink(resolv_conf):
85+ resolv_conf = os.path.realpath(resolv_conf)
86+ if (resolv_conf == "/run/systemd/resolve/stub-resolv.conf" and
87+ os.path.isfile("/run/systemd/resolve/resolv.conf")):
88+ resolv_conf = "/run/systemd/resolve/resolv.conf"
89+
90+ self.copy_in(resolv_conf, "/etc/resolv.conf")
91+
92 with tempfile.NamedTemporaryFile(mode="w+") as policy_rc_d_file:
93 policy_rc_d_file.write(policy_rc_d)
94 policy_rc_d_file.flush()
95@@ -481,8 +511,8 @@
96 data = source_file.read()
97 mode = stat.S_IMODE(os.fstat(source_file.fileno()).st_mode)
98 headers = {
99- "X-LXD-uid": 0,
100- "X-LXD-gid": 0,
101+ "X-LXD-uid": "0",
102+ "X-LXD-gid": "0",
103 "X-LXD-mode": "%#o" % mode,
104 }
105 try:
106
107=== modified file 'lpbuildd/target/tests/test_lxd.py'
108--- lpbuildd/target/tests/test_lxd.py 2018-05-08 09:37:16 +0000
109+++ lpbuildd/target/tests/test_lxd.py 2018-10-25 09:55:10 +0000
110@@ -155,23 +155,45 @@
111 image.add_alias.assert_called_once_with(
112 "lp-xenial-amd64", "lp-xenial-amd64")
113
114- def assert_correct_profile(self, extra_raw_lxc_config=""):
115+ def assert_correct_profile(self, extra_raw_lxc_config=None,
116+ driver_version="2.0"):
117+ if extra_raw_lxc_config is None:
118+ extra_raw_lxc_config = []
119+
120 client = pylxd.Client()
121 client.profiles.get.assert_called_once_with("lpbuildd")
122+
123+ raw_lxc_config = [
124+ ("lxc.cap.drop", ""),
125+ ("lxc.cap.drop", "sys_time sys_module"),
126+ ("lxc.cgroup.devices.deny", ""),
127+ ("lxc.cgroup.devices.allow", ""),
128+ ("lxc.mount.auto", ""),
129+ ("lxc.mount.auto", "proc:rw sys:rw"),
130+ ]
131+
132+ major, minor = [int(v) for v in driver_version.split(".")[0:2]]
133+
134+ if major >= 3:
135+ raw_lxc_config.extend([
136+ ("lxc.apparmor.profile", "unconfined"),
137+ ("lxc.net.0.ipv4.address", "10.10.10.2/24"),
138+ ("lxc.net.0.ipv4.gateway", "10.10.10.1"),
139+ ])
140+ else:
141+ raw_lxc_config.extend([
142+ ("lxc.aa_profile", "unconfined"),
143+ ("lxc.network.0.ipv4", "10.10.10.2/24"),
144+ ("lxc.network.0.ipv4.gateway", "10.10.10.1"),
145+ ])
146+
147+ raw_lxc_config = "".join("{key}={val}\n".format(key=key, val=val)
148+ for key, val in sorted(raw_lxc_config + extra_raw_lxc_config))
149+
150 expected_config = {
151 "security.privileged": "true",
152 "security.nesting": "true",
153- "raw.lxc": dedent("""\
154- lxc.aa_profile=unconfined
155- lxc.cap.drop=
156- lxc.cap.drop=sys_time sys_module
157- lxc.cgroup.devices.deny=
158- lxc.cgroup.devices.allow=
159- lxc.mount.auto=
160- lxc.mount.auto=proc:rw sys:rw
161- lxc.network.0.ipv4=10.10.10.2/24
162- lxc.network.0.ipv4.gateway=10.10.10.1
163- """) + extra_raw_lxc_config,
164+ "raw.lxc": raw_lxc_config,
165 }
166 expected_devices = {
167 "eth0": {
168@@ -181,22 +203,42 @@
169 "type": "nic",
170 },
171 }
172+ if driver_version == "3.0":
173+ expected_devices["root"] = {
174+ "path": "/",
175+ "pool": "default",
176+ "type": "disk",
177+ }
178 client.profiles.create.assert_called_once_with(
179 "lpbuildd", expected_config, expected_devices)
180
181 def test_create_profile_amd64(self):
182- self.useFixture(MockPatch("pylxd.Client"))
183- client = pylxd.Client()
184- client.profiles.get.side_effect = FakeLXDAPIException
185- LXD("1", "xenial", "amd64").create_profile()
186- self.assert_correct_profile()
187+ with MockPatch("pylxd.Client"):
188+ for driver_version in ["2.0", "3.0"]:
189+ client = pylxd.Client()
190+ client.reset_mock()
191+ client.profiles.get.side_effect = FakeLXDAPIException
192+ client.host_info = {
193+ "environment": {"driver_version": driver_version}
194+ }
195+ LXD("1", "xenial", "amd64").create_profile()
196+ self.assert_correct_profile(
197+ driver_version=driver_version or "3.0")
198
199 def test_create_profile_powerpc(self):
200- self.useFixture(MockPatch("pylxd.Client"))
201- client = pylxd.Client()
202- client.profiles.get.side_effect = FakeLXDAPIException
203- LXD("1", "xenial", "powerpc").create_profile()
204- self.assert_correct_profile("lxc.seccomp=\n")
205+ with MockPatch("pylxd.Client"):
206+ for driver_version in ["2.0", "3.0"]:
207+ client = pylxd.Client()
208+ client.reset_mock()
209+ client.profiles.get.side_effect = FakeLXDAPIException
210+ client.host_info = {
211+ "environment": {"driver_version": driver_version}
212+ }
213+ LXD("1", "xenial", "powerpc").create_profile()
214+ self.assert_correct_profile(
215+ extra_raw_lxc_config=[("lxc.seccomp", ""),],
216+ driver_version=driver_version or "3.0"
217+ )
218
219 def test_start(self):
220 fs_fixture = self.useFixture(FakeFilesystem())
221@@ -213,6 +255,7 @@
222 client.profiles.get.side_effect = FakeLXDAPIException
223 container = client.containers.create.return_value
224 client.containers.get.return_value = container
225+ client.host_info = {"environment": {"driver_version": "2.0"}}
226 container.start.side_effect = (
227 lambda wait=False: setattr(container, "status_code", LXD_RUNNING))
228 files_api = container.api.files
229@@ -298,19 +341,19 @@
230 data=(
231 b"127.0.0.1\tlocalhost\n\n"
232 b"127.0.1.1\texample.buildd example\n"),
233- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
234+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
235 files_api.post.assert_any_call(
236 params={"path": "/etc/hostname"},
237 data=b"example\n",
238- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
239+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
240 files_api.post.assert_any_call(
241 params={"path": "/etc/resolv.conf"},
242 data=b"host resolv.conf\n",
243- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
244+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
245 files_api.post.assert_any_call(
246 params={"path": "/usr/local/sbin/policy-rc.d"},
247 data=policy_rc_d.encode("UTF-8"),
248- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0755"})
249+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0755"})
250 files_api.session.get.assert_any_call(
251 "/1.0/containers/lp-xenial-amd64/files",
252 params={"path": "/etc/init/mounted-dev.conf"}, stream=True)
253@@ -321,7 +364,7 @@
254 files_api.post.assert_any_call(
255 params={"path": "/etc/systemd/system/snapd.service.d/no-cdn.conf"},
256 data=b"[Service]\nEnvironment=SNAPPY_STORE_NO_CDN=1\n",
257- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
258+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
259 container.start.assert_called_once_with(wait=True)
260 self.assertEqual(LXD_RUNNING, container.status_code)
261
262@@ -340,6 +383,7 @@
263 client.profiles.get.side_effect = FakeLXDAPIException
264 container = client.containers.create.return_value
265 client.containers.get.return_value = container
266+ client.host_info = {"environment": {"driver_version": "2.0"}}
267 container.start.side_effect = (
268 lambda wait=False: setattr(container, "status_code", LXD_RUNNING))
269 files_api = container.api.files
270@@ -360,7 +404,7 @@
271 data=(
272 fallback_hosts +
273 "\n127.0.1.1\texample.buildd example\n").encode("UTF-8"),
274- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
275+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
276
277 def test_start_with_mounted_dev_conf(self):
278 fs_fixture = self.useFixture(FakeFilesystem())
279@@ -375,6 +419,7 @@
280 self.useFixture(MockPatch("pylxd.Client"))
281 client = pylxd.Client()
282 client.profiles.get.side_effect = FakeLXDAPIException
283+ client.host_info = {"environment": {"driver_version": "2.0"}}
284 container = client.containers.create.return_value
285 client.containers.get.return_value = container
286 container.start.side_effect = (
287@@ -406,7 +451,7 @@
288 : # /sbin/MAKEDEV std fd ppp tun
289 end script
290 """).encode("UTF-8"),
291- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
292+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
293
294 def test_run(self):
295 processes_fixture = self.useFixture(FakeProcesses())
296@@ -456,7 +501,7 @@
297 container.api.files.post.assert_called_once_with(
298 params={"path": target_path},
299 data=b"hello\n",
300- headers={"X-LXD-uid": 0, "X-LXD-gid": 0, "X-LXD-mode": "0644"})
301+ headers={"X-LXD-uid": "0", "X-LXD-gid": "0", "X-LXD-mode": "0644"})
302
303 def test_copy_in_error(self):
304 source_dir = self.useFixture(TempDir()).path

Subscribers

People subscribed via source and target branches