Add documentation for parallel-debian

This commit is contained in:
Colin Walters 2011-10-17 09:40:12 -04:00
parent d32dd476f7
commit 8020f444cf
6 changed files with 366 additions and 38 deletions

View File

@ -1,38 +0,0 @@
Experimenting with multiple roots
---------------------------------
$ qemu-img create debian.img 600M
$ mkfs.ext2 debian.img
$ mkdir debian-mnt
$ mount -o loop debian.img debian-mnt
$ debootstrap wheezy debian-mnt
$ chroot debian-mnt
$ apt-get install linux-image-3.0.0
Control-d
$ cp debian-mnt/boot/vmlinuz* .
$ cp debian-mnt/boot/initrd* .
$ umount debian-mnt
You now have a Debian disk image in debian.img and a kernel+initrd that are bootable with qemu.
Modifying the image
-------------------
The first thing I did was re-mount the image, and move almost everythig
(/boot, /var, /etc), except lost+found to a new directory "r0".
Then I started hacking on the initrd, making understand how to chroot
to "r0".
This means that after booting, every process would be in /r0 -
including any hacktree process. Assuming objects live in say
/objects, we need some way for hacktree to switch things. I think
just chroot breakout would work. This has the advantage the daemon
can continue to use libraries from the active host.
Note there is a self-reference here (as is present in Debian/Fedora
etc.) - the update system would at present be shipped with the system
itself. Should they be independent? That has advantages and
disadvantages. I think we should just try really really hard to avoid
breaking hacktree in updates.

View File

