summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am48
-rw-r--r--febootstrap-supermin-helper.pod105
-rwxr-xr-xfebootstrap-supermin-helper.sh132
-rw-r--r--febootstrap-to-supermin.pod193
-rwxr-xr-xfebootstrap-to-supermin.sh133
-rw-r--r--febootstrap.pod6
7 files changed, 616 insertions, 3 deletions
diff --git a/.gitignore b/.gitignore
index 24fc34d..a430f1f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,8 @@ febootstrap-run
febootstrap-install
febootstrap-minimize
febootstrap-to-initramfs
+febootstrap-to-supermin
+febootstrap-supermin-helper
install-sh
missing
stamp-h1
diff --git a/Makefile.am b/Makefile.am
index b239bbf..861b5e0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,9 @@ bin_SCRIPTS = \
febootstrap-run \
febootstrap-install \
febootstrap-minimize \
- febootstrap-to-initramfs
+ febootstrap-to-initramfs \
+ febootstrap-to-supermin \
+ febootstrap-supermin-helper
DISTCLEANFILES = $(bin_SCRIPTS)
febootstrap: febootstrap.sh
@@ -57,12 +59,26 @@ febootstrap-to-initramfs: febootstrap-to-initramfs.sh
chmod 0555 $@-t
mv $@-t $@
+febootstrap-to-supermin: febootstrap-to-supermin.sh
+ rm -f $@
+ cp $< $@-t
+ chmod 0555 $@-t
+ mv $@-t $@
+
+febootstrap-supermin-helper: febootstrap-supermin-helper.sh
+ rm -f $@
+ cp $< $@-t
+ chmod 0555 $@-t
+ mv $@-t $@
+
man_MANS = \
febootstrap.8 \
febootstrap-run.8 \
febootstrap-install.8 \
febootstrap-minimize.8 \
- febootstrap-to-initramfs.8
+ febootstrap-to-initramfs.8 \
+ febootstrap-to-supermin.8 \
+ febootstrap-supermin-helper.8
if HAVE_PERLDOC
@@ -116,6 +132,26 @@ febootstrap-to-initramfs.8: febootstrap-to-initramfs.pod
febootstrap-to-initramfs.txt: febootstrap-to-initramfs.pod
pod2text $< > $@
+febootstrap-to-supermin.8: febootstrap-to-supermin.pod
+ pod2man \
+ --section 8 \
+ -c "Virtualization Support" \
+ --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
+ $< > $@
+
+febootstrap-to-supermin.txt: febootstrap-to-supermin.pod
+ pod2text $< > $@
+
+febootstrap-supermin-helper.8: febootstrap-supermin-helper.pod
+ pod2man \
+ --section 8 \
+ -c "Virtualization Support" \
+ --release "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \
+ $< > $@
+
+febootstrap-supermin-helper.txt: febootstrap-supermin-helper.pod
+ pod2text $< > $@
+
endif
EXTRA_DIST = \
@@ -132,4 +168,10 @@ EXTRA_DIST = \
febootstrap-minimize.sh \
febootstrap-to-initramfs.8 febootstrap-to-initramfs.txt \
febootstrap-to-initramfs.pod \
- febootstrap-to-initramfs.sh
+ febootstrap-to-initramfs.sh \
+ febootstrap-to-supermin.8 febootstrap-to-supermin.txt \
+ febootstrap-to-supermin.pod \
+ febootstrap-to-supermin.sh \
+ febootstrap-supermin-helper.8 febootstrap-supermin-helper.txt \
+ febootstrap-supermin-helper.pod \
+ febootstrap-supermin-helper.sh
diff --git a/febootstrap-supermin-helper.pod b/febootstrap-supermin-helper.pod
new file mode 100644
index 0000000..d39d8bd
--- /dev/null
+++ b/febootstrap-supermin-helper.pod
@@ -0,0 +1,105 @@
+=head1 NAME
+
+febootstrap-supermin-helper - Reconstruct initramfs from supermin appliance.
+
+=head1 SYNOPSIS
+
+ febootstrap-supermin-helper supermin.img hostfiles.txt kernel initrd
+
+=head1 DESCRIPTION
+
+I<febootstrap-supermin-helper> reconstructs a bootable kernel and
+initramfs from a supermin appliance. First you should be familiar
+with L<febootstrap(8)>, L<febootstrap-to-initramfs(8)> and
+L<febootstrap-to-supermin(8)>.
+
+=head1 PARAMETERS
+
+Of the four parameters, the first two are I<input> files, and the last
+two are I<output> files.
+
+C<supermin.img> and C<hostfiles.txt> are the input files which
+describe the supermin appliance.
+
+C<kernel> and C<initrd> are the temporary output files that this
+script produces. These output files are meant to be used just for
+booting the appliance, and should be deleted straight afterwards.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--kmods file>
+
+If this option is specified, then C<file> should be a list of
+wildcards matching kernel module names, eg:
+
+ virtio*.ko
+ scsi*.ko
+ piix.ko
+
+In this case, only kernel modules matching those wildcards will be
+included in the output appliance. Note: You must resolve any
+dependencies yourself as this does not pull in dependent modules
+automatically.
+
+If this option is not specified, then every kernel module from the
+host will be included. This is safer, but can produce rather large
+appliances which need a lot more memory to boot.
+
+=back
+
+=head1 SPEED
+
+In libguestfs, on a mid-range Intel-based PC, we reconstruct the
+initramfs using this script in around 1/5th of a second (assuming a
+"hot cache" - it's rather slower when run the first time on a cold
+cache).
+
+Some tips to improve performance:
+
+=over 4
+
+=item *
+
+Use a kernel module whitelist (the C<--kmods> option), and only
+list the kernel modules you really need.
+
+=item *
+
+Minimize the appliance, removing as much extraneous junk as possible.
+
+As well as using L<febootstrap-minimize(8)> it is worth checking for
+anything that is not necessary for your particular application and
+removing it by hand.
+
+=back
+
+=head1 SEE ALSO
+
+L<febootstrap(8)>,
+L<febootstrap-to-initramfs(8)>,
+L<febootstrap-to-supermin(8)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones <rjones @ redhat . com>
+
+=head1 COPYRIGHT
+
+(C) Copyright 2009 Red Hat Inc.,
+L<http://et.redhat.com/~rjones/febootstrap>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/febootstrap-supermin-helper.sh b/febootstrap-supermin-helper.sh
new file mode 100755
index 0000000..c2088bf
--- /dev/null
+++ b/febootstrap-supermin-helper.sh
@@ -0,0 +1,132 @@
+#!/bin/bash -
+# febootstrap-supermin-helper
+# (C) Copyright 2009 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# Written by Richard W.M. Jones <rjones@redhat.com>
+
+unset CDPATH
+
+TEMP=`getopt \
+ -o '' \
+ --long help,kmods: \
+ -n febootstrap-supermin-helper -- "$@"`
+if [ $? != 0 ]; then
+ echo "febootstrap-supermin-helper: problem parsing the command line arguments"
+ exit 1
+fi
+eval set -- "$TEMP"
+
+usage ()
+{
+ echo "Usage: febootstrap-supermin-helper supermin.img hostfiles.txt kernel initrd"
+ echo "Please read febootstrap-supermin-helper(8) man page for more information."
+}
+
+kmods=""
+
+while true; do
+ case "$1" in
+ --help)
+ usage
+ exit 0;;
+ --kmods)
+ kmods=$2
+ shift 2;;
+ --)
+ shift
+ break;;
+ *)
+ echo "Internal error!"
+ exit 1;;
+ esac
+done
+
+if [ $# -ne 4 ]; then
+ usage
+ exit 1
+fi
+
+set -e
+
+# Input files.
+supermin="$1"
+hostfiles="$2"
+
+# Output files.
+kernel="$3"
+initrd="$4"
+
+rm -f "$kernel" "$initrd"
+
+# Kernel:
+# Look for the most recent kernel named vmlinuz-*.<arch>* which has a
+# corresponding directory in /lib/modules/. If the architecture is x86, look
+# for any x86 kernel.
+#
+# RHEL 5 didn't append the arch to the kernel name, so look for kernels
+# without arch second.
+
+arch=$(echo "@host_cpu@" | sed 's/^i.86$/i?86/')
+kernels=$(ls -1vr /boot/vmlinuz-*.$arch* 2>/dev/null | grep -v xen; ls -1vr /boot/vmlinuz-* 2>/dev/null | grep -v xen)
+for f in $kernels; do
+ b=$(basename "$f")
+ b=$(echo "$b" | sed 's,vmlinuz-,,')
+ modpath="/lib/modules/$b"
+ if [ -d "$modpath" ]; then
+ ln -sf "$f" "$kernel"
+ break
+ fi
+ modpath=
+done
+
+if [ -z "$modpath" ]; then
+ echo "$0: failed to find a suitable kernel" >&2
+ exit 1
+fi
+
+# The initrd consists of these components:
+# (1) The base skeleton appliance that we constructed at build time.
+# format = plain cpio (could be compressed cpio)
+# (2) The modules from modpath which are on the module whitelist.
+# format = plain cpio
+# (3) The host files which match wildcards in hostfiles.
+# format = plain cpio
+
+cp "$supermin" "$initrd" ;# (1)
+
+# Kernel modules (2).
+
+if [ -n "$kmods" ]; then
+ exec 5<"$kmods"
+ whitelist=
+ while read kmod 0<&5; do
+ whitelist="$whitelist -o -name $kmod"
+ done
+ exec 5<&-
+else
+ whitelist="-o -name *.ko"
+fi
+
+find "$modpath" \( -not -name '*.ko' $whitelist \) -a -print0 |
+ cpio --quiet -o -0 -H newc >> "$initrd"
+
+# Host files (3).
+
+hostfiles=$(readlink -f "$hostfiles")
+(cd / &&
+ ls -1df $(cat "$hostfiles") 2>/dev/null |
+ cpio --quiet -o -H newc ) >> "$initrd"
diff --git a/febootstrap-to-supermin.pod b/febootstrap-to-supermin.pod
new file mode 100644
index 0000000..6263f51
--- /dev/null
+++ b/febootstrap-to-supermin.pod
@@ -0,0 +1,193 @@
+=head1 NAME
+
+febootstrap-to-supermin - Convert febootstrap root to supermin appliance.
+
+=head1 SYNOPSIS
+
+ febootstrap-to-supermin DIR supermin.img hostfiles.txt
+
+=head1 DESCRIPTION
+
+I<febootstrap-to-supermin> converts the filesystem created by
+L<febootstrap(8)> into a supermin appliance. The term "supermin
+appliance" is described in the documentation below. First you should
+be familiar with L<febootstrap(8)> and L<febootstrap-to-initramfs(8)>.
+
+=head1 PARAMETERS
+
+C<DIR> is the directory created by febootstrap (ie. the output of
+febootstrap and the input to this program).
+
+C<supermin.img> is the name of the supermin appliance that this
+program creates, and C<hostfiles.txt> is the name of the list of
+hostfiles that this program creates. (ie. the outputs of this
+program).
+
+=head1 SUPERMIN APPLIANCE
+
+A supermin appliance is a very specialized, highly minimized
+appliance which can be reconstructed on-the-fly at runtime into
+an ordinary (initramfs) appliance.
+
+The normal appliance is a self-contained Linux operating system, based
+on the Fedora/RHEL/CentOS Linux distro. So it contains a complete
+copy of all the libraries and programs needed, like kernel, libc,
+bash, coreutils etc etc.
+
+The supermin appliance removes the kernel and all the executable
+libraries and programs from the appliance. That just leaves a
+skeleton of directories, config files and some data files, which is
+obviously massively smaller than the normal appliance. At runtime we
+rebuild the appliance on-the-fly from the libraries and programs on
+the host (eg. pulling in the real /lib/libc.so, the real /bin/bash
+etc.)
+
+Although this process of rebuilding the appliance each time sounds
+slow, it turns out to be faster than using a prebuilt appliance.
+(Most of the saving comes from not compressing the appliance - it
+transpires that decompressing the appliance is the slowest part of the
+whole boot sequence). On my machine, a new appliance can be built in
+under a fifth of a second, and the boot time is several seconds
+shorter.
+
+The big advantage of the supermin appliance for distributions like
+Fedora is that it gets security fixes automatically from the host, so
+there is no need to rebuild the whole appliance for a security update
+in some underlying library.
+
+There are several I<disadvantages>:
+
+It won't work at all except in very narrow, controlled cases like the
+Fedora packaging case. We control the dependencies of the appliance
+RPM tightly to ensure that the required binaries are actually present
+on the host.
+
+Furthermore there are certain unlikely changes in the packages on the
+host which could break a supermin appliance, eg. an updated library
+which depends on an additional data file.
+
+Also supermin appliances are subjected to changes in the host kernel
+which might break compatibility with qemu -- these are, of course,
+real bugs in any case.
+
+Lastly, supermin appliances really can't be moved between branches of
+distributions (eg. built on Fedora 12 and moved to Fedora 10) because
+they are not self-contained and they rely on certain libraries being
+around. You shouldn't do this anyway.
+
+Use supermin appliances with caution.
+
+=head2 ANATOMY OF A SUPERMIN APPLIANCE
+
+A supermin appliance consists of two files:
+
+=over 4
+
+=item supermin.img
+
+The image file (conventionally called C<supermin.img>, but you can
+call it anything you want) is the skeleton initramfs. This is like an
+initramfs built by L<febootstrap-to-initramfs(8)>, but all libraries
+and binaries are removed.
+
+=item hostfiles.txt
+
+This plain text file contains a list of files that we need to add back
+from the host at runtime. ie. It's the list of libraries and binaries
+that we removed when we constructed C<supermin.img>.
+
+This file usually contains wildcards. This is because we don't
+want the file to break on minor updates to libraries, so for example
+instead of listing
+
+ lib64/libreadline.so.6.1.2
+
+the file contains
+
+ lib64/libreadline.so.6.*
+
+=back
+
+=head2 RECONSTRUCTING AN INITRAMFS FROM A SUPERMIN APPLIANCE
+
+The program L<febootstrap-supermin-helper(8)> can be used to
+reconstruct a full initramfs from C<supermin.img> and C<hostfiles.txt>
+(plus, naturally, the required programs and libraries in the host
+filesystem).
+
+See that man page for details.
+
+=head2 RESTRICTION: UNREADABLE BINARIES ON THE HOST
+
+Some binaries on the host are not publically readable. For example:
+
+ $ ll /usr/libexec/pt_chown
+ -rws--x--x 1 root root 28418 2009-09-28 13:42 /usr/libexec/pt_chown
+ $ ll /usr/bin/chsh
+ -rws--x--x 1 root root 18072 2009-10-05 16:28 /usr/bin/chsh
+
+These binaries cause a problem when reconstructing the supermin
+appliance, because we'd like to copy them into the final appliance,
+and usually that process is done as non-root. Currently the only
+solution is that you should remove these problematic binaries from the
+appliance.
+
+=head1 EXAMPLE
+
+Create a basic Fedora directory and turn it into a supermin image.
+
+I<NB> You must only build "Rawhide on Rawhide". If using another
+Fedora branch, you must change C<rawhide> below as appropriate, eg to
+C<fedora-12>.
+
+ $ febootstrap rawhide /tmp/fedora
+ $ febootstrap-to-supermin /tmp/fedora supermin.img hostfiles.txt
+
+Examine the resulting files:
+
+ $ cpio -itv < supermin.img | less
+ $ less hostfiles.txt
+
+Reconstruct the final kernel and initramfs.
+
+I<NB> The first time you run this, it will be slow because the
+required host files are not in cache. With a "hot cache" it should be
+lightning fast. Run it several times to get representative timings.
+
+ $ febootstrap-supermin-helper supermin.img hostfiles.txt \
+ /tmp/kernel /tmp/initrd
+
+You would boot the final image like this, although in this example it
+probably won't work unless you add a C</init> file to the appliance
+(see the discussion in L<febootstrap-to-initramfs(8)>).
+
+ $ qemu -m 1024 -kernel /tmp/kernel -initrd /tmp/initrd [etc...]
+
+=head1 SEE ALSO
+
+L<febootstrap(8)>,
+L<febootstrap-to-initramfs(8)>,
+L<febootstrap-supermin-helper(8)>.
+
+=head1 AUTHORS
+
+Richard W.M. Jones <rjones @ redhat . com>
+
+=head1 COPYRIGHT
+
+(C) Copyright 2009 Red Hat Inc.,
+L<http://et.redhat.com/~rjones/febootstrap>.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/febootstrap-to-supermin.sh b/febootstrap-to-supermin.sh
new file mode 100755
index 0000000..32fd593
--- /dev/null
+++ b/febootstrap-to-supermin.sh
@@ -0,0 +1,133 @@
+#!/bin/bash -
+# febootstrap-to-supermin
+# (C) Copyright 2009 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+# Written by Richard W.M. Jones <rjones@redhat.com>
+
+unset CDPATH
+
+TEMP=`getopt \
+ -o '' \
+ --long help \
+ -n febootstrap-to-supermin -- "$@"`
+if [ $? != 0 ]; then
+ echo "febootstrap-to-supermin: problem parsing the command line arguments"
+ exit 1
+fi
+eval set -- "$TEMP"
+
+usage ()
+{
+ echo "Usage: febootstrap-to-supermin DIR supermin.img hostfiles.txt"
+ echo "Please read febootstrap-to-supermin(8) man page for more information."
+}
+
+while true; do
+ case "$1" in
+ --help)
+ usage
+ exit 0;;
+ --)
+ shift
+ break;;
+ *)
+ echo "Internal error!"
+ exit 1;;
+ esac
+done
+
+if [ $# -ne 3 ]; then
+ usage
+ exit 1
+fi
+
+set -e
+
+# Create a temporary directory, make sure it gets cleaned up at the end.
+tmpdir=$(mktemp -d)
+remove_tmpdir ()
+{
+ status=$?
+ rm -rf "$tmpdir" && exit $status
+}
+trap remove_tmpdir EXIT
+
+# Get the complete list of files and directories in the appliance.
+(cd "$1" > /dev/null && find) > "$tmpdir/files"
+
+exec 5>"$tmpdir/keep" # Files/dirs we will keep in supermin.img
+exec 6>$3 # hostfiles.txt (output)
+exec 7<"$tmpdir/files"
+
+while read path <&7; do
+ dir=$(dirname "$path")
+ file=$(basename "$path")
+
+ # Ignore fakeroot.log.
+ if [ "$path" = "./fakeroot.log" ]; then
+ :
+
+ # Kernel modules are always copied in from the host, including all
+ # the dependency information files.
+ elif [[ "$path" =~ '^\./lib/modules/' ]]; then
+ :
+
+ # All we're going to keep are the special files /init, the daemon,
+ # configuration files (/etc), devices and modifiable stuff (/var).
+ elif [ "$path" = "./init" ]; then
+ echo "$path" >&5
+
+ elif [[ "$path" =~ '^\./etc' || "$path" =~ '^./dev' || "$path" =~ '^\./var' ]]; then
+ echo "$path" >&5
+
+ # Always write directory names to both output files.
+ elif [ -d "$path" ]; then
+ echo "$path" >&5
+ echo "$path" >&6
+
+ # Some libraries need fixed version numbers replaced by wildcards.
+ elif [[ "$file" =~ '^ld-[.0-9]+\.so$' ]]; then
+ echo "$dir/ld-*.so" >&6
+
+ # libfoo-1.2.3.so
+ elif [[ "$file" =~ '^lib(.*)-[-.0-9]+\.so$' ]]; then
+ echo "$dir/lib${BASH_REMATCH[1]}-*.so" >&6
+
+ # libfoo-1.2.3.so.1.2.3 (but NOT '*.so.N')
+ elif [[ "$file" =~ '^lib(.*)-[-.0-9]+\.so\.([0-9]+)\.' ]]; then
+ echo "$dir/lib${BASH_REMATCH[1]}-*.so.${BASH_REMATCH[2]}.*" >&6
+
+ # libfoo.so.1.2.3 (but NOT '*.so.N')
+ elif [[ "$file" =~ '^lib(.*)\.so\.([0-9]+)\.' ]]; then
+ echo "$dir/lib${BASH_REMATCH[1]}.so.${BASH_REMATCH[2]}.*" >&6
+
+ else
+ # Anything else comes from the host directly.
+ echo "$path" >&6
+ fi
+done
+
+# Close output files.
+exec 5>&-
+exec 6>&-
+
+# Now run febootstrap-to-initramfs to construct the supermin
+# appliance.
+if ! febootstrap-to-initramfs --nocompress --files="$tmpdir/keep" "$1" > "$2"
+then
+ rm -f "$2"
+fi
diff --git a/febootstrap.pod b/febootstrap.pod
index e208603..d8ec24e 100644
--- a/febootstrap.pod
+++ b/febootstrap.pod
@@ -169,6 +169,11 @@ permissions using the tool C<febootstrap-to-initramfs>.
=item *
+Generate a supermin appliance using the tool
+C<febootstrap-to-supermin>.
+
+=item *
+
Apply the permissions to the target directory using the forthcoming
tool C<febootstrap-fix-root> (requires root).
@@ -227,6 +232,7 @@ L<febootstrap-to-initramfs(8)>,
L<febootstrap-minimize(8)>,
L<febootstrap-run(8)>,
L<febootstrap-install(8)>,
+L<febootstrap-to-supermin(8)>,
L<fakeroot(1)>,
L<fakechroot(1)>,
L<yum(8)>,