← Back to team overview

yellow team mailing list archive

[Merge] lp:~frankban/lpsetup/bug-1018736-initlxc-command into lp:lpsetup

 

Francesco Banconi has proposed merging lp:~frankban/lpsetup/bug-1018736-initlxc-command into lp:lpsetup.

Requested reviews:
  Yellow Squad (yellow)
Related bugs:
  Bug #1018736 in lpsetup: "lpsetup: initlxc command"
  https://bugs.launchpad.net/lpsetup/+bug/1018736

For more details, see:
https://code.launchpad.net/~frankban/lpsetup/bug-1018736-initlxc-command/+merge/112740

== Changes ==

Implemented initlxc.

initlxc now takes a --stop-lxc argument: this flag is also activated by lxc-install --testing

Updated lxcinstall:
  - use initlxc steps
  - subclass initlxc

Updated relevant tests.

Bumped version up: initlxc command.
-- 
https://code.launchpad.net/~frankban/lpsetup/bug-1018736-initlxc-command/+merge/112740
Your team Yellow Squad is requested to review the proposed merge of lp:~frankban/lpsetup/bug-1018736-initlxc-command into lp:lpsetup.
=== modified file 'lpsetup/__init__.py'
--- lpsetup/__init__.py	2012-05-15 14:58:14 +0000
+++ lpsetup/__init__.py	2012-06-29 10:21:18 +0000
@@ -9,7 +9,7 @@
     'get_version',
     ]
 
-VERSION = (0, 2, 1)
+VERSION = (0, 2, 2)
 
 
 def get_version():

=== modified file 'lpsetup/cli.py'
--- lpsetup/cli.py	2012-06-26 17:00:54 +0000
+++ lpsetup/cli.py	2012-06-29 10:21:18 +0000
@@ -19,15 +19,18 @@
     branch,
     get,
     inithost,
+    initlxc,
     install,
     lxcinstall,
     update,
     version,
     )
 