@ -0,0 +1,148 @@
From 0e22e86348bb356e69ed28a58e959b7fab7c43cc Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Sun, 16 Oct 2011 14:26:40 -0400
Subject: [PATCH] Add support for subroot= option
Passing this option causes the initrd to chroot() into a subdirectory of /.
This is useful for parallel installing multiple systems in one filesystem.
This relies on a patched switch_root from util-linux.
---
init | 32 +++++++++++++++++++++-----------
scripts/init-bottom/udev | 5 ++---
scripts/local | 6 ++++--
3 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/init b/init
index 445c354..3ff2750 100755
--- a/init
+++ b/init
@@ -49,6 +49,8 @@ export init=/sbin/init
export quiet=n
export readonly=y
export rootmnt=/root
+export subroot=
+export rootsubmnt=
export debug=
export panic=
export blacklist=
@@ -68,6 +70,10 @@ for x in $(cat /proc/cmdline); do
init=*)
init=${x#init=}
;;
+ subroot=*)
+ subroot=${x#subroot=}
+ rootsubmnt=${x#subroot=}
+ ;;
root=*)
ROOT=${x#root=}
case $ROOT in
@@ -218,14 +224,18 @@ maybe_break mountroot
mountroot
log_end_msg
+if test -n "${rootsubmnt}"; then
+ rootsubmnt=${rootmnt}/${rootsubmnt}
+fi
+
maybe_break bottom
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom"
run_scripts /scripts/init-bottom
[ "$quiet" != "y" ] && log_end_msg
# Preserve information on old systems without /run on the rootfs
-if [ -d ${rootmnt}/run ]; then
- mount -n -o move /run ${rootmnt}/run
+if [ -d ${rootsubmnt}/run ]; then
+ mount -n -o move /run ${rootsubmnt}/run
else
# The initramfs udev database must be migrated:
if [ -d /run/udev ] && [ ! -d /dev/.udev ]; then
@@ -239,27 +249,27 @@ else
fi
# Move virtual filesystems over to the real filesystem
-mount -n -o move /sys ${rootmnt}/sys
-mount -n -o move /proc ${rootmnt}/proc
+mount -n -o move /sys ${rootsubmnt}/sys
+mount -n -o move /proc ${rootsubmnt}/proc
validate_init() {
checktarget="${1}"
# Work around absolute symlinks
- if [ -d "${rootmnt}" ] && [ -h "${rootmnt}${checktarget}" ]; then
- case $(readlink "${rootmnt}${checktarget}") in /*)
- checktarget="$(chroot ${rootmnt} readlink ${checktarget})"
+ if [ -d "${rootsubmnt}" ] && [ -h "${rootsubmnt}${checktarget}" ]; then
+ case $(readlink "${rootsubmnt}${checktarget}") in /*)
+ checktarget="$(chroot ${rootsubmnt} readlink ${checktarget})"
;;
esac
fi
# Make sure the specified init can be executed
- if [ ! -x "${rootmnt}${checktarget}" ]; then
+ if [ ! -x "${rootsubmnt}${checktarget}" ]; then
return 1
fi
# Upstart uses /etc/init as configuration directory :-/
- if [ -d "${rootmnt}${checktarget}" ]; then
+ if [ -d "${rootsubmnt}${checktarget}" ]; then
return 1
fi
}
@@ -273,7 +283,7 @@ if [ -n "${init}" ]; then
fi
# Common case: /sbin/init is present
-if [ ! -x "${rootmnt}/sbin/init" ]; then
+if [ ! -x "${rootsubmnt}/sbin/init" ]; then
# ... if it's not available search for valid init
if [ -z "${init}" ] ; then
for inittest in /sbin/init /etc/init /bin/init /bin/sh; do
@@ -315,5 +325,5 @@ unset resume
unset resume_offset
# Chain to real filesystem
-exec run-init ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console
+exec switch_root --subroot ${subroot} ${rootmnt} ${init} "$@" <${rootsubmnt}/dev/console >${rootsubmnt}/dev/console
panic "Could not execute run-init."
diff --git a/scripts/init-bottom/udev b/scripts/init-bottom/udev
index 375dfab..7922d0f 100755
--- a/scripts/init-bottom/udev
+++ b/scripts/init-bottom/udev
@@ -20,9 +20,8 @@ if [ -e /etc/udev/udev.conf ]; then
fi
# move the /dev tmpfs to the rootfs
-mount -n -o move /dev ${rootmnt}${udev_root}
+mount -n -o move /dev ${rootsubmnt}${udev_root}
# create a temporary symlink to the final /dev for other initramfs scripts
nuke /dev
-ln -s ${rootmnt}${udev_root} /dev
-
+ln -s ${rootsubmnt}${udev_root} /dev
diff --git a/scripts/local b/scripts/local
index 521e69a..25b518f 100644
--- a/scripts/local
+++ b/scripts/local
@@ -101,9 +101,11 @@ mountroot()
# FIXME This has no error checking
# Mount root
if [ "${FSTYPE}" != "unknown" ]; then
- mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}
+ echo mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt}
+ mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} ${rootmnt} || echo "FAILED TO MOUNT ROOT"
else
- mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
+ echo mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt}
+ mount ${roflag} ${ROOTFLAGS} ${ROOT} ${rootmnt} || echo "FAILED TO MOUNT ROOT"
fi
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
--
1.7.6.4

View File

@ -0,0 +1,102 @@
From fa0e7df4e3d6550f0391bb3b81b2b6ac5165439d Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Sun, 16 Oct 2011 21:01:46 -0400
Subject: [PATCH] switch_root: Add --subroot option
This is useful for parallel installing multiple operating system
roots. See: http://git.gnome.org/browse/hacktree
---
sys-utils/switch_root.8 | 4 ++++
sys-utils/switch_root.c | 31 +++++++++++++++++++++----------
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/sys-utils/switch_root.8 b/sys-utils/switch_root.8
index 34ab0d0..6981852 100644
--- a/sys-utils/switch_root.8
+++ b/sys-utils/switch_root.8
@@ -27,6 +27,10 @@ process.
show help and exit
.IP "\fB\-V, \-\-version\fP"
show version number and exit
+.IP "\-\-subroot\fP"
+Instead of calling chroot into the / of the new root, instead use the
+given argument. This helps parallel install multiple operating systems in one
+root filesystem.
.SH RETURN VALUE
.B switch_root
diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c
index 2dfed71..20ae5d6 100644
--- a/sys-utils/switch_root.c
+++ b/sys-utils/switch_root.c
@@ -108,7 +108,7 @@ done:
return rc;
}
-static int switchroot(const char *newroot)
+static int switchroot(const char *newroot, const char *subroot)
{
/* Don't try to unmount the old "/", there's no way to do it. */
const char *umounts[] = { "/dev", "/proc", "/sys", NULL };
@@ -141,7 +141,7 @@ static int switchroot(const char *newroot)
return -1;
}
- if (chroot(".")) {
+ if (chroot(subroot ? subroot : ".")) {
warn("failed to change root");
return -1;
}
@@ -160,7 +160,7 @@ static int switchroot(const char *newroot)
static void usage(FILE *output)
{
- fprintf(output, "usage: %s <newrootdir> <init> <args to init>\n",
+ fprintf(output, "usage: %s [--subroot DIR] <newrootdir> <init> <args to init>\n",
program_invocation_short_name);
exit(output == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
}
@@ -175,22 +175,33 @@ static void version(void)
int main(int argc, char *argv[])
{
char *newroot, *init, **initargs;
+ char *subroot = NULL;
+ int argi;
- if (argv[1] && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
+ if (argc < 2)
+ usage(stderr);
+
+ argi = 1;
+ if ((!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
usage(stdout);
- if (argv[1] && (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-V")))
+ if ((!strcmp(argv[1], "--version") || !strcmp(argv[1], "-V")))
version();
- if (argc < 3)
+ if (argc > 3 && argv[1] && (!strcmp(argv[1], "--subroot"))) {
+ subroot = argv[2];
+ argi = 3;
+ }
+ if (argc <= argi+1) {
usage(stderr);
+ }
- newroot = argv[1];
- init = argv[2];
- initargs = &argv[2];
+ newroot = argv[argi];
+ init = argv[argi+1];
+ initargs = &argv[argi+1];
if (!*newroot || !*init)
usage(stderr);
- if (switchroot(newroot))
+ if (switchroot(newroot, subroot))
errx(EXIT_FAILURE, "failed. Sorry.");
if (access(init, X_OK))
--
1.7.6.4

View File

@ -0,0 +1,80 @@
Experimenting with multiple roots
---------------------------------
<http://wiki.debian.org/QEMU#Setting_up_a_testing.2BAC8-unstable_system>
Follow the steps for making a disk image, downloading the business
card CD, booting it in QEMU and running through the installer.
Test that the image works after installation too, before you start
modifying things below! Remember to remove the -cdrom and -boot
options from the installation QEMU command.
Modifying the image
-------------------
You now have a disk image in debian.img, and the first partition
should be ext4.
The first thing I did was mount the image, and move almost everythig
(/boot, /var, /etc), except lost+found to a new directory "r0".
$ mkdir /mnt/debian
$ modprobe nbd max_part=8
$ qemu-nbd --connect=/dev/nbd0 debian.qcow
$ mount /dev/nbd0p1 /mnt/debian/
$ cd /mnt/debian
$ mkdir r0
$ DIRS="bin boot dev etc lib lib64 media mnt opt proc root run sbin selinux srv sys tmp usr var"
$ mv $DIRS r0
Now with it still mounted, we need to move on to the next part -
modifying the initrd.
Then I started hacking on the initrd, making understand how to chroot
to "r0". I ended up with two patches - one to util-linux, and one to
the "init" script in Debian's initrd.
See:
0001-switch_root-Add-subroot-option.patch
0001-Add-support-for-subroot-option.patch
$ git clone --depth=1 git://github.com/karelzak/util-linux.git
$ cd util-linux
$ patch -p1 -i ../0001-switch_root-Add-subroot-option.patch
$ ./autogen.sh; ./configure ; make
Now you have a modified "sys-utils/switch_root" binary. Let's next
patch the initrd and rebuild it:
Make a backup:
$ mkdir initrd
$ cp /mnt/debian/boot/initrd.img-3.0.0-1-amd64{,.orig}
Unpack, and patch:
$ zcat /mnt/debian/boot/initrd.img-3.0.0-1-amd64 | (cd initrd; cpio -d -i -v)
$ (cd initrd && patch -p1 -i ../0001-Add-support-for-subroot-option.patch)
Repack:
$ (cd initrd; find | cpio -o -H newc) | gzip > /mnt/debian/boot/initrd.img-3.0.0-1-amd64.new
$ mv /mnt/debian/boot/initrd.img-3.0.0-1-amd64{.new,}
Running hacktree inside the system
----------------------------------
This means that after booting, every process would be in /r0 -
including any hacktree process. Assuming objects live in say
/objects, we need some way for hacktree to switch things. I think
just chroot breakout would work. This has the advantage the daemon
can continue to use libraries from the active host.
Note there is a self-reference here (as is present in Debian/Fedora
etc.) - the update system would at present be shipped with the system
itself. Should they be independent? That has advantages and
disadvantages. I think we should just try really really hard to avoid
breaking hacktree in updates.

View File

@ -0,0 +1,16 @@
#!/bin/sh
set -e
set -x
if test -f debian.img; then
echo debian.img already exists
exit 1
fi
qemu-img create debian.img 600M
mkfs.ext2 -q -F debian.img
mkdir -p debian-mnt
mount -o loop debian.img debian-mnt
debootstrap --arch amd64 wheezy debian-mnt
umount debian-mnt

View File

@ -0,0 +1,20 @@
#!/bin/sh
set -e
set -x
DIRS="bin boot dev etc lib lib64 media mnt opt proc root run sbin selinux srv sys tmp usr var"
if ! test -f debian.img; then
echo need debian.img
exit 1
fi
mount -o loop debian.img debian-mnt
cd debian-mnt
if ! test -d r0; then
mkdir r0
mv $DIRS r0
fi
cd ..
umount debian-mnt