scripts/create-vmachine.sh

147 lines
3.9 KiB
Bash
Executable File

#!/bin/bash
# Creates a new virtual machine from the given stage4 tarball
DOMNAME="$1"
STAGE_TBZ="$2"
VMNAME=$(echo "${DOMNAME}" | tr '[:upper:]' '[:lower:]')
VM_FQDN="${VMNAME}.$(hostname -d)"
if [[ -z $STAGE_TBZ || -z $VMNAME ]]; then
echo "Usage: $(basename $0) <vmname> <stage4-tarball>" >&2
exit 2
fi
: ${VG:=vmachines}
: ${POOL:=LVM}
: ${DOMXML_TMPL:=/etc/libvirt/qemu/_template.xml}
: ${MOUNTPOINT:=/mnt/new_vmachine}
: ${PORTAGE_PROFILE:="default/linux/amd64/13.0"}
: ${VM_TZ:=America/Chicago}
quit() {
exit "$@"
}
cleanup() {
local mnt
echo "Failed! Cleaning up..."
sync ; sync ; sync
if [ -n "${MOUNTPOINT}" ]; then
for d in home usr var run tmp ""; do
mnt="${MOUNTPOINT}"/$d
mountpoint -q "${mnt}" && umount -l "${mnt}"
done
fi
vgchange -an ${VMNAME}
lvchange -an ${VG}/${VMNAME}
virsh -c qemu:///system vol-delete ${VMNAME} ${POOL}
}
while [[ -z ${VM_ROOTPW} ]]; do
read -sp 'New VM root password: ' VM_ROOTPW
echo
read -sp 'Confirm root password: ' confirm_rootpw
echo
if [[ ${VM_ROOTPW} != ${confirm_rootpw} ]]; then
echo "Passwords don't match" >&2
unset VM_ROOTPW
fi
done
set -e
PORTDIR=$(portageq envvar PORTDIR)
DISTDIR=$(portageq envvar DISTDIR)
PKGDIR=$(portageq envvar PKGDIR)
if lvdisplay ${VG}/${VMNAME} >/dev/null 2>&1; then
echo "ERROR: Logical volume ${VMNAME} already exists in group ${VG}" >&2
exit 1
fi
echo "Creating storage volume..."
virsh -c qemu:///system vol-create-as ${POOL} ${VMNAME} 2G
echo "Creating LVM volumes..."
pvcreate /dev/${VG}/${VMNAME}
vgcreate ${VMNAME} /dev/${VG}/${VMNAME}
lvcreate -nroot -L100M ${VMNAME}
lvcreate -nhome -L200M ${VMNAME}
lvcreate -nvar -L400M ${VMNAME}
lvcreate -nusr -l100%FREE ${VMNAME}
trap "quit" INT TERM
trap "cleanup" EXIT
echo "Creating XFS filesystems..."
for fs in root home usr var; do
mkfs.xfs -L$fs -q /dev/${VMNAME}/$fs
done
echo "Mounting filesystems..."
[[ ! -d "${MOUNTPOINT}" ]] && mkdir -p "${MOUNTPOINT}"
mount /dev/${VMNAME}/root "${MOUNTPOINT}"
for fs in home usr var; do
mkdir "${MOUNTPOINT}"/$fs
mount /dev/${VMNAME}/$fs "${MOUNTPOINT}"/$fs
done
mkdir "${MOUNTPOINT}"/run
mount -t tmpfs tmpfs "${MOUNTPOINT}"/run
echo "Extracting stage tarball..."
tar -xjpf "${STAGE_TBZ}" -C "${MOUNTPOINT}"
echo "Setting hostname..."
sed -i "s/localhost/${VMNAME}/" "${MOUNTPOINT}"/etc/conf.d/hostname
echo "Setting time zone..."
rm -f "${MOUNTPOINT}"/etc/localtime
ln -s /usr/share/zoneinfo/${VM_TZ} "${MOUNTPOINT}"/etc/localtime
echo ${VM_TZ} > "${MOUNTPOINT}"/etc/timezone
echo "Configuring network..."
echo 'config_eth0="dhcp"' > "${MOUNTPOINT}"/etc/conf.d/net
ln -s net.lo "${MOUNTPOINT}"/etc/init.d/net.eth0
ln -s /etc/init.d/net.eth0 "${MOUNTPOINT}"/etc/runlevels/default/
for keytype in dsa rsa ecdsa; do
key="${MOUNTPOINT}"/etc/ssh/ssh_host_${keytype}_key
echo "Creating ${keytype} SSH host key..."
ssh-keygen -t ${keytype} -f "${key}" -N '' || true
done
echo "Configuring fstab..."
cat << EOF > "${MOUNTPOINT}"/etc/fstab
/dev/${VMNAME}/root / xfs ro,noatime 0 1
/dev/${VMNAME}/usr /usr xfs ro,noatime 0 2
/dev/${VMNAME}/var /var xfs noatime 0 2
/dev/${VMNAME}/home /home xfs noatime 0 2
tmpfs /tmp tmpfs defaults 0 0
EOF
echo "Creating read-only root filesystem compatibility symlinks..."
rm -f "${MOUNTPOINT}"/etc/{resolv,ntp}.conf
rm -f "${MOUNTPOINT}"/etc/mtab
ln -s /proc/self/mounts "${MOUNTPOINT}"/etc/mtab
ln -s /run/resolv.conf "${MOUNTPOINT}"/etc/resolv.conf
ln -s /run/ntp.conf "${MOUNTPOINT}"/etc/ntp.conf
echo "Setting root password..."
echo "root:${VM_ROOTPW}" | chroot "${MOUNTPOINT}" chpasswd
echo "Enabling serial console..."
sed -i 's/#s0/s0/' "${MOUNTPOINT}"/etc/inittab
trap - INT TERM EXIT
echo "Cleaning up..."
umount "${MOUNTPOINT}"/{run,usr,var,home,}
vgchange -an ${VMNAME}
echo "Creating libvirt domain..."
virsh -c qemu:///system define <(m4 -P -DNAME="${DOMNAME}" "${DOMXML_TMPL}")
echo "Starting virtual machine..."
virsh -c qemu:///system start ${DOMNAME}