← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad-buildd/start-stop-python into lp:launchpad-buildd

 

Colin Watson has proposed merging lp:~cjwatson/launchpad-buildd/start-stop-python into lp:launchpad-buildd with lp:~cjwatson/launchpad-buildd/create-remove-python as a prerequisite.

Commit message:
Rewrite mount-chroot and umount-chroot 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/start-stop-python/+merge/328570
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad-buildd/start-stop-python into lp:launchpad-buildd.
=== modified file 'bin/mount-chroot'
--- bin/mount-chroot	2017-07-25 22:11:19 +0000
+++ bin/mount-chroot	2017-08-04 12:08:56 +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 mount a chroot
-
-# Expects build id as arg 1, makes build-id to contain the build
-
-# Needs SUDO to be set to a sudo instance for passwordless access
-
-SUDO=/usr/bin/sudo
-BUILDID="$1"
-
-set -e
-
-exec 2>&1
-
-echo "Mounting chroot for build $BUILDID"
-
-$SUDO mount -t proc none "$HOME/build-$BUILDID/chroot-autobuild/proc"
-$SUDO mount -t devpts -o gid=5,mode=620 none "$HOME/build-$BUILDID/chroot-autobuild/dev/pts"
-$SUDO mount -t sysfs none "$HOME/build-$BUILDID/chroot-autobuild/sys"
-$SUDO mount -t tmpfs none "$HOME/build-$BUILDID/chroot-autobuild/dev/shm"
-$SUDO cp /etc/hosts /etc/hostname /etc/resolv.conf $HOME/build-$BUILDID/chroot-autobuild/etc/
+"""Mount a chroot."""
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import sys
+
+from lpbuildd.target.operation import configure_logging
+from lpbuildd.target.start import Start
+
+
+def main():
+    configure_logging()
+    return Start().run()
+
+
+if __name__ == "__main__":
+    sys.exit(main())

=== modified file 'bin/umount-chroot'
--- bin/umount-chroot	2017-07-25 22:11:19 +0000
+++ bin/umount-chroot	2017-08-04 12:08:56 +0000
@@ -1,40 +1,24 @@
-#!/bin/sh
+#! /usr/bin/python -u
 #
-# Copyright 2009-2011 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 mount a chroot
-
-# Expects build id as arg 1, makes build-id to contain the build
-
-# Needs SUDO to be set to a sudo instance for passwordless access
-
-SUDO=/usr/bin/sudo
-BUILDID="$1"
-GREP=/bin/grep
-CUT=/usr/bin/cut
-XARGS=/usr/bin/xargs
-SORT=/usr/bin/sort
-
-set -e
-
-exec 2>&1
-
-echo "Unmounting chroot for build $BUILDID..."
-
-# binfmt-support adds a mount under /proc, which means that our first
-# pass at umounting fails unless we reverse the list.  Leave the while
-# loop in just to handle pathological cases, too.
-COUNT=0
-while $GREP -q "$HOME/build-$BUILDID/chroot-autobuild" /proc/mounts; do
-    COUNT=$(($COUNT+1))
-    if [ $COUNT -ge 20 ]; then
-    	echo "failed to umount $HOME/build-$BUILDID/chroot-autobuild"
-	if [ -x /usr/bin/lsof ]; then
-	    /usr/bin/lsof "$HOME/build-$BUILDID/chroot-autobuild"
-	fi
-	exit 1
-    fi
-    $GREP "$HOME/build-$BUILDID/chroot-autobuild" /proc/mounts | \
-	  $CUT -d\  -f2 | LANG=C $SORT -r | $XARGS -r -n 1 $SUDO umount || sleep 1
-done
+"""Unmount a chroot."""
+
+from __future__ import print_function
+
+__metaclass__ = type
+
+import sys
+
+from lpbuildd.target.operation import configure_logging
+from lpbuildd.target.stop import Stop
+
+
+def main():
+    configure_logging()
+    return Stop().run()
+
+
+if __name__ == "__main__":
+    sys.exit(main())

