#!/bin/bash
# Copyright 2012  Andrey Tataranovich
# 
# 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 3 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, see <http://www.gnu.org/licenses/>.

DEFAULT_IMAGE_NAME="debian-image-`date +'%Y-%m-%d'`.raw"
DEFAULT_IMAGE_SIZE="1024M"
IMAGE_NAME="$1"
IMAGE_SIZE="$2"

if [ `hostname` == "debbox" ]; then
	DEBIAN_REPO="ftp://192.168.90.32/mirror/debian"
	DEBIAN_SECURITY_REPO="ftp://192.168.90.32/mirror/debian-security"
else
	DEBIAN_REPO="http://ftp.by.debian.org/debian"
	DEBIAN_SECURITY_REPO="http://security.debian.org/"
fi

export LC_ALL=C

if [ `id -u` != 0 ]; then
	echo "You must be root to run this script"
	exit 1
fi

if [ "${IMAGE_NAME}" == "" ]; then
	IMAGE_NAME=${DEFAULT_IMAGE_NAME}
fi

if ! echo "${IMAGE_SIZE}" | grep -q -E '^[0-9]+[kKmMgG]?$'; then
	IMAGE_SIZE=${DEFAULT_IMAGE_SIZE}
fi

# Create RAW image and attach it to loop device
truncate -s ${IMAGE_SIZE} ${IMAGE_NAME}
LOOP_DEVICE=`losetup -f --show ${IMAGE_NAME}`
if [ ! -b ${LOOP_DEVICE} ]; then
	echo "Failed to attach file ${IMAGE_NAME} to loop device"
	exit 1
fi

dd if=/dev/zero of=/dev/loop0 bs=1M count=1 conv=notrunc

# Create single partition
sfdisk --force -uS ${LOOP_DEVICE} << EOF
63,204800,b,*
204863,,83
EOF

# Populate partitions from loop device
LOOP_VFAT_PARTITION=`losetup -f --show -o 32256 --sizelimit 104857600 ${IMAGE_NAME}`
LOOP_EXT3_PARTITION=`losetup -f --show -o 104889856 ${IMAGE_NAME}`
if [ ! -b ${LOOP_VFAT_PARTITION} -o ! -b ${LOOP_EXT3_PARTITION} ]; then
	echo "Failed to populate partitions from ${LOOP_DEVICE}"
	losetup -d ${LOOP_VFAT_PARTITION}
	losetup -d ${LOOP_EXT3_PARTITION}
	losetup -d ${LOOP_DEVICE}
	exit 1
fi

# Create filesystems and mount it
mkfs.vfat ${LOOP_VFAT_PARTITION}
mkfs.ext3 ${LOOP_EXT3_PARTITION}

# Detect UUID of created partitions
VFAT_FS_UUID=`blkid -o udev ${LOOP_VFAT_PARTITION} | grep ^ID_FS_UUID= | cut -d= -f2`
EXT3_FS_UUID=`blkid -o udev ${LOOP_EXT3_PARTITION} | grep ^ID_FS_UUID= | cut -d= -f2`

BOOTSTRAP_DIR=`mktemp -d`
if [ ! -d ${BOOTSTRAP_DIR} ]; then
	echo "mktemp failed to create bootstrap directory"
	losetup -d ${LOOP_VFAT_PARTITION}
	losetup -d ${LOOP_EXT3_PARTITION}
	losetup -d ${LOOP_DEVICE}
	exit 1
else
	mount -t ext3 ${LOOP_EXT3_PARTITION} ${BOOTSTRAP_DIR}
	mkdir ${BOOTSTRAP_DIR}/boot
	mount -t vfat ${LOOP_VFAT_PARTITION} ${BOOTSTRAP_DIR}/boot -o uid=0,gid=0,dmask=0022,fmask=0133
fi

# Debootstrap stable debian
debootstrap squeeze ${BOOTSTRAP_DIR} ${DEBIAN_REPO}

# Mount needed filesystems
mount -t proc none ${BOOTSTRAP_DIR}/proc
mount -t sysfs none ${BOOTSTRAP_DIR}/sys
mount -o bind /dev ${BOOTSTRAP_DIR}/dev
mount -t devpts none ${BOOTSTRAP_DIR}/dev/pts

# Create initial APT settings
cat > ${BOOTSTRAP_DIR}/etc/apt/sources.list << EOF
deb ${DEBIAN_REPO} squeeze main contrib non-free
deb ${DEBIAN_SECURITY_REPO} squeeze/updates main contrib non-free
EOF

