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 <[email protected]> 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())
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : [email protected] Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp

