launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29595
[Merge] ~cjwatson/launchpad-buildd:lpcraft-as-buildd-user into launchpad-buildd:master
Colin Watson has proposed merging ~cjwatson/launchpad-buildd:lpcraft-as-buildd-user into launchpad-buildd:master.
Commit message:
Run lpcraft as the buildd user to allow nvidia.runtime=true to work
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/+git/launchpad-buildd/+merge/436283
LXC's `nvidia` hook refuses to run if `both 0 0` is set in LXD's `raw.idmap` key (mapping UID/GID 0 outside the container to UID/GID 0 inside). I'm not exactly sure why that is, but running `lpcraft` as a non-root user is fairly straightforward, so just do that to work around it.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad-buildd:lpcraft-as-buildd-user into launchpad-buildd:master.
diff --git a/debian/changelog b/debian/changelog
index 867c9f5..61afd5a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,7 @@ launchpad-buildd (227) UNRELEASED; urgency=medium
* Tolerate receiving "builder_constraints": None.
* Check the appropriate server.key path for the LXD snap.
+ * Run lpcraft as the buildd user to allow nvidia.runtime=true to work.
-- Colin Watson <cjwatson@xxxxxxxxxx> Tue, 24 Jan 2023 13:13:27 +0000
diff --git a/lpbuildd/target/run_ci.py b/lpbuildd/target/run_ci.py
index e75cdc9..62757e2 100644
--- a/lpbuildd/target/run_ci.py
+++ b/lpbuildd/target/run_ci.py
@@ -157,6 +157,16 @@ class RunCI(BuilderProxyOperationMixin, Operation):
help="perform malware scans on output files",
)
+ def run_build_command(self, args, **kwargs):
+ # Run build commands as the `buildd` user, since `lpcraft` can only
+ # start containers with `nvidia.runtime=true` if it's run as a
+ # non-root user.
+ super().run_build_command(
+ ["runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--"]
+ + args,
+ **kwargs,
+ )
+
def run_job(self):
logger.info("Running job phase...")
env = self.build_proxy_environment(proxy_url=self.args.proxy_url)
@@ -167,6 +177,7 @@ class RunCI(BuilderProxyOperationMixin, Operation):
job_output_path = os.path.join(
output_path, self.args.job_name, str(self.args.job_index))
self.backend.run(["mkdir", "-p", job_output_path])
+ self.backend.run(["chown", "-R", "buildd:buildd", output_path])
lpcraft_args = [
"lpcraft",
"-v",
diff --git a/lpbuildd/target/tests/test_run_ci.py b/lpbuildd/target/tests/test_run_ci.py
index daee43f..3eac5fc 100644
--- a/lpbuildd/target/tests/test_run_ci.py
+++ b/lpbuildd/target/tests/test_run_ci.py
@@ -388,7 +388,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output test 0 2>&1 " # noqa: E501
"| tee /build/output/test/0/log",
@@ -412,7 +414,9 @@ class TestRunCI(TestCase):
}
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output test 0 2>&1 " # noqa: E501
"| tee /build/output/test/0/log",
@@ -431,7 +435,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -456,7 +462,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -479,7 +487,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -501,7 +511,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -522,7 +534,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -530,7 +544,8 @@ class TestRunCI(TestCase):
"| tee /build/output/test/0/log",
], cwd="/build/tree"),
RanBuildCommand(
- ["clamscan", "--recursive", "/build/output/test/0"],
+ ["runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
+ "clamscan", "--recursive", "/build/output/test/0"],
cwd="/build/tree"),
]))
@@ -538,7 +553,7 @@ class TestRunCI(TestCase):
class FailClamscan(FakeMethod):
def __call__(self, run_args, *args, **kwargs):
super().__call__(run_args, *args, **kwargs)
- if run_args[0] == "clamscan":
+ if run_args[0] == "runuser" and "clamscan" in run_args:
raise subprocess.CalledProcessError(1, run_args)
self.useFixture(FakeLogger())
@@ -563,7 +578,9 @@ class TestRunCI(TestCase):
run_ci.run_job()
self.assertThat(run_ci.backend.run.calls, MatchesListwise([
RanCommand(["mkdir", "-p", "/build/output/test/0"]),
+ RanCommand(["chown", "-R", "buildd:buildd", "/build/output"]),
RanBuildCommand([
+ "runuser", "-u", "buildd", "-g", "buildd", "-G", "lxd", "--",
"/bin/bash", "-o", "pipefail", "-c",
"lpcraft -v run-one --output-directory /build/output "
"test 0 "
@@ -590,7 +607,7 @@ class TestRunCI(TestCase):
class FailInstall(FakeMethod):
def __call__(self, run_args, *args, **kwargs):
super().__call__(run_args, *args, **kwargs)
- if run_args[0] == "/bin/bash":
+ if run_args[0] == "runuser" and "/bin/bash" in run_args:
raise subprocess.CalledProcessError(1, run_args)
self.useFixture(FakeLogger())