=== modified file 'debian/changelog'
--- debian/changelog	2017-08-04 12:08:56 +0000
+++ debian/changelog	2017-08-04 12:08:56 +0000
@@ -17,6 +17,8 @@
   * Configure sbuild to use schroot sessions rather than sudo.
   * Rewrite unpack-chroot and remove-build in Python, allowing them to have
     unit tests.
+  * Rewrite mount-chroot and umount-chroot in Python, allowing them to have
+    unit tests.
 
  -- Colin Watson <cjwatson@xxxxxxxxxx>  Tue, 25 Jul 2017 23:07:58 +0100
 

=== modified file 'debian/control'
--- debian/control	2017-08-03 13:13:08 +0000
+++ debian/control	2017-08-04 12:08:56 +0000
@@ -10,7 +10,7 @@
 Architecture: all
 Depends: python-lpbuildd (=${source:Version}), python, debootstrap, dpkg-dev,
  file, bzip2, sudo, ntpdate, adduser, apt-transport-https, lsb-release,
- pristine-tar, python-apt, sbuild, schroot, ${misc:Depends}
+ pristine-tar, python-apt, sbuild, schroot, lsof, ${misc:Depends}
 Description: Launchpad buildd slave
  This is the launchpad buildd slave package. It contains everything needed to
  get a launchpad buildd going apart from the database manipulation required to

=== modified file 'lpbuildd/slave.py'
--- lpbuildd/slave.py	2017-08-04 12:08:56 +0000
+++ lpbuildd/slave.py	2017-08-04 12:08:56 +0000
@@ -196,13 +196,11 @@
 
     def doMounting(self):
         """Mount things in the chroot, e.g. proc."""
-        self.runSubProcess( self._mountpath,
-                            ["mount-chroot", self._buildid])
+        self.runTargetSubProcess(self._mountpath, ["mount-chroot"])
 
     def doUnmounting(self):
         """Unmount the chroot."""
-        self.runSubProcess( self._umountpath,
-                            ["umount-chroot", self._buildid])
+        self.runTargetSubProcess(self._umountpath, ["umount-chroot"])
 
     def initiate(self, files, chroot, extra_args):
         """Initiate a build given the input files.

=== modified file 'lpbuildd/target/backend.py'
--- lpbuildd/target/backend.py	2017-08-04 12:08:56 +0000
+++ lpbuildd/target/backend.py	2017-08-04 12:08:56 +0000
@@ -38,6 +38,13 @@
         """
         raise NotImplementedError
 
+    def start(self):
+        """Start the backend.
+
+        This puts the backend into a state where it can run commands.
+        """
+        raise NotImplementedError
+
     def run(self, args, env=None, input_text=None, **kwargs):
         """Run a command in the target environment.
 
@@ -62,6 +69,10 @@
         """
         raise NotImplementedError
 
+    def stop(self):
+        """Stop the backend."""
+        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 12:08:56 +0000
+++ lpbuildd/target/chroot.py	2017-08-04 12:08:56 +0000
@@ -8,8 +8,12 @@
 import os.path
 import stat
 import subprocess
+import time
 
