1278985Sgjb#!/bin/sh 2278985Sgjb# 3278985Sgjb# $FreeBSD: stable/10/release/tools/vmimage.subr 325491 2017-11-06 18:07:23Z gjb $ 4278985Sgjb# 5278985Sgjb# 6278985Sgjb# Common functions for virtual machine image build scripts. 7278985Sgjb# 8278985Sgjb 9278985Sgjbexport PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 10278985Sgjbtrap "cleanup" INT QUIT TRAP ABRT TERM 11278985Sgjb 12278985Sgjbwrite_partition_layout() { 13278985Sgjb if [ -z "${NOSWAP}" ]; then 14318811Snp SWAPOPT="-p freebsd-swap/swapfs::${SWAPSIZE}" 15278985Sgjb fi 16278985Sgjb 17282111Sgjb _OBJDIR="$(make -C ${WORLDDIR} -V .OBJDIR)" 18317442Sgjb _OBJDIR="$(realpath ${_OBJDIR})" 19282111Sgjb if [ -d "${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}" ]; then 20282111Sgjb BOOTFILES="/${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}/usr/src/sys/boot" 21282111Sgjb else 22282111Sgjb BOOTFILES="/${_OBJDIR}/sys/boot" 23282111Sgjb fi 24282111Sgjb 25278985Sgjb case "${TARGET}:${TARGET_ARCH}" in 26278985Sgjb amd64:amd64 | i386:i386) 27282877Sgjb mkimg -s gpt -f ${VMFORMAT} \ 28282877Sgjb -b ${BOOTFILES}/i386/pmbr/pmbr \ 29282111Sgjb -p freebsd-boot/bootfs:=${BOOTFILES}/i386/gptboot/gptboot \ 30278985Sgjb ${SWAPOPT} \ 31278985Sgjb -p freebsd-ufs/rootfs:=${VMBASE} \ 32278985Sgjb -o ${VMIMAGE} 33278985Sgjb ;; 34278985Sgjb powerpc:powerpc*) 35282877Sgjb mkimg -s apm -f ${VMFORMAT} \ 36282111Sgjb -p apple-boot/bootfs:=${BOOTFILES}/powerpc/boot1.chrp/boot1.hfs \ 37278985Sgjb ${SWAPOPT} \ 38278985Sgjb -p freebsd-ufs/rootfs:=${VMBASE} \ 39278985Sgjb -o ${VMIMAGE} 40278985Sgjb ;; 41278985Sgjb *) 42278985Sgjb # ENOTSUPP 43278985Sgjb return 1 44278985Sgjb ;; 45278985Sgjb esac 46278985Sgjb 47278985Sgjb return 0 48278985Sgjb} 49278985Sgjb 50278985Sgjberr() { 51278985Sgjb printf "${@}\n" 52278985Sgjb cleanup 53278985Sgjb return 1 54278985Sgjb} 55278985Sgjb 56278985Sgjbcleanup() { 57282111Sgjb if [ -c "${DESTDIR}/dev/null" ]; then 58282111Sgjb umount_loop ${DESTDIR}/dev 2>/dev/null 59282111Sgjb fi 60282111Sgjb umount_loop ${DESTDIR} 61278985Sgjb if [ ! -z "${mddev}" ]; then 62278985Sgjb mdconfig -d -u ${mddev} 63278985Sgjb fi 64278985Sgjb 65278985Sgjb return 0 66278985Sgjb} 67278985Sgjb 68278985Sgjbvm_create_base() { 69278985Sgjb # Creates the UFS root filesystem for the virtual machine disk, 70278985Sgjb # written to the formatted disk image with mkimg(1). 71278985Sgjb 72278985Sgjb mkdir -p ${DESTDIR} 73278985Sgjb truncate -s ${VMSIZE} ${VMBASE} 74278985Sgjb mddev=$(mdconfig -f ${VMBASE}) 75282111Sgjb newfs /dev/${mddev} 76278985Sgjb mount /dev/${mddev} ${DESTDIR} 77278985Sgjb 78278985Sgjb return 0 79278985Sgjb} 80278985Sgjb 81282111Sgjbvm_copy_base() { 82282111Sgjb # Creates a new UFS root filesystem and copies the contents of the 83282111Sgjb # current root filesystem into it. This produces a "clean" disk 84282111Sgjb # image without any remnants of files which were created temporarily 85282111Sgjb # during image-creation and have since been deleted (e.g., downloaded 86282111Sgjb # package archives). 87282111Sgjb 88282111Sgjb mkdir -p ${DESTDIR}/old 89282111Sgjb mdold=$(mdconfig -f ${VMBASE}) 90282111Sgjb mount /dev/${mdold} ${DESTDIR}/old 91282111Sgjb 92282111Sgjb truncate -s ${VMSIZE} ${VMBASE}.tmp 93282111Sgjb mkdir -p ${DESTDIR}/new 94282111Sgjb mdnew=$(mdconfig -f ${VMBASE}.tmp) 95282111Sgjb newfs /dev/${mdnew} 96282111Sgjb mount /dev/${mdnew} ${DESTDIR}/new 97282111Sgjb 98282111Sgjb tar -cf- -C ${DESTDIR}/old . | tar -xUf- -C ${DESTDIR}/new 99282111Sgjb 100282111Sgjb umount_loop /dev/${mdold} 101282111Sgjb rmdir ${DESTDIR}/old 102282111Sgjb mdconfig -d -u ${mdold} 103282111Sgjb 104282111Sgjb umount_loop /dev/${mdnew} 105282111Sgjb rmdir ${DESTDIR}/new 106288468Sgjb tunefs -n enable /dev/${mdnew} 107282111Sgjb mdconfig -d -u ${mdnew} 108282111Sgjb mv ${VMBASE}.tmp ${VMBASE} 109282111Sgjb} 110282111Sgjb 111278985Sgjbvm_install_base() { 112278985Sgjb # Installs the FreeBSD userland/kernel to the virtual machine disk. 113278985Sgjb 114278985Sgjb cd ${WORLDDIR} && \ 115278985Sgjb make DESTDIR=${DESTDIR} \ 116278985Sgjb installworld installkernel distribution || \ 117278985Sgjb err "\n\nCannot install the base system to ${DESTDIR}." 118278985Sgjb 119323815Sgjb # Bootstrap etcupdate(8) and mergemaster(8) databases. 120323815Sgjb mkdir -p ${DESTDIR}/var/db/etcupdate 121323815Sgjb etcupdate extract -B \ 122323815Sgjb -M "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ 123323815Sgjb -s ${WORLDDIR} -d ${DESTDIR}/var/db/etcupdate 124323815Sgjb sh ${WORLDDIR}/release/scripts/mm-mtree.sh -m ${WORLDDIR} \ 125323815Sgjb -F "TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH}" \ 126323815Sgjb -D ${DESTDIR} 127323815Sgjb 128278985Sgjb echo '# Custom /etc/fstab for FreeBSD VM images' \ 129278985Sgjb > ${DESTDIR}/etc/fstab 130278985Sgjb echo '/dev/gpt/rootfs / ufs rw 1 1' \ 131278985Sgjb >> ${DESTDIR}/etc/fstab 132278985Sgjb if [ -z "${NOSWAP}" ]; then 133278985Sgjb echo '/dev/gpt/swapfs none swap sw 0 0' \ 134278985Sgjb >> ${DESTDIR}/etc/fstab 135278985Sgjb fi 136278985Sgjb 137325491Sgjb local hostname 138325491Sgjb hostname="$(echo $(uname -o) | tr '[:upper:]' '[:lower:]')" 139325491Sgjb echo "hostname=\"${hostname}\"" >> ${DESTDIR}/etc/rc.conf 140325491Sgjb 141278985Sgjb mkdir -p ${DESTDIR}/dev 142278985Sgjb mount -t devfs devfs ${DESTDIR}/dev 143278985Sgjb chroot ${DESTDIR} /usr/bin/newaliases 144278985Sgjb chroot ${DESTDIR} /etc/rc.d/ldconfig forcestart 145282111Sgjb umount_loop ${DESTDIR}/dev 146278985Sgjb 147278985Sgjb cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf 148278985Sgjb 149278985Sgjb return 0 150278985Sgjb} 151278985Sgjb 152278985Sgjbvm_extra_install_base() { 153278985Sgjb # Prototype. When overridden, runs extra post-installworld commands 154278985Sgjb # as needed, based on the target virtual machine image or cloud 155278985Sgjb # provider image target. 156278985Sgjb 157278985Sgjb return 0 158278985Sgjb} 159278985Sgjb 160278985Sgjbvm_extra_enable_services() { 161278985Sgjb if [ ! -z "${VM_RC_LIST}" ]; then 162278985Sgjb for _rcvar in ${VM_RC_LIST}; do 163278985Sgjb echo ${_rcvar}_enable="YES" >> ${DESTDIR}/etc/rc.conf 164278985Sgjb done 165278985Sgjb fi 166278985Sgjb 167319032Sgjb if [ -z "${VMCONFIG}" -o -c "${VMCONFIG}" ]; then 168319032Sgjb echo 'ifconfig_DEFAULT="DHCP inet6 accept_rtadv"' >> \ 169319032Sgjb ${DESTDIR}/etc/rc.conf 170319032Sgjb fi 171319032Sgjb 172278985Sgjb return 0 173278985Sgjb} 174278985Sgjb 175278985Sgjbvm_extra_install_packages() { 176278985Sgjb if [ -z "${VM_EXTRA_PACKAGES}" ]; then 177278985Sgjb return 0 178278985Sgjb fi 179278985Sgjb mkdir -p ${DESTDIR}/dev 180278985Sgjb mount -t devfs devfs ${DESTDIR}/dev 181278985Sgjb chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 182278985Sgjb /usr/sbin/pkg bootstrap -y 183278985Sgjb chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 184278985Sgjb /usr/sbin/pkg install -y ${VM_EXTRA_PACKAGES} 185282111Sgjb umount_loop ${DESTDIR}/dev 186278985Sgjb 187278985Sgjb return 0 188278985Sgjb} 189278985Sgjb 190278985Sgjbvm_extra_install_ports() { 191278985Sgjb # Prototype. When overridden, installs additional ports within the 192278985Sgjb # virtual machine environment. 193278985Sgjb 194278985Sgjb return 0 195278985Sgjb} 196278985Sgjb 197278985Sgjbvm_extra_pre_umount() { 198282262Sgjb # Prototype. When overridden, performs additional tasks within the 199282262Sgjb # virtual machine environment prior to unmounting the filesystem. 200282262Sgjb # Note: When overriding this function, removing resolv.conf in the 201282262Sgjb # disk image must be included. 202278985Sgjb 203278985Sgjb rm -f ${DESTDIR}/etc/resolv.conf 204278985Sgjb return 0 205278985Sgjb} 206278985Sgjb 207278985Sgjbvm_extra_pkg_rmcache() { 208278985Sgjb if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then 209278985Sgjb chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 210278985Sgjb /usr/local/sbin/pkg clean -y -a 211278985Sgjb fi 212278985Sgjb 213278985Sgjb return 0 214278985Sgjb} 215278985Sgjb 216282111Sgjbumount_loop() { 217282111Sgjb DIR=$1 218278985Sgjb i=0 219278985Sgjb sync 220282111Sgjb while ! umount ${DIR}; do 221278985Sgjb i=$(( $i + 1 )) 222278985Sgjb if [ $i -ge 10 ]; then 223278985Sgjb # This should never happen. But, it has happened. 224282111Sgjb echo "Cannot umount(8) ${DIR}" 225282111Sgjb echo "Something has gone horribly wrong." 226282111Sgjb return 1 227278985Sgjb fi 228278985Sgjb sleep 1 229278985Sgjb done 230278985Sgjb 231278985Sgjb return 0 232278985Sgjb} 233278985Sgjb 234278985Sgjbvm_create_disk() { 235278985Sgjb echo "Creating image... Please wait." 236278985Sgjb echo 237278985Sgjb 238278985Sgjb write_partition_layout || return 1 239278985Sgjb 240278985Sgjb return 0 241278985Sgjb} 242278985Sgjb 243278985Sgjbvm_extra_create_disk() { 244278985Sgjb 245278985Sgjb return 0 246278985Sgjb} 247278985Sgjb 248