cat > ${BOOTSTRAP_DIR}/etc/apt/apt.conf.d/70disable-recommends-suggests << EOF
APT::Install-Recommends "false";
APT::Install-Suggests "false";
EOF

# Setup basic network
cat > ${BOOTSTRAP_DIR}/etc/network/interfaces << EOF
auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet dhcp
EOF

# Setup fstab
cat > ${BOOTSTRAP_DIR}/etc/fstab << EOF
UUID=${EXT3_FS_UUID}		/		ext3	defaults,relatime,errors=remount-ro		1 1
UUID=${VFAT_FS_UUID}	/boot	vfat	defaults,uid=0,gid=0,dmask=0022,fmask=0133 1 2
none		/tmp	tmpfs	defaults								0 0
EOF

# Prepare to replace syslinux with grub
cat > ${BOOTSTRAP_DIR}/root/syslinux-replace.sh << EOF
#!/bin/bash
clear
echo "Finishing installation..."
(sysctl -w kernel.printk='3 4 1 3'
mount -o remount,rw /
mount /boot
cd /boot
tar -cf /root/boot.tar .
cd /
umount /boot
TARGET_PART=\`blkid -o device -U ${VFAT_FS_UUID}\`
mkfs.ext3 \${TARGET_PART}
TARGET_UUID=\`blkid -o udev \${TARGET_PART} | grep ^ID_FS_UUID= | cut -d= -f2\`
sed -i -e '/vfat/d' /etc/fstab
echo "UUID=\${TARGET_UUID} /boot ext3 defaults 1 2" >> /etc/fstab
mount /boot
tar -xf /root/boot.tar -C /boot
rm -fr /boot/{syslinux,ldlinux.sys}
TARGET_DEVICE=\`echo \${TARGET_PART} | sed -e 's/[0-9]*$//'\`
grub-install \${TARGET_DEVICE}
update-initramfs -u -k all
update-grub
yes | aptitude purge syslinux mtools
rm -f /root/{boot.tar,syslinux-replace.sh}
umount /boot
mount -o remount,ro /) > /dev/null 2>&1
echo s > /proc/sysrq-trigger
sleep 1
echo b > /proc/sysrq-trigger
EOF
chmod +x ${BOOTSTRAP_DIR}/root/syslinux-replace.sh

cat > ${BOOTSTRAP_DIR}/root/last.stage << EOF
export DEBIAN_FRONTEND=noninteractive
export LC_ALL=C
aptitude update
yes | aptitude install openssh-server openssh-client vim less wget
yes | aptitude install --with-recommends linux-image-2.6-686 grub-pc
yes | aptitude install syslinux mtools
rm -f /etc/udev/rules.d/70-persistent-net.rules
dd if=/usr/lib/syslinux/mbr.bin of=${LOOP_DEVICE}
syslinux -i ${LOOP_VFAT_PARTITION}
echo -e 'root\nroot\n' | passwd root
EOF

chroot ${BOOTSTRAP_DIR} /bin/bash /root/last.stage
rm -f ${BOOTSTRAP_DIR}/root/last.stage

# Detect kernel image and initrd file names
KERNEL_FNAME=$(basename $(ls -1 ${BOOTSTRAP_DIR}/boot/vmlinuz-*))
INITRD_FNAME=$(basename $(ls -1 ${BOOTSTRAP_DIR}/boot/initrd.img-*))

# Setup syslinux
mkdir ${BOOTSTRAP_DIR}/boot/syslinux
cat > ${BOOTSTRAP_DIR}/boot/syslinux/syslinux.cfg << EOF
default linux
timeout 5

label linux
        kernel /${KERNEL_FNAME}
		initrd /${INITRD_FNAME}
        append root=UUID=${EXT3_FS_UUID} ro quiet init=/root/syslinux-replace.sh
EOF

# Do cleanup
umount ${BOOTSTRAP_DIR}/dev/pts
umount ${BOOTSTRAP_DIR}/dev
umount ${BOOTSTRAP_DIR}/proc
umount ${BOOTSTRAP_DIR}/sys
umount ${BOOTSTRAP_DIR}/boot
umount ${BOOTSTRAP_DIR}
rmdir ${BOOTSTRAP_DIR}
losetup -d ${LOOP_VFAT_PARTITION}
losetup -d ${LOOP_EXT3_PARTITION}
losetup -d ${LOOP_DEVICE}

chmod 666 ${IMAGE_NAME}
echo "Virtual image ${IMAGE_NAME} created"