-from lpbuildd.target.backend import Backend
+from lpbuildd.target.backend import (
+    Backend,
+    BackendException,
+    )
 from lpbuildd.util import (
     set_personality,
     shell_escape,
@@ -28,6 +32,25 @@
         subprocess.check_call(
             ["sudo", "tar", "-C", self.build_path, "-xf", tarball_path])
 
+    def start(self):
+        """See `Backend`."""
+        mounts = (
+            ("proc", None, "none", "proc"),
+            ("devpts", "gid=5,mode=620", "none", "dev/pts"),
+            ("sysfs", None, "none", "sys"),
+            ("tmpfs", None, "none", "dev/shm"),
+            )
+        for mount in mounts:
+            cmd = ["sudo", "mount", "-t", mount[0]]
+            if mount[1]:
+                cmd.extend(["-o", mount[1]])
+            cmd.append(mount[2])
+            cmd.append(os.path.join(self.chroot_path, mount[3]))
+            subprocess.check_call(cmd)
+
+        for path in ("/etc/hosts", "/etc/hostname", "/etc/resolv.conf"):
+            self.copy_in(path, path)
+
     def run(self, args, env=None, input_text=None, **kwargs):
         """See `Backend`."""
         if env:
@@ -57,3 +80,29 @@
         subprocess.check_call(
             ["sudo", "install", "-o", "root", "-g", "root", "-m", "%o" % mode,
              source_path, full_target_path])
+
+    def _get_chroot_mounts(self):
+        with open("/proc/mounts") as mounts_file:
+            for line in mounts_file:
+                mount_path = line.split()[1]
+                if mount_path.startswith(self.chroot_path):
+                    yield mount_path
+
+    def stop(self):
+        """See `Backend`."""
+        for _ in range(20):
+            # Reverse the list, since we must unmount subdirectories before
+            # parent directories.
+            mounts = reversed(list(self._get_chroot_mounts()))
+            if not mounts:
+                break
+            retcodes = [
+                subprocess.call(["sudo", "umount", mount])
+                for mount in mounts]
+            if any(retcodes):
+                time.sleep(1)
+        else:
+            if list(self._get_chroot_mounts()):
+                subprocess.check_call(["lsof", self.chroot_path])
+                raise BackendException(
+                    "Failed to unmount %s" % self.chroot_path)

=== added file 'lpbuildd/target/start.py'
--- lpbuildd/target/start.py	1970-01-01 00:00:00 +0000
+++ lpbuildd/target/start.py	2017-08-04 12:08:56 +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 Start(Operation):
+
+    description = "Start the target environment."
+
+    def run(self):
+        logger.info("Starting target for build %s", self.args.build_id)
+        self.backend.start()
+        return 0

=== added file 'lpbuildd/target/stop.py'
--- lpbuildd/target/stop.py	1970-01-01 00:00:00 +0000
+++ lpbuildd/target/stop.py	2017-08-04 12:08:56 +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.backend import BackendException
+from lpbuildd.target.operation import Operation
+
+
+logger = logging.getLogger(__name__)
+
+
+class Stop(Operation):
+
+    description = "Stop the target environment."
+
+    def run(self):
+        logger.info("Stopping target for build %s", self.args.build_id)
+        try:
+            self.backend.stop()
+        except BackendException:
+            logger.exception('Failed to stop target')
+            return 1
+        return 0

=== modified file 'lpbuildd/target/tests/test_chroot.py'
--- lpbuildd/target/tests/test_chroot.py	2017-08-04 12:08:56 +0000
+++ lpbuildd/target/tests/test_chroot.py	2017-08-04 12:08:56 +0000
@@ -4,15 +4,23 @@
 __metaclass__ = type
 
 import os.path
+from textwrap import dedent
+import time
 
 from fixtures import (
     EnvironmentVariable,
     TempDir,
     )
-from systemfixtures import FakeProcesses
+from systemfixtures import (
+    FakeFilesystem,
+    FakeProcesses,
+    FakeTime,
+    )
 from testtools import TestCase
 
+from lpbuildd.target.backend import BackendException
 from lpbuildd.target.chroot import Chroot
+from lpbuildd.target.tests.testfixtures import SudoUmount
 
 
 class TestChroot(TestCase):
@@ -31,6 +39,43 @@
             expected_args,
             [proc._args["args"] for proc in processes_fixture.procs])
 
