launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21779
[Merge] lp:~cjwatson/launchpad-buildd/create-remove-python into lp:launchpad-buildd
Colin Watson has proposed merging lp:~cjwatson/launchpad-buildd/create-remove-python into lp:launchpad-buildd with lp:~cjwatson/launchpad-buildd/target-abstractions as a prerequisite.
Commit message:
Rewrite unpack-chroot and remove-build in Python, allowing them to have
unit tests.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/create-remove-python/+merge/328556
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad-buildd/create-remove-python into lp:launchpad-buildd.
=== modified file 'bin/remove-build'
--- bin/remove-build 2017-07-25 22:11:19 +0000
+++ bin/remove-build 2017-08-04 02:29:49 +0000
@@ -1,25 +1,24 @@
-#!/bin/sh
+#! /usr/bin/python -u
#
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-# Buildd Slave tool to remove an unmounted chroot
-
-# Expects build id as arg 1, makes build-id to contain the build
-
-# Needs RM to be set to a gnu rm instance
-# Needs SUDO to be set to a sudo instance for passwordless access
-
-RM=/bin/rm
-SUDO=/usr/bin/sudo
-BUILDID="$1"
-
-set -e
-
-exec 2>&1
-
-echo "Removing build $BUILDID"
-
-cd $HOME
-
-$SUDO $RM -rf "build-$BUILDID"
+"""Remove an unmounted chroot."""
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import sys
+
+from lpbuildd.target.operation import configure_logging
+from lpbuildd.target.remove import Remove
+
+
+def main():
+ configure_logging()
+ return Remove().run()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
=== modified file 'bin/unpack-chroot'
--- bin/unpack-chroot 2017-07-25 22:11:19 +0000
+++ bin/unpack-chroot 2017-08-04 02:29:49 +0000
@@ -1,43 +1,24 @@
-#!/bin/sh
+#! /usr/bin/python -u
#
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-# Buildd Slave tool to unpack a chroot tarball
-
-# Expects build id as arg 1, makes build-id to contain the build
-# Expects bzip2 compressed tarball as arg 2
-
-# Needs TAR to be set to a gnu tar instance, that needs bzip2
-# Needs SUDO to be set to a sudo instance for passwordless access
-# BUNZIP2 must un-bzip2
-# FILE must implement the -b and -i arguments (so a Debianish file)
-
-export PATH=/usr/bin:/bin:/usr/sbin:/sbin:${PATH}
-
-TAR=tar
-SUDO=sudo
-BUNZIP2=bunzip2
-FILE=file
-
-BUILDID="$1"
-TARBALL="$2"
-
-set -e
-
-exec 2>&1
-
-MIMETYPE=$($FILE -bi "$TARBALL")
-
-if [ x"$MIMETYPE" = "xapplication/x-bzip2" ]; then
- echo "Uncompressing the tarball..."
- $BUNZIP2 -c < "$TARBALL" > "$TARBALL".tmp
- mv "$TARBALL".tmp "$TARBALL"
- exec $0 "$@"
-fi
-
-cd $HOME
-cd "build-$BUILDID"
-
-echo "Unpacking chroot for build $BUILDID"
-$SUDO $TAR -xf "$TARBALL"
+"""Unpack a chroot tarball."""
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import sys
+
+from lpbuildd.target.create import Create
+from lpbuildd.target.operation import configure_logging
+
+
+def main():
+ configure_logging()
+ return Create().run()
+
+
+if __name__ == "__main__":
+ sys.exit(main())
=== modified file 'debian/changelog'
--- debian/changelog 2017-08-03 13:13:08 +0000
+++ debian/changelog 2017-08-04 02:29:49 +0000
@@ -15,6 +15,8 @@
* Rewrite override-sources-list in Python, allowing it to have unit tests.
* Rewrite add-trusted-keys in Python, allowing it to have unit tests.
* Configure sbuild to use schroot sessions rather than sudo.
+ * Rewrite unpack-chroot and remove-build in Python, allowing them to have
+ unit tests.
-- Colin Watson <cjwatson@xxxxxxxxxx> Tue, 25 Jul 2017 23:07:58 +0100
=== modified file 'lpbuildd/slave.py'
--- lpbuildd/slave.py 2017-08-04 02:29:49 +0000
+++ lpbuildd/slave.py 2017-08-04 02:29:49 +0000
@@ -163,9 +163,8 @@
def doUnpack(self):
"""Unpack the build chroot."""
- self.runSubProcess(
- self._unpackpath,
- ["unpack-chroot", self._buildid, self._chroottarfile])
+ self.runTargetSubProcess(
+ self._unpackpath, ["unpack-chroot", self._chroottarfile])
def doReapProcesses(self, state, notify=True):
"""Reap any processes left lying around in the chroot."""
@@ -188,7 +187,7 @@
def doCleanup(self):
"""Remove the build tree etc."""
- self.runSubProcess(self._cleanpath, ["remove-build", self._buildid])
+ self.runTargetSubProcess(self._cleanpath, ["remove-build"])
# Sanitize the URLs in the buildlog file if this is a build
# in a private archive.
=== modified file 'lpbuildd/target/backend.py'
--- lpbuildd/target/backend.py 2017-08-04 02:29:49 +0000
+++ lpbuildd/target/backend.py 2017-08-04 02:29:49 +0000
@@ -6,6 +6,7 @@
__metaclass__ = type
import os.path
+import subprocess
class BackendException(Exception):
@@ -30,6 +31,13 @@
raise KeyError("Unknown backend: %s" % name)
return backend_factory(build_id, series=series, arch=arch)
+ def create(self, tarball_path):
+ """Create the backend based on a chroot tarball.
+
+ This puts the backend into a state where it is ready to be started.
+ """
+ raise NotImplementedError
+
def run(self, args, env=None, input_text=None, **kwargs):
"""Run a command in the target environment.
@@ -53,3 +61,7 @@
environment's root.
"""
raise NotImplementedError
+
+ def remove(self):
+ """Remove the backend."""
+ subprocess.check_call(["sudo", "rm", "-rf", self.build_path])
=== modified file 'lpbuildd/target/chroot.py'
--- lpbuildd/target/chroot.py 2017-08-04 02:29:49 +0000
+++ lpbuildd/target/chroot.py 2017-08-04 02:29:49 +0000
@@ -23,6 +23,11 @@
super(Chroot, self).__init__(build_id, series=series, arch=arch)
self.chroot_path = os.path.join(self.build_path, "chroot-autobuild")
+ def create(self, tarball_path):
+ """See `Backend`."""
+ subprocess.check_call(
+ ["sudo", "tar", "-C", self.build_path, "-xf", tarball_path])
+
def run(self, args, env=None, input_text=None, **kwargs):
"""See `Backend`."""
if env:
=== added file 'lpbuildd/target/create.py'
--- lpbuildd/target/create.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/target/create.py 2017-08-04 02:29:49 +0000
@@ -0,0 +1,28 @@
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import logging
+
+from lpbuildd.target.operation import Operation
+
+
+logger = logging.getLogger(__name__)
+
+
+class Create(Operation):
+
+ description = "Create the target environment."
+
+ def make_parser(self):
+ parser = super(Create, self).make_parser()
+ parser.add_argument("tarball_path", help="path to chroot tarball")
+ return parser
+
+ def run(self):
+ logger.info("Creating target for build %s", self.args.build_id)
+ self.backend.create(self.args.tarball_path)
+ return 0
=== added file 'lpbuildd/target/remove.py'
--- lpbuildd/target/remove.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/target/remove.py 2017-08-04 02:29:49 +0000
@@ -0,0 +1,23 @@
+# Copyright 2009-2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import logging
+
+from lpbuildd.target.operation import Operation
+
+
+logger = logging.getLogger(__name__)
+
+
+class Remove(Operation):
+
+ description = "Remove the target environment."
+
+ def run(self):
+ logger.info("Removing build %s", self.args.build_id)
+ self.backend.remove()
+ return 0
=== modified file 'lpbuildd/target/tests/test_chroot.py'
--- lpbuildd/target/tests/test_chroot.py 2017-08-04 02:29:49 +0000
+++ lpbuildd/target/tests/test_chroot.py 2017-08-04 02:29:49 +0000
@@ -17,6 +17,20 @@
class TestChroot(TestCase):
+ def test_create(self):
+ self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+ processes_fixture = self.useFixture(FakeProcesses())
+ processes_fixture.add(lambda _: {}, name="sudo")
+ Chroot("1", "xenial", "amd64").create("/path/to/tarball")
+
+ expected_args = [
+ ["sudo", "tar", "-C", "/expected/home/build-1",
+ "-xf", "/path/to/tarball"],
+ ]
+ self.assertEqual(
+ expected_args,
+ [proc._args["args"] for proc in processes_fixture.procs])
+
def test_run(self):
self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
processes_fixture = self.useFixture(FakeProcesses())
@@ -54,3 +68,14 @@
self.assertEqual(
expected_args,
[proc._args["args"] for proc in processes_fixture.procs])
+
+ def test_remove(self):
+ self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+ processes_fixture = self.useFixture(FakeProcesses())
+ processes_fixture.add(lambda _: {}, name="sudo")
+ Chroot("1", "xenial", "amd64").remove()
+
+ expected_args = [["sudo", "rm", "-rf", "/expected/home/build-1"]]
+ self.assertEqual(
+ expected_args,
+ [proc._args["args"] for proc in processes_fixture.procs])
=== added file 'lpbuildd/target/tests/test_create.py'
--- lpbuildd/target/tests/test_create.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/target/tests/test_create.py 2017-08-04 02:29:49 +0000
@@ -0,0 +1,30 @@
+# Copyright 2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from fixtures import EnvironmentVariable
+from systemfixtures import FakeProcesses
+from testtools import TestCase
+
+from lpbuildd.target.create import Create
+
+
+class TestCreate(TestCase):
+
+ def test_succeeds(self):
+ self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+ processes_fixture = self.useFixture(FakeProcesses())
+ processes_fixture.add(lambda _: {}, name="sudo")
+ args = [
+ "--backend=chroot", "--series=xenial", "--arch=amd64", "1",
+ "/path/to/tarball"]
+ Create(args=args).run()
+
+ expected_args = [
+ ["sudo", "tar", "-C", "/expected/home/build-1",
+ "-xf", "/path/to/tarball"],
+ ]
+ self.assertEqual(
+ expected_args,
+ [proc._args["args"] for proc in processes_fixture.procs])
=== added file 'lpbuildd/target/tests/test_remove.py'
--- lpbuildd/target/tests/test_remove.py 1970-01-01 00:00:00 +0000
+++ lpbuildd/target/tests/test_remove.py 2017-08-04 02:29:49 +0000
@@ -0,0 +1,25 @@
+# Copyright 2017 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from fixtures import EnvironmentVariable
+from systemfixtures import FakeProcesses
+from testtools import TestCase
+
+from lpbuildd.target.remove import Remove
+
+
+class TestRemove(TestCase):
+
+ def test_succeeds(self):
+ self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+ processes_fixture = self.useFixture(FakeProcesses())
+ processes_fixture.add(lambda _: {}, name="sudo")
+ args = ["--backend=chroot", "--series=xenial", "--arch=amd64", "1"]
+ Remove(args=args).run()
+
+ expected_args = [["sudo", "rm", "-rf", "/expected/home/build-1"]]
+ self.assertEqual(
+ expected_args,
+ [proc._args["args"] for proc in processes_fixture.procs])
=== modified file 'lpbuildd/tests/test_binarypackage.py'
--- lpbuildd/tests/test_binarypackage.py 2017-08-03 13:13:08 +0000
+++ lpbuildd/tests/test_binarypackage.py 2017-08-04 02:29:49 +0000
@@ -313,7 +313,9 @@
self.buildmanager.iterate(0)
self.assertState(
BinaryPackageBuildState.CLEANUP,
- ['sharepath/slavebin/remove-build', 'remove-build', self.buildid],
+ ['sharepath/slavebin/remove-build', 'remove-build',
+ '--backend=chroot', '--series=warty', '--arch=i386',
+ self.buildid],
final=True)
self.assertFalse(self.slave.wasCalled('builderFail'))
=== modified file 'lpbuildd/tests/test_debian.py'
--- lpbuildd/tests/test_debian.py 2017-08-04 02:29:49 +0000
+++ lpbuildd/tests/test_debian.py 2017-08-04 02:29:49 +0000
@@ -106,6 +106,7 @@
self.assertEqual(DebianBuildState.UNPACK, self.getState())
self.assertEqual(
(['sharepath/slavebin/unpack-chroot', 'unpack-chroot',
+ '--backend=chroot', '--series=xenial', '--arch=amd64',
self.buildid,
os.path.join(self.buildmanager._cachepath, 'chroot.tar.gz')],
None),
@@ -177,7 +178,9 @@
self.buildmanager.iterate(0)
self.assertEqual(DebianBuildState.CLEANUP, self.getState())
self.assertEqual(
- (['sharepath/slavebin/remove-build', 'remove-build', self.buildid],
+ (['sharepath/slavebin/remove-build', 'remove-build',
+ '--backend=chroot', '--series=xenial', '--arch=amd64',
+ self.buildid],
None),
self.buildmanager.commands[-1])
self.assertEqual(
@@ -208,6 +211,7 @@
self.assertEqual(DebianBuildState.UNPACK, self.getState())
self.assertEqual(
(['sharepath/slavebin/unpack-chroot', 'unpack-chroot',
+ '--backend=chroot', '--series=xenial', '--arch=amd64',
self.buildid,
os.path.join(self.buildmanager._cachepath, 'chroot.tar.gz')],
None),
@@ -290,7 +294,9 @@
self.buildmanager.iterate(0)
self.assertEqual(DebianBuildState.CLEANUP, self.getState())
self.assertEqual(
- (['sharepath/slavebin/remove-build', 'remove-build', self.buildid],
+ (['sharepath/slavebin/remove-build', 'remove-build',
+ '--backend=chroot', '--series=xenial', '--arch=amd64',
+ self.buildid],
None),
self.buildmanager.commands[-1])
self.assertEqual(
Follow ups