Conditional partitioning in debian installer

I needed to create an automatic, unattended installer that would repartition the whole disk, but keep an existing home partition if it is already existing. The idea is to replace the operating system, but keep the user's home files. If the home partition does not exist, however, we need to create it.

The starting point for this is in Holger's website, which does everything except create the partition if it's missing.

The technique I used is to create a udeb that would scan the partitions using /usr/lib/partconf/find-partitions and then load the right preseeding for partman-auto, the automatic partitioner.

Here you find the udeb source. I'll comment the most important bits:

First, the two partman-auto recipes that we are going to preseed. The format is documented in the debian-installer documentation.

This will create /home if missing:

        d-i partman-auto/expert_recipe string                           \
                condpart ::                                             \
                2048 2048 2048 ext3                                     \
                        $primary{ } $bootable{ }                        \
                        method{ format } format{ }                      \
                        use_filesystem{ } filesystem{ ext3 }            \
                        mountpoint{ / }                                 \
                .                                                       \
                1024 1024 1024 linux-swap                               \
                        method{ swap } format{ }                        \
                .                                                       \
                1024 4096 10000000 ext3                                 \
                        method{ format } format{ }                      \
                        use_filesystem{ } filesystem{ ext3 }            \
                        mountpoint{ /home }                             \
                .

And this will keep /home if it exists:

        d-i partman-auto/expert_recipe string                           \
                condpart ::                                             \
                2048 2048 2048 ext3                                     \
                        $primary{ } $bootable{ }                        \
                        method{ format } format{ }                      \
                        use_filesystem{ } filesystem{ ext3 }            \
                        mountpoint{ / }                                 \
                .                                                       \
                1024 1024 1024 linux-swap                               \
                        method{ swap } format{ }                        \
                .                                                       \
                1024 4096 10000000 ext3                                 \
                        method{ keep }                                  \
                        use_filesystem{ } filesystem{ ext3 }            \
                        mountpoint{ /home }                             \
                .

Then the postinst file of the package, where the logic is. Otavio and Daniel on #debian-boot have taught me that udebs are, simply put, just big postinsts (installer wise, apart from shipping binaries). Postinst is where the logic is done, or applications are started.

#!/bin/sh

# Copyright 2008 Enrico Zini <enrico@truelite.it>
# Licensed under the terms of the GNU General Public License,
# version 3 or any later version.

set -e

FINDPARTS="/usr/lib/partconf/find-partitions"

notice () {
    logger -t condpart "$@"
}
error () {
    logger -t condpart "error: $@"
}

# load debconf
. /usr/share/debconf/confmodule

notice "Checking if we need to recreate /home"

if [ ! -x $FINDPARTS ]
then
    error "$FINDPARTS not found"
    exit 1
fi

if $FINDPARTS | grep -q part6
then
    # Keep
    notice "/home exists: we keep it"
    debconf-set-selections /usr/lib/condpart/part-keep.preseed
else
    # Format
    notice "/home does not exist: we create it"
    debconf-set-selections /usr/lib/condpart/part-create.preseed
fi

notice "Finished special handling of /home"

#DEBHELPER#

exit 0

Finally, debian/control. The basic bits about creating a d-i udeb are to put it in Section: debian-installer and to use XC-Package-Type: udeb. Then there is XB-Installer-Menu-Item, that defines the order of execution of postinsts. The d-i documentation lists the numbers that are currently assigned.

Source: condpart
Section: debian-installer
Priority: optional
Maintainer: Enrico Zini <enrico@debian.org>
Build-Depends: debhelper (>= 4.0.0), cdbs
Standards-Version: 3.7.2.1

Package: condpart
Architecture: any
XC-Package-Type: udeb
XB-Installer-Menu-Item: 38
Description: Conditional partitioning
 Tells partman-auto to create /home if it's missing, or if it exists, to keep
 it.

I am using 38 rather than 3800 because I'm targeting etch d-i. After etch, "numbers have been multiplied by 100 from what they were before to give us more space".

This is it. debian/rules is just boilerplate, except installing the preseed files in the right place. CDBS is useful to make this self-evident:

#!/usr/bin/make -f

include /usr/share/cdbs/1/rules/debhelper.mk

install/condpart::
    install -o root -g root -m 0644 *.preseed debian/$(cdbs_curpkg)/usr/lib/condpart/

To build the installer CD with this d-i, I'm using simple-cdd; here are the profile files I'm using at the moment, with the main preseeding for fully unattended install (it is designed to trash your hard disk if you boot it, so only test it in an emulated environment) and the inclusion of the custom udeb.