+    def test_start(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        processes_fixture.add(lambda _: {}, name="sudo")
+        fs_fixture = self.useFixture(FakeFilesystem())
+        fs_fixture.add("/etc")
+        os.mkdir("/etc")
+        for etc_name in ("hosts", "hostname", "resolv.conf.real"):
+            with open(os.path.join("/etc", etc_name), "w") as etc_file:
+                etc_file.write("%s\n" % etc_name)
+            os.chmod(os.path.join("/etc", etc_name), 0o644)
+        os.symlink("resolv.conf.real", "/etc/resolv.conf")
+        Chroot("1", "xenial", "amd64").start()
+
+        expected_args = [
+            ["sudo", "mount", "-t", "proc", "none",
+             "/expected/home/build-1/chroot-autobuild/proc"],
+            ["sudo", "mount", "-t", "devpts", "-o", "gid=5,mode=620", "none",
+             "/expected/home/build-1/chroot-autobuild/dev/pts"],
+            ["sudo", "mount", "-t", "sysfs", "none",
+             "/expected/home/build-1/chroot-autobuild/sys"],
+            ["sudo", "mount", "-t", "tmpfs", "none",
+             "/expected/home/build-1/chroot-autobuild/dev/shm"],
+            ["sudo", "install", "-o", "root", "-g", "root", "-m", "644",
+             "/etc/hosts",
+             "/expected/home/build-1/chroot-autobuild/etc/hosts"],
+            ["sudo", "install", "-o", "root", "-g", "root", "-m", "644",
+             "/etc/hostname",
+             "/expected/home/build-1/chroot-autobuild/etc/hostname"],
+            ["sudo", "install", "-o", "root", "-g", "root", "-m", "644",
+             "/etc/resolv.conf",
+             "/expected/home/build-1/chroot-autobuild/etc/resolv.conf"],
+            ]
+        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())
@@ -69,6 +114,91 @@
             expected_args,
             [proc._args["args"] for proc in processes_fixture.procs])
 