+
 subcommands = [
     ('install', install.SubCommand),
     ('inithost', inithost.SubCommand),
+    ('initlxc', initlxc.SubCommand),
     ('get', get.SubCommand),
     ('update', update.SubCommand),
     ('lxc-install', lxcinstall.SubCommand),
@@ -40,8 +43,8 @@
     if args is None:
         args = sys.argv[1:]
     parser = argparser.ArgumentParser(description=description)
-    for subcommand, callable in subcommands:
-        parser.register_subcommand(subcommand, callable)
+    for name, klass in subcommands:
+        parser.register_subcommand(name, klass)
     try:
         args = parser.parse_args(args)
     except SystemExit as err:

=== modified file 'lpsetup/handlers.py'
--- lpsetup/handlers.py	2012-06-27 08:44:32 +0000
+++ lpsetup/handlers.py	2012-06-29 10:21:18 +0000
@@ -255,8 +255,9 @@
     """
     if getattr(namespace, 'testing', False):
         namespace.create_scripts = True
+        namespace.feed_random = True
         namespace.install_subunit = True
-        namespace.feed_random = True
+        namespace.stop_lxc = True
 
 
 def handle_branch_creation(namespace):

=== modified file 'lpsetup/subcommands/inithost.py'
--- lpsetup/subcommands/inithost.py	2012-06-27 09:10:56 +0000
+++ lpsetup/subcommands/inithost.py	2012-06-29 10:21:18 +0000
@@ -2,7 +2,7 @@
 # Copyright 2012 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""hostinit subcommand: prepare a host machine to run Launchpad."""
+"""inithost subcommand: prepare a host machine to run Launchpad."""
 
 __metaclass__ = type
 __all__ = [

=== added file 'lpsetup/subcommands/initlxc.py'
--- lpsetup/subcommands/initlxc.py	1970-01-01 00:00:00 +0000
+++ lpsetup/subcommands/initlxc.py	2012-06-29 10:21:18 +0000
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""initlxc subcommand: prepare an LXC container to run Launchpad."""
+
+__metaclass__ = type
+__all__ = [
+    'create_lxc',
+    'initialize_lxc',
+    'SubCommand',
+    'setup_lxc',
+    'start_lxc',
+    'stop_lxc',
+    'wait_for_lxc',
+    ]
+
+import os
+import shutil
+import subprocess
+
+from shelltoolbox import (
+    apt_get_install,
+    file_append,
+    mkdirs,
+    )
+
+from lpsetup import exceptions
+from lpsetup.settings import (
+    BASE_PACKAGES,
+    LPSETUP_PPA,
+    LXC_CONFIG_TEMPLATE,
+    LXC_GUEST_ARCH,
+    LXC_GUEST_CHOICES,
+    LXC_GUEST_OS,
+    LXC_NAME,
+    LXC_OPTIONS,
+    LXC_PACKAGES,
+    )
+from lpsetup.subcommands import inithost
+from lpsetup.utils import (
+    call,
+    get_container_path,
+    get_lxc_gateway,
+    lxc_stopped,
+    render_to_file,
+    retry,
+    sshlxc as ssh,
+    this_command,
+    )
+
+
+def create_lxc(lxc_name, lxc_arch, lxc_os, user, install_subunit=False):
+    """Create the LXC named `lxc_name` sharing `user` home directory.
+
+    The container will be used as development environment or as base template
+    for parallel testing using ephemeral instances.
+    """
+    # Install necessary deb packages.
+    packages = list(LXC_PACKAGES)
+    if install_subunit:
+        packages.append('subunit')
+    apt_get_install(*packages, caller=call)
+    # XXX 2012-02-02 gmb bug=925024:
+    #     These calls need to be removed once the lxc vs. apparmor bug
+    #     is resolved, since having apparmor enabled for lxc is very
+    #     much a Good Thing.
+    # Disable the apparmor profiles for lxc so that we don't have
+    # problems installing postgres.
+    subprocess.call([
+        'ln', '-s',
+        '/etc/apparmor.d/usr.bin.lxc-start', '/etc/apparmor.d/disable/'])
+    subprocess.call([
+        'apparmor_parser', '-R', '/etc/apparmor.d/usr.bin.lxc-start'])
+    # Container configuration template.
+    lxc_gateway = get_lxc_gateway()
+    if lxc_gateway is None:
+        raise exceptions.ExecutionError(
+            'Error: LXC bridge interface not found.')
+    content = LXC_OPTIONS.format(interface=lxc_gateway)
+    with open(LXC_CONFIG_TEMPLATE, 'w') as f:
+        f.write(content)
+    # Creating container.
+    call(
+        'lxc-create',
+        '-t', 'ubuntu',
+        '-n', lxc_name,
+        '-f', LXC_CONFIG_TEMPLATE,
+        '--',
+        '-r {os} -a {arch} -b {user}'.format(
+            os=lxc_os, arch=lxc_arch, user=user),
+        )
+    # Set up root ssh key.
+    user_authorized_keys = os.path.expanduser(
+        '~' + user + '/.ssh/authorized_keys')
+    dst = get_container_path(lxc_name, '/root/.ssh/')
+    mkdirs(dst)
+    shutil.copy(user_authorized_keys, dst)
+    if lxc_os == 'lucid':
+        # XXX 2012-04-18 frankban bug=974584:
+        # Add a line to the container's fstab to be able to create semaphores
+        # in lxc. This workaround needs to be removed once the lxc bug is
+        # resolved for lucid containers too.
+        file_append(
+            '/var/lib/lxc/{0}/fstab'.format(lxc_name),
+            'none dev/shm tmpfs defaults 0 0\n')
+
+
+def start_lxc(lxc_name):
+    """Start the lxc instance named `lxc_name`."""
+    call('lxc-start', '-n', lxc_name, '-d')
+
+
+def wait_for_lxc(lxc_name, ssh_key_path):
+    """Try to ssh into the LXC container named `lxc_name`."""
+    retry_ssh = retry(subprocess.CalledProcessError)(ssh)
+    retry_ssh(lxc_name, 'true', key=ssh_key_path)
+
+
+def initialize_lxc(lxc_name, ssh_key_path, lxc_os):
+    """Initialize LXC container."""
+    base_packages = list(BASE_PACKAGES) + ['python-software-properties']
+    ssh(lxc_name,
+        'DEBIAN_FRONTEND=noninteractive '
+        'apt-get install -y ' + ' '.join(base_packages),
+        key=ssh_key_path)
+    args = {
+        'assume_yes': '' if lxc_os == 'lucid' else '-y',
+        'repository': LPSETUP_PPA,
+        }
+    ssh(lxc_name,
+        'apt-add-repository {assume_yes} {repository}'.format(**args),
+        key=ssh_key_path)
+    ssh(lxc_name, 'apt-get clean && apt-get update', key=ssh_key_path)
+    ssh(lxc_name,
+        'DEBIAN_FRONTEND=noninteractive '
+        'apt-get upgrade -y && apt-get install -y lpsetup',
+        key=ssh_key_path)
+    # XXX benji 2012-03-19 bug=959352: this is so graphviz will work in an
+    # ephemeral container
+    ssh(lxc_name, 'mkdir -p /rootfs/usr/lib', key=ssh_key_path)
+    ssh(lxc_name,
+        'ln -s /usr/lib/graphviz /rootfs/usr/lib/graphviz',
+        key=ssh_key_path)
+    # XXX gary 2012-06-26 bug=1014916: this fixes a bug in Lucid LXC
+    # containers.
+    if lxc_os == 'lucid':
+        # Change /var/lib/lxc/lptests/rootfs/etc/init/networking.conf to not
+        # wait for udev (that is, use start on (local-filesystems)).
+        udevtrigger = get_container_path(
+            lxc_name, '/etc/init/udevtrigger.conf')
+        call('mv', udevtrigger, udevtrigger + '.orig')
+        networking = get_container_path(lxc_name, '/etc/init/networking.conf')
+        call('mv', networking, networking + '.orig')
+        render_to_file('networking.conf', {}, networking)
+
+
+def setup_lxc(lxc_name, ssh_key_path, user, home_dir):
+    """Prepare the Launchpad environment inside an LXC."""
+    # Use ssh to call this script from inside the container.
+    args = ['inithost', '-u', user, '-s', 'setup_apt']
+    cmd = this_command(home_dir, args)
+    ssh(lxc_name, cmd, key=ssh_key_path)
+
+
+def stop_lxc(lxc_name, ssh_key_path):
+    """Stop the lxc instance named `lxc_name`."""
+    ssh(lxc_name, 'poweroff', key=ssh_key_path)
+    if not lxc_stopped(lxc_name):
+        subprocess.call(['lxc-stop', '-n', lxc_name])
+
+
+class SubCommand(inithost.SubCommand):
+    """Prepare an LXC container to run Launchpad."""
+
+    create_lxc_step = (create_lxc,
+        'lxc_name', 'lxc_arch', 'lxc_os', 'user')
+    start_lxc_step = (start_lxc,
+        'lxc_name')
+    wait_for_lxc_step = (wait_for_lxc,
+        'lxc_name', 'ssh_key_path')
+    initialize_lxc_step = (initialize_lxc,
+        'lxc_name', 'ssh_key_path', 'lxc_os')
+    setup_lxc_step = (setup_lxc,
+        'lxc_name', 'ssh_key_path', 'user', 'home_dir')
+    stop_lxc_step = (stop_lxc,
+        'lxc_name', 'ssh_key_path')
+
+    steps = (
+        inithost.SubCommand.initialize_step,
+        create_lxc_step,
+        start_lxc_step,
+        wait_for_lxc_step,
+        initialize_lxc_step,
+        setup_lxc_step,
+        stop_lxc_step,
+        )
+
+    help = __doc__
+    needs_root = True
+
+    def call_stop_lxc(self, namespace, step, args):
+        """Run the `stop_lxc` step only if the related flag is set."""
+        if namespace.stop_lxc:
+            return step(*args)
+
+    def add_arguments(self, parser):
+        super(SubCommand, self).add_arguments(parser)
+        # Add LXC related arguments.
+        parser.add_argument(
+            'lxc_name', nargs='?', default=LXC_NAME,
+            help='The LXC container name to setup. '
+                 '[DEFAULT={0}]'.format(LXC_NAME))
+        parser.add_argument(
+            '-A', '--lxc-arch', default=LXC_GUEST_ARCH,
+            help='The LXC container architecture. '
+                 '[DEFAULT={0}]'.format(LXC_GUEST_ARCH))
+        parser.add_argument(
+            '-r', '--lxc-os', default=LXC_GUEST_OS,
+            choices=LXC_GUEST_CHOICES,
+            help='The LXC container distro codename. '
+                 '[DEFAULT={0}]'.format(LXC_GUEST_OS))
+        parser.add_argument(
+            '--stop-lxc', action='store_true',
+            help='Shut down the LXC container at the end of the process.')

=== modified file 'lpsetup/subcommands/lxcinstall.py'
--- lpsetup/subcommands/lxcinstall.py	2012-06-27 19:01:08 +0000
+++ lpsetup/subcommands/lxcinstall.py	2012-06-29 10:21:18 +0000
@@ -6,58 +6,37 @@
 
 __metaclass__ = type
 __all__ = [
-    'create_lxc',
     'create_scripts',
-    'initialize_lxc',
     'SubCommand',
-    'setup_launchpad_lxc',
-    'start_lxc',
-    'stop_lxc',
+    'setup_lxc',
     ]
 
 import os
-import shutil
-import subprocess
 
-from shelltoolbox import (
-    apt_get_install,
-    file_append,
-    mkdirs,
+from lpsetup.handlers import (
+    handle_directories,
+    handle_testing,
     )
-
-from lpsetup import exceptions
-from lpsetup.handlers import handle_testing
 from lpsetup.settings import (
-    BASE_PACKAGES,
-    LPSETUP_PPA,
-    LXC_CONFIG_TEMPLATE,
-    LXC_GUEST_ARCH,
-    LXC_GUEST_CHOICES,
-    LXC_GUEST_OS,
+    CHECKOUT_DIR,
+    DEPENDENCIES_DIR,
     LXC_IP_COMMAND,
-    LXC_NAME,
-    LXC_OPTIONS,
-    LXC_PACKAGES,
     SCRIPTS,
     )
 from lpsetup.subcommands import (
     get,
     inithost,
+    initlxc,
     install,
     )
 from lpsetup.utils import (
-    call,
-    get_container_path,
-    get_lxc_gateway,
-    lxc_stopped,
     render_to_file,
-    retry,
     sshlxc as ssh,
     this_command,
     )
 
 
-def create_scripts(user, lxc_name, ssh_key_path):
+def create_scripts(lxc_name, ssh_key_path, user):
     """Create scripts to update the Launchpad environment and run tests."""
     context = {
         'lxcip': LXC_IP_COMMAND[0],
@@ -88,113 +67,7 @@
         f.write('0\n')
 
 
-def create_lxc(user, lxc_name, lxc_arch, lxc_os, install_subunit):
-    """Create the LXC named `lxc_name` sharing `user` home directory.
-
-    The container will be used as development environment or as base template
-    for parallel testing using ephemeral instances.
-    """
-    # Install necessary deb packages.
-    packages = list(LXC_PACKAGES)
-    if install_subunit:
-        packages.append('subunit')
-    apt_get_install(*packages, caller=call)
-    # XXX 2012-02-02 gmb bug=925024:
-    #     These calls need to be removed once the lxc vs. apparmor bug
-    #     is resolved, since having apparmor enabled for lxc is very
-    #     much a Good Thing.
-    # Disable the apparmor profiles for lxc so that we don't have
-    # problems installing postgres.
-    subprocess.call([
-        'ln', '-s',
-        '/etc/apparmor.d/usr.bin.lxc-start', '/etc/apparmor.d/disable/'])
-    subprocess.call([
-        'apparmor_parser', '-R', '/etc/apparmor.d/usr.bin.lxc-start'])
-    # Container configuration template.
-    lxc_gateway = get_lxc_gateway()
-    if lxc_gateway is None:
-        raise exceptions.ExecutionError(
-            'Error: LXC bridge interface not found.')
-    content = LXC_OPTIONS.format(interface=lxc_gateway)
-    with open(LXC_CONFIG_TEMPLATE, 'w') as f:
-        f.write(content)
-    # Creating container.
-    call(
-        'lxc-create',
-        '-t', 'ubuntu',
-        '-n', lxc_name,
-        '-f', LXC_CONFIG_TEMPLATE,
-        '--',
-        '-r {os} -a {arch} -b {user}'.format(
-            os=lxc_os, arch=lxc_arch, user=user),
-        )
-    # Set up root ssh key.
-    user_authorized_keys = os.path.expanduser(
-        '~' + user + '/.ssh/authorized_keys')
-    dst = get_container_path(lxc_name, '/root/.ssh/')
-    mkdirs(dst)
-    shutil.copy(user_authorized_keys, dst)
-    if lxc_os == 'lucid':
-        # XXX 2012-04-18 frankban bug=974584:
-        # Add a line to the container's fstab to be able to create semaphores
-        # in lxc. This workaround needs to be removed once the lxc bug is
-        # resolved for lucid containers too.
-        file_append(
-            '/var/lib/lxc/{0}/fstab'.format(lxc_name),
-            'none dev/shm tmpfs defaults 0 0\n')
-
-
-def start_lxc(lxc_name):
-    """Start the lxc instance named `lxc_name`."""
-    call('lxc-start', '-n', lxc_name, '-d')
-
-
-def wait_for_lxc(lxc_name, ssh_key_path):
-    """Try to ssh into the LXC container named `lxc_name`."""
-    retry_ssh = retry(subprocess.CalledProcessError)(ssh)
-    retry_ssh(lxc_name, 'true', key=ssh_key_path)
-
-
-def initialize_lxc(lxc_name, ssh_key_path, lxc_os):
-    """Initialize LXC container."""
-    base_packages = list(BASE_PACKAGES) + ['python-software-properties']
-    ssh(lxc_name,
-        'DEBIAN_FRONTEND=noninteractive '
-        'apt-get install -y ' + ' '.join(base_packages),
-        key=ssh_key_path)
-    args = {
-        'assume_yes': '' if lxc_os == 'lucid' else '-y',
-        'repository': LPSETUP_PPA,
-        }
-    ssh(lxc_name,
-        'apt-add-repository {assume_yes} {repository}'.format(**args),
-        key=ssh_key_path)
-    ssh(lxc_name, 'apt-get clean && apt-get update', key=ssh_key_path)
-    ssh(lxc_name,
-        'DEBIAN_FRONTEND=noninteractive '
-        'apt-get upgrade -y && apt-get install -y lpsetup',
-        key=ssh_key_path)
-    # XXX benji 2012-03-19 bug=959352: this is so graphviz will work in an
-    # ephemeral container
-    ssh(lxc_name, 'mkdir -p /rootfs/usr/lib', key=ssh_key_path)
-    ssh(lxc_name,
-        'ln -s /usr/lib/graphviz /rootfs/usr/lib/graphviz',
-        key=ssh_key_path)
-    # XXX gary 2012-06-26 bug=1014916: this fixes a bug in Lucid LXC
-    # containers.
-    if lxc_os == 'lucid':
-        # Change /var/lib/lxc/lptests/rootfs/etc/init/networking.conf to not
-        # wait for udev (that is, use start on (local-filesystems)).
-        udevtrigger = get_container_path(
-            lxc_name, '/etc/init/udevtrigger.conf')
-        call('mv', udevtrigger, udevtrigger + '.orig')
-        networking = get_container_path(lxc_name, '/etc/init/networking.conf')
-        call('mv', networking, networking + '.orig')
-        render_to_file('networking.conf', {}, networking)
-
-
-def setup_launchpad_lxc(
-    user, dependencies_dir, directory, valid_ssh_keys, ssh_key_path, lxc_name):
+def setup_lxc(lxc_name, ssh_key_path, user, dependencies_dir, directory):
     """Set up the Launchpad environment inside an LXC."""
     # Use ssh to call this script from inside the container.
     args = [
@@ -205,14 +78,7 @@
     ssh(lxc_name, cmd, key=ssh_key_path)
 
 
-def stop_lxc(lxc_name, ssh_key_path):
-    """Stop the lxc instance named `lxc_name`."""
-    ssh(lxc_name, 'poweroff', key=ssh_key_path)
-    if not lxc_stopped(lxc_name):
-        subprocess.call(['lxc-stop', '-n', lxc_name])
-
-
-class SubCommand(install.SubCommand):
+class SubCommand(initlxc.SubCommand):
     """Install the Launchpad environment inside an LXC."""
 
     steps = (
@@ -220,26 +86,20 @@
         get.SubCommand.fetch_step,
         install.SubCommand.setup_bzr_locations_step,
         (create_scripts,
-         'user', 'lxc_name', 'ssh_key_path'),
-        (create_lxc,
-         'user', 'lxc_name', 'lxc_arch', 'lxc_os', 'install_subunit'),
-        (start_lxc,
-         'lxc_name'),
-        (wait_for_lxc,
-         'lxc_name', 'ssh_key_path'),
-        (initialize_lxc,
-         'lxc_name', 'ssh_key_path', 'lxc_os'),
-        (setup_launchpad_lxc,
-         'user', 'dependencies_dir', 'directory',
-         'valid_ssh_keys', 'ssh_key_path', 'lxc_name'),
-        (stop_lxc,
-         'lxc_name', 'ssh_key_path'),
+         'lxc_name', 'ssh_key_path', 'user'),
+        initlxc.SubCommand.create_lxc_step + ('install_subunit',),
+        initlxc.SubCommand.start_lxc_step,
+        initlxc.SubCommand.wait_for_lxc_step,
+        initlxc.SubCommand.initialize_lxc_step,
+        (setup_lxc,
+         'lxc_name', 'ssh_key_path', 'user', 'dependencies_dir', 'directory'),
+        initlxc.SubCommand.stop_lxc_step,
         )
     help = __doc__
 
     def get_handlers(self, namespace):
         handlers = super(SubCommand, self).get_handlers(namespace)
-        return handlers + (handle_testing,)
+        return handlers + (handle_directories, handle_testing)
 
     def call_create_scripts(self, namespace, step, args):
         """Run the `create_scripts` step only if the related flag is set."""
@@ -249,18 +109,18 @@
     def add_arguments(self, parser):
         super(SubCommand, self).add_arguments(parser)
         parser.add_argument(
-            '-n', '--lxc-name', default=LXC_NAME,
-            help='The LXC container name to setup. '
-                 '[DEFAULT={0}]'.format(LXC_NAME))
-        parser.add_argument(
-            '-A', '--lxc-arch', default=LXC_GUEST_ARCH,
-            help='The LXC container architecture. '
-                 '[DEFAULT={0}]'.format(LXC_GUEST_ARCH))
-        parser.add_argument(
-            '-r', '--lxc-os', default=LXC_GUEST_OS,
-            choices=LXC_GUEST_CHOICES,
-            help='The LXC container distro codename. '
-                 '[DEFAULT={0}]'.format(LXC_GUEST_OS))
+            '-d', '--dependencies-dir', default=DEPENDENCIES_DIR,
+            help='The directory of the Launchpad dependencies to be created. '
+                 'The directory must reside under the home directory of the '
+                 'given user (see -u argument). '
+                 '[DEFAULT={0}]'.format(DEPENDENCIES_DIR))
+        parser.add_argument(
+            '-c', '--directory', default=CHECKOUT_DIR,
+            help='The directory of the Launchpad repository to be created. '
+                 'The directory must reside under the home directory of the '
+                 'given user (see -u argument). '
+                 '[DEFAULT={0}]'.format(CHECKOUT_DIR))
+        # Add parallel testing related arguments.
         parser.add_argument(
             '-C', '--create-scripts', action='store_true',
             help='Create the scripts used by buildbot for parallel testing.')

=== added file 'lpsetup/tests/subcommands/test_initlxc.py'
--- lpsetup/tests/subcommands/test_initlxc.py	1970-01-01 00:00:00 +0000
+++ lpsetup/tests/subcommands/test_initlxc.py	2012-06-29 10:21:18 +0000
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# Copyright 2012 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for the initlxc sub command."""
+
+import random
+import unittest
+
+from lpsetup import (
+    handlers,
+    settings,
+    )
+from lpsetup.subcommands import initlxc
+from lpsetup.tests.subcommands import test_inithost
+from lpsetup.tests.utils import (
+    get_random_string,
+    StepsBasedSubCommandTestMixin,
+    )
+
+
+create_lxc_step = (
+    initlxc.create_lxc, ['lxc_name', 'lxc_arch', 'lxc_os', 'user'])
+start_lxc_step = (initlxc.start_lxc, ['lxc_name'])
+wait_for_lxc_step = (initlxc.wait_for_lxc, ['lxc_name', 'ssh_key_path'])
+initialize_lxc_step = (
+    initlxc.initialize_lxc, ['lxc_name', 'ssh_key_path', 'lxc_os'])
+setup_lxc_step = (
+    initlxc.setup_lxc, ['lxc_name', 'ssh_key_path', 'user', 'home_dir'])
+stop_lxc_step = (initlxc.stop_lxc, ['lxc_name', 'ssh_key_path'])
+
+
+def get_arguments():
+    inithost_arguments = test_inithost.get_arguments()
+    lxc_name = get_random_string()
+    lxc_arch = random.choice(['i386', 'amd64'])
+    lxc_os = random.choice(settings.LXC_GUEST_CHOICES)
+    return (
+        lxc_name, '-A', lxc_arch, '-r', lxc_os,
+        '--stop-lxc') + inithost_arguments
+
+
+class InithostTest(StepsBasedSubCommandTestMixin, unittest.TestCase):
+
+    sub_command_class = initlxc.SubCommand
+    expected_arguments = get_arguments()
+    expected_handlers = (
+        handlers.handle_user,
+        handlers.handle_lpuser,
+        handlers.handle_userdata,
+        handlers.handle_ssh_keys,
+        )
+    expected_steps = (
+        test_inithost.initialize_step,
+        create_lxc_step,
+        start_lxc_step,
+        wait_for_lxc_step,
+        initialize_lxc_step,
+        setup_lxc_step,
+        stop_lxc_step,
+        )
+    needs_root = True

=== modified file 'lpsetup/tests/subcommands/test_lxcinstall.py'
--- lpsetup/tests/subcommands/test_lxcinstall.py	2012-06-26 10:25:46 +0000
+++ lpsetup/tests/subcommands/test_lxcinstall.py	2012-06-29 10:21:18 +0000
@@ -4,17 +4,14 @@
 
 """Tests for the lxcinstall sub command."""
 
-import random
 import unittest
 
-from lpsetup import (
-    handlers,
-    settings,
-    )
+from lpsetup import handlers
 from lpsetup.subcommands import lxcinstall
 from lpsetup.tests.subcommands import (
     test_get,
     test_inithost,
+    test_initlxc,
     test_install,
     )
 from lpsetup.tests.utils import (
@@ -24,26 +21,19 @@
 
 
 create_scripts_step = (
-    lxcinstall.create_scripts, ['user', 'lxc_name', 'ssh_key_path'])
-create_lxc_step = (
-    lxcinstall.create_lxc, ['user', 'lxc_name', 'lxc_arch', 'lxc_os',
-    'install_subunit'])
-start_lxc_step = (lxcinstall.start_lxc, ['lxc_name'])
-wait_for_lxc_step = (lxcinstall.wait_for_lxc, ['lxc_name', 'ssh_key_path'])
-initialize_lxc_step = (
-    lxcinstall.initialize_lxc, ['lxc_name', 'ssh_key_path', 'lxc_os'])
-setup_launchpad_lxc_step = (
-    lxcinstall.setup_launchpad_lxc, ['user', 'dependencies_dir', 'directory',
-    'valid_ssh_keys', 'ssh_key_path', 'lxc_name'])
-stop_lxc_step = (lxcinstall.stop_lxc, ['lxc_name', 'ssh_key_path'])
+    lxcinstall.create_scripts, ['lxc_name', 'ssh_key_path', 'user'])
+create_lxc_callable, create_lxc_args = test_initlxc.create_lxc_step
+create_lxc_step = (create_lxc_callable, create_lxc_args + ['install_subunit'])
+setup_lxc_step = (
+    lxcinstall.setup_lxc, ['lxc_name', 'ssh_key_path', 'user',
+    'dependencies_dir', 'directory'])
 
 
 def get_arguments():
-    lxc_name = get_random_string()
-    lxc_arch = random.choice(['i386', 'amd64'])
-    lxc_os = random.choice(settings.LXC_GUEST_CHOICES)
-    return test_inithost.get_arguments() + (
-        '-n', lxc_name, '-A', lxc_arch, '-r', lxc_os,
+    dependencies_dir = '~/' + get_random_string()
+    directory = '~/' + get_random_string()
+    return test_initlxc.get_arguments() + (
+        '-d', dependencies_dir, '-c', directory,
         '--create-scripts', '--install-subunit', '--testing'
         )
 
@@ -66,10 +56,10 @@
         test_install.setup_bzr_locations_step,
         create_scripts_step,
         create_lxc_step,
-        start_lxc_step,
-        wait_for_lxc_step,
-        initialize_lxc_step,
-        setup_launchpad_lxc_step,
-        stop_lxc_step,
+        test_initlxc.start_lxc_step,
+        test_initlxc.wait_for_lxc_step,
+        test_initlxc.initialize_lxc_step,
+        setup_lxc_step,
+        test_initlxc.stop_lxc_step,
         )
     needs_root = True

=== modified file 'lpsetup/tests/test_handlers.py'
--- lpsetup/tests/test_handlers.py	2012-05-22 09:58:51 +0000
+++ lpsetup/tests/test_handlers.py	2012-06-29 10:21:18 +0000
@@ -197,8 +197,9 @@
 
     ctx = {
         'create_scripts': True,
+        'feed_random': False,
         'install_subunit': False,
-        'feed_random': False,
+        'stop_lxc': False,
         }
 
     def test_true(self):