#!/bin/bash # Creates a new virtual machine from the given stage3 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) " >&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"} 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 -nhome -L200M ${VMNAME} lvcreate -nvar -L400M ${VMNAME} lvcreate -nroot -l100%FREE ${VMNAME} echo "Creating XFS filesystems..." for fs in root home 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 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}" cp -L /etc/resolv.conf "${MOUNTPOINT}/etc/resolv.conf" echo "Installing critical packages..." # Installing packages must be done in a chroot instead of using the $ROOT # Portage environment variable because several ebuilds use enewuser/enewgroup # to create system users, which creates the user on the host system, not the # target system. See Gentoo bug #53269 for details on the problem. mkdir "${MOUNTPOINT}"/usr/portage mount -obind "${PORTDIR}" "${MOUNTPOINT}"/usr/portage mount -obind "${DISTDIR}" "${MOUNTPOINT}"/usr/portage/distfiles mount -obind "${PKGDIR}" "${MOUNTPOINT}"/usr/portage/packages mount -t tmpfs tmpfs "${MOUNTPOINT}"/tmp mount -t proc proc "${MOUNTPOINT}"/proc mount -t sysfs sysfs "${MOUNTPOINT}"/sys cat < "${MOUNTPOINT}"/build-base.sh #!/bin/bash set -e export EMERGE_DEFAULT_OPTS="--binpkg-respect-use=y" export FEATURES="-news" env-update USE=-thin emerge -jkv xfsprogs nfs-utils lvm2 rc-update add lvm boot EOF chmod u+x "${MOUNTPOINT}"/build-base.sh chroot "${MOUNTPOINT}" /build-base.sh rm "${MOUNTPOINT}"/build-base.sh echo "Setting hostname..." sed -i "s/localhost/${VMNAME}/" "${MOUNTPOINT}"/etc/conf.d/hostname echo "Configuring network..." echo 'config_eth0="dhcp"' > "${MOUNTPOINT}"/etc/conf.d/net echo 'dhcpcd_eth0="-q"' >> "${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/ ln -s /etc/init.d/sshd "${MOUNTPOINT}"/etc/runlevels/default/ echo "Configuring fstab..." cat << EOF > "${MOUNTPOINT}"/etc/fstab LABEL=root / xfs noatime 0 1 LABEL=var /var xfs noatime 0 2 LABEL=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/mounts "${MOUNTPOINT}"/etc/mtab ln -s /run/resolv.conf "${MOUNTPOINT}"/etc/resolv.conf ln -s /run/ntp.conf "${MOUNTPOINT}"/etc/ntp.conf echo "Blanking root password..." sed -i 's/^root:.*/root::0:0:::::/' "${MOUNTPOINT}"/etc/shadow echo "Enabling serial console..." sed -i 's/#s0/s0/' "${MOUNTPOINT}"/etc/inittab echo "Cleaning up..." umount "${MOUNTPOINT}"/usr/portage/{packages,distfiles,} rmdir "${MOUNTPOINT}"/usr/portage umount "${MOUNTPOINT}"/{tmp,proc,sys,run,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}