+    def _make_initial_proc_mounts(self):
+        fs_fixture = self.useFixture(FakeFilesystem())
+        fs_fixture.add("/proc")
+        os.mkdir("/proc")
+        with open("/proc/mounts", "w") as mounts_file:
+            mounts_file.write(dedent("""\
+                sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
+                proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
+                none {chroot}/proc proc rw,relatime 0 0
+                none {chroot}/dev/pts devpts rw,relative,gid=5,mode=620 0 0
+                none {chroot}/sys sysfs rw,relatime 0 0
+                none {chroot}/dev/shm tmpfs rw,relatime 0 0
+                """.format(chroot="/expected/home/build-1/chroot-autobuild")))
+
+    def test_stop(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        processes_fixture.add(SudoUmount(), name="sudo")
+        self._make_initial_proc_mounts()
+        self.useFixture(FakeTime())
+        start_time = time.time()
+        Chroot("1", "xenial", "amd64").stop()
+
+        expected_chroot_path = "/expected/home/build-1/chroot-autobuild"
+        expected_args = [
+            ["sudo", "umount", expected_chroot_path + "/dev/shm"],
+            ["sudo", "umount", expected_chroot_path + "/sys"],
+            ["sudo", "umount", expected_chroot_path + "/dev/pts"],
+            ["sudo", "umount", expected_chroot_path + "/proc"],
+            ]
+        self.assertEqual(
+            expected_args,
+            [proc._args["args"] for proc in processes_fixture.procs])
+        self.assertEqual(start_time, time.time())
+
+    def test_stop_retries(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        delays = {"/expected/home/build-1/chroot-autobuild/sys": 1}
+        processes_fixture.add(SudoUmount(delays=delays), name="sudo")
+        self._make_initial_proc_mounts()
+        self.useFixture(FakeTime())
+        start_time = time.time()
+        Chroot("1", "xenial", "amd64").stop()
+
+        expected_chroot_path = "/expected/home/build-1/chroot-autobuild"
+        expected_args = [
+            ["sudo", "umount", expected_chroot_path + "/dev/shm"],
+            ["sudo", "umount", expected_chroot_path + "/sys"],
+            ["sudo", "umount", expected_chroot_path + "/dev/pts"],
+            ["sudo", "umount", expected_chroot_path + "/proc"],
+            ["sudo", "umount", expected_chroot_path + "/sys"],
+            ]
+        self.assertEqual(
+            expected_args,
+            [proc._args["args"] for proc in processes_fixture.procs])
+        self.assertEqual(start_time + 1, time.time())
+
+    def test_stop_too_many_retries(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        delays = {"/expected/home/build-1/chroot-autobuild/sys": 20}
+        processes_fixture.add(SudoUmount(delays=delays), name="sudo")
+        processes_fixture.add(lambda _: {}, name="lsof")
+        self._make_initial_proc_mounts()
+        self.useFixture(FakeTime())
+        start_time = time.time()
+        self.assertRaises(
+            BackendException, Chroot("1", "xenial", "amd64").stop)
+
+        expected_chroot_path = "/expected/home/build-1/chroot-autobuild"
+        expected_args = [
+            ["sudo", "umount", expected_chroot_path + "/dev/shm"],
+            ["sudo", "umount", expected_chroot_path + "/sys"],
+            ["sudo", "umount", expected_chroot_path + "/dev/pts"],
+            ["sudo", "umount", expected_chroot_path + "/proc"],
+            ]
+        expected_args.extend(
+            [["sudo", "umount", expected_chroot_path + "/sys"]] * 19)
+        expected_args.append(["lsof", expected_chroot_path])
+        self.assertEqual(
+            expected_args,
+            [proc._args["args"] for proc in processes_fixture.procs])
+        self.assertEqual(start_time + 20, time.time())
+
     def test_remove(self):
         self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
         processes_fixture = self.useFixture(FakeProcesses())

=== added file 'lpbuildd/target/tests/test_start.py'
--- lpbuildd/target/tests/test_start.py	1970-01-01 00:00:00 +0000
+++ lpbuildd/target/tests/test_start.py	2017-08-04 12:08:56 +0000
@@ -0,0 +1,39 @@
+# Copyright 2017 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import os.path
+
+from fixtures import EnvironmentVariable
+from systemfixtures import (
+    FakeFilesystem,
+    FakeProcesses,
+    )
+from testtools import TestCase
+
+from lpbuildd.target.start import Start
+
+
+class TestStart(TestCase):
+
+    def test_succeeds(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        processes_fixture.add(lambda _: {}, name="sudo")
+        fs_fixture = self.useFixture(FakeFilesystem())
+        fs_fixture.add("/etc")
+        os.mkdir("/etc")
+        for etc_name in ("hosts", "hostname", "resolv.conf.real"):
+            with open(os.path.join("/etc", etc_name), "w") as etc_file:
+                etc_file.write("%s\n" % etc_name)
+            os.chmod(os.path.join("/etc", etc_name), 0o644)
+        os.symlink("resolv.conf.real", "/etc/resolv.conf")
+        args = ["--backend=chroot", "--series=xenial", "--arch=amd64", "1"]
+        Start(args=args).run()
+
+        # Tested in more detail in lpbuildd.target.tests.test_chroot.
+        self.assertIn(
+            ["sudo", "mount", "-t", "proc", "none",
+             "/expected/home/build-1/chroot-autobuild/proc"],
+            [proc._args["args"] for proc in processes_fixture.procs])

=== added file 'lpbuildd/target/tests/test_stop.py'
--- lpbuildd/target/tests/test_stop.py	1970-01-01 00:00:00 +0000
+++ lpbuildd/target/tests/test_stop.py	2017-08-04 12:08:56 +0000
@@ -0,0 +1,38 @@
+# Copyright 2017 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import os.path
+
+from fixtures import EnvironmentVariable
+from systemfixtures import (
+    FakeFilesystem,
+    FakeProcesses,
+    )
+from testtools import TestCase
+
+from lpbuildd.target.stop import Stop
+from lpbuildd.target.tests.testfixtures import SudoUmount
+
+
+class TestStop(TestCase):
+
+    def test_succeeds(self):
+        self.useFixture(EnvironmentVariable("HOME", "/expected/home"))
+        processes_fixture = self.useFixture(FakeProcesses())
+        processes_fixture.add(SudoUmount(), name="sudo")
+        fs_fixture = self.useFixture(FakeFilesystem())
+        fs_fixture.add("/proc")
+        os.mkdir("/proc")
+        with open("/proc/mounts", "w") as mounts_file:
+            mounts_file.write(
+                "none {chroot}/proc proc rw,relatime 0 0".format(
+                    chroot="/expected/home/build-1/chroot-autobuild"))
+        args = ["--backend=chroot", "--series=xenial", "--arch=amd64", "1"]
+        Stop(args=args).run()
+
+        # Tested in more detail in lpbuildd.target.tests.test_chroot.
+        self.assertIn(
+            ["sudo", "umount", "/expected/home/build-1/chroot-autobuild/proc"],
+            [proc._args["args"] for proc in processes_fixture.procs])

=== added file 'lpbuildd/target/tests/testfixtures.py'
--- lpbuildd/target/tests/testfixtures.py	1970-01-01 00:00:00 +0000
+++ lpbuildd/target/tests/testfixtures.py	2017-08-04 12:08:56 +0000
@@ -0,0 +1,38 @@
+# Copyright 2017 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+import argparse
+
+
+class SudoUmount:
+
+    name = "sudo"
+
+    def __init__(self, delays=None):
+        self.delays = delays or {}
+
+    def __call__(self, proc_args):
+        parser = argparse.ArgumentParser()
+        parser.add_argument("command", choices=["umount"])
+        parser.add_argument("mount_path")
+        args = parser.parse_args(proc_args["args"][1:])
+        if self.delays.get(args.mount_path, 0) > 0:
+            self.delays[args.mount_path] -= 1
+            return {'returncode': 1}
+        with open("/proc/mounts") as mounts_file:
+            mounts = mounts_file.readlines()
+        to_remove = None
+        for i, mount in reversed(list(enumerate(mounts))):
+            if mount.split()[1] == args.mount_path:
+                to_remove = i
+                break
+        if to_remove is None:
+            return {'returncode': 1}
+        else:
+            del mounts[to_remove]
+            with open("/proc/mounts", "w") as mounts_file:
+                for mount in mounts:
+                    mounts_file.write(mount)
+            return {}

=== modified file 'lpbuildd/tests/test_binarypackage.py'
--- lpbuildd/tests/test_binarypackage.py	2017-08-04 12:08:56 +0000
+++ lpbuildd/tests/test_binarypackage.py	2017-08-04 12:08:56 +0000
@@ -159,6 +159,7 @@
         self.assertState(
             BinaryPackageBuildState.UMOUNT,
             ['sharepath/slavebin/umount-chroot', 'umount-chroot',
+             '--backend=chroot', '--series=warty', '--arch=i386',
              self.buildid], final=True)
 
     def test_iterate(self):
@@ -294,6 +295,7 @@
         self.assertState(
             BinaryPackageBuildState.UMOUNT,
             ['sharepath/slavebin/umount-chroot', 'umount-chroot',
+             '--backend=chroot', '--series=warty', '--arch=i386',
              self.buildid], final=True)
 
     def test_abort_between_subprocesses(self):

=== modified file 'lpbuildd/tests/test_debian.py'
--- lpbuildd/tests/test_debian.py	2017-08-04 12:08:56 +0000
+++ lpbuildd/tests/test_debian.py	2017-08-04 12:08:56 +0000
@@ -117,7 +117,9 @@
         self.buildmanager.iterate(0)
         self.assertEqual(DebianBuildState.MOUNT, self.getState())
         self.assertEqual(
-            (['sharepath/slavebin/mount-chroot', 'mount-chroot', self.buildid],
+            (['sharepath/slavebin/mount-chroot', 'mount-chroot',
+              '--backend=chroot', '--series=xenial', '--arch=amd64',
+              self.buildid],
              None),
             self.buildmanager.commands[-1])
         self.assertEqual(
@@ -169,6 +171,7 @@
         self.assertEqual(DebianBuildState.UMOUNT, self.getState())
         self.assertEqual(
             (['sharepath/slavebin/umount-chroot', 'umount-chroot',
+              '--backend=chroot', '--series=xenial', '--arch=amd64',
               self.buildid],
              None),
             self.buildmanager.commands[-1])
@@ -222,7 +225,9 @@
         self.buildmanager.iterate(0)
         self.assertEqual(DebianBuildState.MOUNT, self.getState())
         self.assertEqual(
-            (['sharepath/slavebin/mount-chroot', 'mount-chroot', self.buildid],
+            (['sharepath/slavebin/mount-chroot', 'mount-chroot',
+              '--backend=chroot', '--series=xenial', '--arch=amd64',
+              self.buildid],
              None),
             self.buildmanager.commands[-1])
         self.assertEqual(
@@ -285,6 +290,7 @@
         self.assertEqual(DebianBuildState.UMOUNT, self.getState())
         self.assertEqual(
             (['sharepath/slavebin/umount-chroot', 'umount-chroot',
+              '--backend=chroot', '--series=xenial', '--arch=amd64',
               self.buildid],
              None),
             self.buildmanager.commands[-1])

=== modified file 'lpbuildd/tests/test_livefs.py'
--- lpbuildd/tests/test_livefs.py	2015-05-11 05:55:24 +0000
+++ lpbuildd/tests/test_livefs.py	2017-08-04 12:08:56 +0000
@@ -114,7 +114,10 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            "sharepath/slavebin/umount-chroot", "umount-chroot", self.buildid]
+            "sharepath/slavebin/umount-chroot", "umount-chroot",
+            "--backend=chroot", "--series=saucy", "--arch=i386",
+            self.buildid,
+            ]
         self.assertEqual(LiveFilesystemBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
         self.assertEqual(

=== modified file 'lpbuildd/tests/test_snap.py'
--- lpbuildd/tests/test_snap.py	2017-07-28 13:57:47 +0000
+++ lpbuildd/tests/test_snap.py	2017-08-04 12:08:56 +0000
@@ -124,7 +124,10 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            "sharepath/slavebin/umount-chroot", "umount-chroot", self.buildid]
+            "sharepath/slavebin/umount-chroot", "umount-chroot",
+            "--backend=chroot", "--series=xenial", "--arch=i386",
+            self.buildid,
+            ]
         self.assertEqual(SnapBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
         self.assertEqual(
@@ -168,7 +171,10 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            "sharepath/slavebin/umount-chroot", "umount-chroot", self.buildid]
+            "sharepath/slavebin/umount-chroot", "umount-chroot",
+            "--backend=chroot", "--series=xenial", "--arch=i386",
+            self.buildid,
+            ]
         self.assertEqual(SnapBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
         self.assertEqual(

=== modified file 'lpbuildd/tests/test_sourcepackagerecipe.py'
--- lpbuildd/tests/test_sourcepackagerecipe.py	2017-07-28 13:57:47 +0000
+++ lpbuildd/tests/test_sourcepackagerecipe.py	2017-08-04 12:08:56 +0000
@@ -141,7 +141,9 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=maverick', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(SourcePackageRecipeBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
@@ -179,7 +181,9 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid,
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=maverick', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(SourcePackageRecipeBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
@@ -214,7 +218,9 @@
         # Control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid,
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=maverick', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(SourcePackageRecipeBuildState.UMOUNT, self.getState())
         self.assertEqual(expected_command, self.buildmanager.commands[-1])

=== modified file 'lpbuildd/tests/test_translationtemplatesbuildmanager.py'
--- lpbuildd/tests/test_translationtemplatesbuildmanager.py	2017-07-28 13:57:47 +0000
+++ lpbuildd/tests/test_translationtemplatesbuildmanager.py	2017-08-04 12:08:56 +0000
@@ -119,7 +119,9 @@
         # The control returns to the DebianBuildManager in the UMOUNT state.
         self.buildmanager.iterateReap(self.getState(), 0)
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid,
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=xenial', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(
             TranslationTemplatesBuildState.UMOUNT, self.getState())
@@ -144,7 +146,9 @@
         self.assertEqual(
             TranslationTemplatesBuildState.UMOUNT, self.getState())
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid,
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=xenial', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
         self.assertEqual(
@@ -180,7 +184,9 @@
         self.assertEqual(
             TranslationTemplatesBuildState.UMOUNT, self.getState())
         expected_command = [
-            'sharepath/slavebin/umount-chroot', 'umount-chroot', self.buildid
+            'sharepath/slavebin/umount-chroot', 'umount-chroot',
+            '--backend=chroot', '--series=xenial', '--arch=i386',
+            self.buildid,
             ]
         self.assertEqual(expected_command, self.buildmanager.commands[-1])
         self.assertEqual(