131 lines
3.0 KiB
Plaintext
131 lines
3.0 KiB
Plaintext
|
#!/bin/sh -e
|
||
|
|
||
|
. shell-error
|
||
|
|
||
|
if [ $# -lt 2 ]; then
|
||
|
fatal "error: tar2vm needs at least two arguments"
|
||
|
fi
|
||
|
|
||
|
# this needs env_keep sudo setup to actually work
|
||
|
if [ -n "$GLOBAL_BUILDDIR" ]; then
|
||
|
WORKDIR="$GLOBAL_BUILDDIR/vmroot"
|
||
|
else
|
||
|
WORKDIR="$(mktemp --tmpdir -d vmroot-XXXXX)"
|
||
|
fi
|
||
|
|
||
|
[ -n "$WORKDIR" ] || fatal "couldn't come up with suitable WORKDIR"
|
||
|
|
||
|
[ -n "$GLOBAL_DEBUG" ] || message "WORKDIR: $WORKDIR"
|
||
|
|
||
|
# a tarball containing chroot with a kernel
|
||
|
TAR="$1"
|
||
|
[ -s "$TAR" ] || fatal "source tarball doesn't really exist"
|
||
|
|
||
|
# a path to the image to be generated
|
||
|
IMG="$2"
|
||
|
[ -d "$(dirname "$IMG")" ] || fatal "target directory doesn't exist"
|
||
|
|
||
|
# image size in bytes (256M is a fallback)
|
||
|
TARSIZE="$(stat -Lc %s "$TAR")"
|
||
|
DEFSIZE="$(expr 3 '*' "$TARSIZE" '/' 2)"
|
||
|
DISKSIZE="${3:-${DEFSIZE:-268435456}}"
|
||
|
# ...and in megabytes
|
||
|
DISKSIZEM="$(expr "$DISKSIZE" / 1048576)"
|
||
|
|
||
|
# tested to work: ext[234], jfs
|
||
|
ROOTFSTYPE="${4:-ext4}"
|
||
|
|
||
|
# single root partition hardwired so far,
|
||
|
# add another image for swap if needed
|
||
|
ROOTDEV="/dev/sda1"
|
||
|
|
||
|
# last preparations...
|
||
|
for i in losetup parted kpartx mkfs."$ROOTFSTYPE"; do
|
||
|
if ! type -t "$i" >&/dev/null; then
|
||
|
fatal "$i required but not found"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
LOOPDEV="$(losetup --find)"
|
||
|
ROOTFS="$WORKDIR/chroot"
|
||
|
|
||
|
exit_handler()
|
||
|
{
|
||
|
rc=$?
|
||
|
if [ -n "$ROOTFS" ]; then
|
||
|
umount "$ROOTFS"{/dev,/proc,/sys,}
|
||
|
if [ -n "$LOOPDEV" ]; then
|
||
|
kpartx -d "$LOOPDEV"
|
||
|
losetup --detach "$LOOPDEV"
|
||
|
fi
|
||
|
rm -r -- "$ROOTFS"
|
||
|
rmdir -- "$WORKDIR"
|
||
|
fi
|
||
|
exit $rc
|
||
|
}
|
||
|
|
||
|
trap exit_handler EXIT
|
||
|
|
||
|
# prepare disk image and a filesystem inside it
|
||
|
rm -f -- "$IMG"
|
||
|
dd if=/dev/zero of="$IMG" bs=1 count=1 seek="$DISKSIZE" conv=notrunc
|
||
|
losetup "$LOOPDEV" "$IMG"
|
||
|
|
||
|
parted --script "$LOOPDEV" mklabel msdos
|
||
|
parted --script "$LOOPDEV" mkpart primary ext2 1 "$DISKSIZEM"
|
||
|
|
||
|
kpartx -a "$LOOPDEV"
|
||
|
LOOPDEV1="/dev/mapper/$(basename "$LOOPDEV")p1"
|
||
|
|
||
|
mkfs."$ROOTFSTYPE" "$LOOPDEV1"
|
||
|
|
||
|
# mount and populate it
|
||
|
mkdir -pm755 "$ROOTFS"
|
||
|
mount "$LOOPDEV1" "$ROOTFS"
|
||
|
tar -C "$ROOTFS" --numeric-owner -xf "$TAR"
|
||
|
for i in /dev /proc /sys; do mount --bind "$i" "$ROOTFS$i"; done
|
||
|
|
||
|
# NB: different storage modules might be needed for non-kvm
|
||
|
echo "$LOOPDEV1 / $ROOTFSTYPE defaults 1 1" >> "$ROOTFS/etc/fstab"
|
||
|
echo "MODULES_PRELOAD=sd_mod ata_piix $ROOTFSTYPE" >> "$ROOTFS/etc/initrd.mk"
|
||
|
|
||
|
KERNEL="$(readlink $ROOTFS/boot/vmlinuz | sed 's,vmlinuz-,,')"
|
||
|
chroot "$ROOTFS" make-initrd -k "$KERNEL"
|
||
|
|
||
|
sed -i "s,$LOOPDEV1,$ROOTDEV," "$ROOTFS/etc/fstab"
|
||
|
|
||
|
# configure and install bootloader
|
||
|
REGEXP='^([0-9]+) heads, ([0-9]+) sectors/track, ([0-9]+) cylinders.*$'
|
||
|
set -- $(fdisk -l "$LOOPDEV" | grep -E "$REGEXP" | sed -r "s@$REGEXP@\1 \2 \3@")
|
||
|
|
||
|
LILO_COMMON="lba32
|
||
|
delay=1
|
||
|
vga=0
|
||
|
image=/boot/vmlinuz
|
||
|
initrd=/boot/initrd.img
|
||
|
append=\"root=$ROOTDEV rootdelay=3\"
|
||
|
label=linux"
|
||
|
|
||
|
cat > "$ROOTFS"/etc/lilo-loop.conf << EOF
|
||
|
boot=$LOOPDEV
|
||
|
disk=$LOOPDEV
|
||
|
bios=0x80
|
||
|
heads=$1
|
||
|
sectors=$2
|
||
|
cylinders=$3
|
||
|
partition=$LOOPDEV1
|
||
|
start=63
|
||
|
$LILO_COMMON
|
||
|
EOF
|
||
|
|
||
|
chroot "$ROOTFS" lilo -C /etc/lilo-loop.conf
|
||
|
|
||
|
cat > "$ROOTFS"/etc/lilo.conf << EOF
|
||
|
boot=${ROOTDEV%[0-9]*}
|
||
|
$LILO_COMMON
|
||
|
EOF
|
||
|
|
||
|
if [ -n "$SUDO_USER" ]; then
|
||
|
chown "$SUDO_USER" "$IMG" "$ROOTFS" "$WORKDIR"
|
||
|
fi
|