Package: vmdebootstrap
Version: 0.11-1
Severity: normal
Tags: patch upstream

Dear Maintainers,

while using vmdebootstrap to create VM images for the use with
autopkgtest, I've stumbled upon the following problem:

 - I want to do integration testing, and part of that is to test the
   package with different init systems.

 - The default test is run with the default init system, systemd. That
   works fine.

 - For testing sysvinit, I run
     apt-get -y --purge --install sysvinit-core
   inside the VM, then reboot the VM.

 - After that, I would run that test again with sysvinit as the init
   system.

Problem:

vmdebootstrap appends the serial console to /etc/inittab when creating
the VM - but sysvinit is not installed, so /etc/inittab doesn't exist.
That causes it to create an empty /etc/inittab with JUST a serial
console. (And no entries that start the rcscripts etc.)

When sysvinit is then installed later on, since /etc/inittab is a
conffile, the default inittab will never be installed.

When rebooting the VM, sysvinit will then hang asking for the runlevel
to boot into on the main kernel console (since no default is defined in
the configuration).

Trivial fix that doesn't hurt /etc/inittab would be to just not modify
the file if it's not present. Doesn't help though, because then the
scenario I'm looking at (want to use sysvinit inside the VM executing
the autopkgtest tests) won't work, because autopkgtest expects a serial
console to be available for communication with the VM.

I've attached a patch that does the following:

 - if /etc/inittab exists, nothing changes

 - if /etc/inittab doesn't exist, /etc/inittab.tail is created instead,
   and an init script is installed that will update /etc/inittab
   and append the /etc/inittab.tail file once it's booted under
   sysvinit for the first time (will do nothing under systemd)

I've successfully tested it on my system.

Thanks,
Christian

For reference, the command execute to create the image (according to
recommendations from the autopkgtest package):

vmdebootstrap --verbose --serial-console --distribution=sid \
              --customize=/usr/share/autopkgtest/adt-setup-vm \
              --user=adt/adt --size=10000000000 --grub \
              --image=adt-sid.raw
From 1cebe2b91e06f66f7a046438f9f191fef3f12446 Mon Sep 17 00:00:00 2001
From: Christian Seiler <christ...@iwakd.de>
Date: Sun, 4 Oct 2015 23:16:28 +0200
Subject: [PATCH] Defer modification of /etc/inittab until sysvinit is install
 (if ever)

If vmdebootstrap creates /etc/inittab (in case sysvinit is not in the
initial package list), don't create it (because it's a conffile and
then will only contain the additions, not the default settings that are
required to make the system boot), but rather defer the modification of
/etc/inittab to an init script that's run when the system is booted
under sysvinit.
---
 vmdebootstrap | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/vmdebootstrap b/vmdebootstrap
index 67ea2c8..ef88f44 100755
--- a/vmdebootstrap
+++ b/vmdebootstrap
@@ -828,6 +828,52 @@ class VmDebootstrap(cliapp.Application):  # pylint: disable=too-many-public-meth
             serial_command = self.settings['serial-console-command']
             logging.debug('adding getty to serial console')
             inittab = os.path.join(rootdir, 'etc/inittab')
+            if not os.path.exists(inittab):
+                # sysvinit is not installed, but might be installed later
+                # install an init script that's run at boot that will
+                # make the modifications later
+                script = os.path.join(rootdir, 'etc/init.d/local-update-inittab')
+                with open(script, 'w') as f:
+                    f.write("""#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          local-update-inittab
+# Required-Start:    $remote_fs
+# Default-Start:     2 3
+# Short-Description: Update /etc/inittab
+### END INIT INFO
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+. /lib/init/vars.sh
+. /lib/lsb/init-functions
+[ -f /etc/inittab ] || exit 0
+[ -f /etc/inittab.tail ] || exit 0
+if [ "$1" = "start" ] ; then
+    cat /etc/inittab.tail >> /etc/inittab
+    rm -f /etc/inittab.tail
+    # we need to reload init to make sure it
+    # picks up the changes to /etc/inittab
+    telinit q
+fi
+if [ "$1" = "stop" ] || [ "$1" = "status" ] ; then
+    exit 0
+fi
+echo "Error: argument '$1' not supported" >&2
+exit 3
+""")
+
+                # mask the corresponding systemd service
+                service = os.path.join(rootdir, 'etc/systemd/system',
+                                       'local-update-inittab.service')
+                os.symlink('/dev/null', service)
+
+                # enable the service
+                self.runcmd(['chroot', rootdir, 'update-rc.d',
+                             'local-update-inittab', 'defaults'])
+
+                # now append the line to /etc/inittab_tail
+                # so that the init script will pick it up
+                # when first booted with sysvinit
+                inittab = os.path.join(rootdir, 'etc/inittab.tail')
+
             # to autologin, serial_command can contain '-a root'
             with open(inittab, 'a') as f:
                 f.write('\nS0:23:respawn:%s\n' % serial_command)
-- 
2.1.4

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to