tar2vm 3.1 KB
Newer Older
Michael Shigorin's avatar
Michael Shigorin committed
1
#!/bin/bash -e
2 3
# usage:
# tar2vm chroot.tar image.raw [size_in_bytes]
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

. 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")"
32
DEFSIZE="$((2 * $TARSIZE))"
33 34
DISKSIZE="${3:-${DEFSIZE:-268435456}}"
# ...and in megabytes
Michael Shigorin's avatar
Michael Shigorin committed
35
DISKSIZEM="$(($DISKSIZE / 1048576))"
36 37 38 39 40 41 42 43 44

# 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...
45
for i in losetup sfdisk parted kpartx mkfs."$ROOTFSTYPE"; do
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
	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"
Michael Shigorin's avatar
Michael Shigorin committed
73 74
dd if=/dev/zero of="$IMG" conv=notrunc \
	bs=1 count=1 seek="$(($DISKSIZE - 1))"
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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
101 102
REGEXP='^Disk .*: ([0-9]+) cylinders, ([0-9]+) heads, ([0-9]+) sectors/track*$'
set -- $(sfdisk -l "$LOOPDEV" | grep -E "$REGEXP" | sed -r "s@$REGEXP@\1 \2 \3@")
103 104 105 106 107 108 109 110 111 112 113 114 115

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
116 117 118
  cylinders=$1
  heads=$2
  sectors=$3
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
  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