#!/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 < /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 < ${mountpoint}/boot/grub/grub.cfg < ${mountpoint}/etc/fstab < ${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}