scripts/mkvm.sh

268 lines
5.7 KiB
Bash
Executable File

#!/bin/sh
usage() {
echo "usage: ${0##*/} [options] name [stage_tarball [custom_script]]"
}
usage_full() {
usage
printf '
Create a libvirt virtual machine running Gentoo Linux
positional arguments:
name The libvirt domain name for the VM
stage_tarball Path to the Gentoo stage tarball to extract to the
virtual machine filesystem
custom_script Path to a script to run in the virtual machine chroot
before powering it on
optional arguments:
-h, --help show this help message and exit
--hostname, -H The hostname of the VM (defaults to the libvirt
domain name, in all lower case)
--kernel-pkg, -K Path to a tarball containing a kernel and modules
--pool, -p The libvirt storage pool in which to create the
virtual disk
--disk-size The size of virtual disk to create (default 6 GB)
--disk-format The image format of the virtual disk (default qcow2)
--vram, -r The amount of RAM to allocate to the VM
--vcpus, -c The number of virtual CPUs to allocate to the VM
--vnet, -n The network adapter on the host to connect to the VM
--timezone, -Z The timezone to set in the VM
'
}
invalid_arg() {
usage >&2
echo "${0##*/}: Unrecognized argument: $1" >&2
exit 2;
}
while [ $# -gt 0 ]; do
case $1 in
--hostname|-H)
shift
VHOSTNAME=$1
shift
;;
--kernel-pkg|-K)
shift
KERNEL_PKG=$1
shift
;;
--pool|-p)
shift
POOL=$1
shift
;;
--disk-size|-s)
shift
VDISKSIZE=$1
shift
;;
--disk-format|-f)
shift
VDISKFORMAT=$1
shift
;;
--vram|-r)
shift
VRAM=$1
shift
;;
--vcpus|-c)
shift
VCPUS=$1
shift
;;
--vnet|-n)
shift
VNET=$1
shift
;;
--timezone|-Z)
shift
TIMEZONE=$1
shift
;;
--help|-h)
usage_full
exit 0
;;
-*)
invalid_arg $1
;;
*)
if [ -z "${DOMNAME}" ]; then
DOMNAME=$1
shift
elif [ -z "${STAGE_TBZ}" ]; then
STAGE_TBZ=$1
shift
elif [ -z "${CUSTOMIZE}" ]; then
CUSTOMIZE=$1
shift
else
invalid_arg $1
fi
;;
esac
done
set -e
if [ -z "${DOMNAME}" ]; then
usage >&2
exit 2
fi
: ${VHOSTNAME:=$(printf "${DOMNAME}" | tr '[A-Z]' '[a-z]')}
: ${POOL:=default}
: ${TIMEZONE:=America/Chicago}
unset $(env | awk -F= '/^LC_/{print $1}')
export LC_ALL=C
mountpoint=${TMPDIR:-/tmp}/${VHOSTNAME}
mkdir ${mountpoint}
virsh vol-create-as ${POOL} ${DOMNAME}.img \
--capacity ${VDISKSIZE:-6G} \
--format ${VDISKFORMAT:-qcow2}
vol_path=$(virsh vol-path ${DOMNAME}.img ${POOL})
echo 'Creating logical volumes and filesystems ...'
i=$(pgrep -fa ^nbd | sort -k2r | sed -rn '1s/[0-9]+\s+nbd//p')
blkdev=/dev/nbd$((${i:--1} + 1))
unset i
sudo /bin/sh -e <<EOS
qemu-nbd -c ${blkdev} ${vol_path}
sgdisk -a 4096 -Z -g \
-n 1::+1M \
-t 1:EF02 \
-c 1:'BIOS boot partition' \
-n 2::+32M \
-c 2:'Linux filesystem' \
-n 3:: \
-t 3:8E00 \
-c 3:'Linux LVM' \
${blkdev}
pvscan > /dev/null
pvcreate ${blkdev}p3
vgcreate ${VHOSTNAME} ${blkdev}p3
lvcreate -nswap -L1G ${VHOSTNAME}
lvcreate -nroot -L300M ${VHOSTNAME}
lvcreate -nusr -L1200M ${VHOSTNAME}
lvcreate -nvar -L600M ${VHOSTNAME}
lvcreate -nopt -L100M ${VHOSTNAME}
lvcreate -nhome -L100M ${VHOSTNAME}
mkswap -Lswap /dev/${VHOSTNAME}/swap
mkfs.ext4 -q -Lboot ${blkdev}p2
for v in root usr var opt home; do
mkfs.xfs -q -L\$v /dev/${VHOSTNAME}/\$v
done
EOS
[ -z "${STAGE_TBZ}" ] && exit 0
echo 'Mounting filesystems ...'
sudo /bin/sh -e <<EOS
mount /dev/${VHOSTNAME}/root ${mountpoint}
install -d ${mountpoint}/boot
mount ${blkdev}p2 ${mountpoint}/boot
for v in usr var opt home; do
install -d ${mountpoint}/\$v
mount /dev/${VHOSTNAME}/\$v ${mountpoint}/\$v
done
EOS
echo 'Extracting stage tarball ...'
sudo tar -xaf "${STAGE_TBZ}" -C ${mountpoint}
echo 'Configuring system ...'
sudo /bin/sh -e <<EOS
mount -t proc proc ${mountpoint}/proc
mount -t sysfs sysfs ${mountpoint}/sys
mount -obind /dev ${mountpoint}/dev
chroot ${mountpoint} grub2-install ${blkdev}
cat > ${mountpoint}/boot/grub/grub.cfg <<EOF
timeout=1
menuentry 'Gentoo Linux' {
root=hd0,gpt2
linux /vmlinuz root=/dev/${VHOSTNAME}/root dolvm net.ifnames=0 quiet
initrd /initramfs
}
EOF
sed -i s/localhost/${VHOSTNAME}/ ${mountpoint}/etc/conf.d/hostname
cat > ${mountpoint}/etc/fstab <<EOF
LABEL=swap none swap sw 0 0
LABEL=boot /boot ext4 noauto,noatime 1 2
/dev/${VHOSTNAME}/root / xfs ro,noatime 0 1
/dev/${VHOSTNAME}/usr /usr xfs ro,noatime 0 2
/dev/${VHOSTNAME}/var /var xfs noatime 0 2
/dev/${VHOSTNAME}/opt /opt xfs ro,noatime 0 2
/dev/${VHOSTNAME}/home /home xfs noatime 0 2
tmpfs /tmp tmpfs defaults 0 0
EOF
rm -rf ${mountpoint}/run/openrc
ln -snf /proc/self/mounts ${mountpoint}/etc/mtab
ln -snf /run/resolv.conf ${mountpoint}/etc/resolv.conf
ln -snf /run/ntp.conf ${mountpoint}/etc/ntp.conf
ln -snf /usr/share/zoneinfo/${TIMEZONE} ${mountpoint}/etc/localtime
echo ${TIMEZONE} > ${mountpoint}/etc/timezone
passwd -R ${mountpoint} -d root
EOS
if [ -n "${KERNEL_PKG}" ]; then
echo 'Extracting kernel package ...'
sudo tar --no-same-owner --no-same-permissions --strip-components=1 \
--dereference -xaf "${KERNEL_PKG}" -C ${mountpoint}
fi
if [ -f "${CUSTOMIZE}" ]; then
echo 'Customizing ...'
sudo /bin/sh "${CUSTOMIZE}"
fi
echo 'Cleaning up ...'
awk '$5~/'${VHOSTNAME}'/{print $5}' /proc/self/mountinfo | tac \
| xargs sudo umount
sudo vgchange -an ${VHOSTNAME}
sudo qemu-nbd -d ${blkdev}
virt-install --name ${DOMNAME} \
--ram ${VRAM:-1024} \
--vcpus ${VCPUS:-2} \
--os-type linux \
--os-variant rhel7 \
--boot hd \
--disk ${vol_path} \
--network bridge=${VNET:-br0} \
--graphics vnc \
--video cirrus \
--memballoon model=virtio \
--noautoconsole
rmdir ${mountpoint}