vmimage.subr revision 282877
1#!/bin/sh 2# 3# $FreeBSD: stable/10/release/tools/vmimage.subr 282877 2015-05-14 04:21:04Z gjb $ 4# 5# 6# Common functions for virtual machine image build scripts. 7# 8 9export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 10trap "cleanup" INT QUIT TRAP ABRT TERM 11 12write_partition_layout() { 13 if [ -z "${NOSWAP}" ]; then 14 SWAPOPT="-p freebsd-swap/swapfs::1G" 15 fi 16 17 _OBJDIR="$(make -C ${WORLDDIR} -V .OBJDIR)" 18 if [ -d "${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}" ]; then 19 BOOTFILES="/${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}/usr/src/sys/boot" 20 else 21 BOOTFILES="/${_OBJDIR}/sys/boot" 22 fi 23 24 case "${TARGET}:${TARGET_ARCH}" in 25 amd64:amd64 | i386:i386) 26 mkimg -s gpt -f ${VMFORMAT} \ 27 -b ${BOOTFILES}/i386/pmbr/pmbr \ 28 -p freebsd-boot/bootfs:=${BOOTFILES}/i386/gptboot/gptboot \ 29 ${SWAPOPT} \ 30 -p freebsd-ufs/rootfs:=${VMBASE} \ 31 -o ${VMIMAGE} 32 ;; 33 powerpc:powerpc*) 34 mkimg -s apm -f ${VMFORMAT} \ 35 -p apple-boot/bootfs:=${BOOTFILES}/powerpc/boot1.chrp/boot1.hfs \ 36 ${SWAPOPT} \ 37 -p freebsd-ufs/rootfs:=${VMBASE} \ 38 -o ${VMIMAGE} 39 ;; 40 *) 41 # ENOTSUPP 42 return 1 43 ;; 44 esac 45 46 return 0 47} 48 49err() { 50 printf "${@}\n" 51 cleanup 52 return 1 53} 54 55cleanup() { 56 if [ -c "${DESTDIR}/dev/null" ]; then 57 umount_loop ${DESTDIR}/dev 2>/dev/null 58 fi 59 umount_loop ${DESTDIR} 60 if [ ! -z "${mddev}" ]; then 61 mdconfig -d -u ${mddev} 62 fi 63 64 return 0 65} 66 67vm_create_base() { 68 # Creates the UFS root filesystem for the virtual machine disk, 69 # written to the formatted disk image with mkimg(1). 70 71 mkdir -p ${DESTDIR} 72 truncate -s ${VMSIZE} ${VMBASE} 73 mddev=$(mdconfig -f ${VMBASE}) 74 newfs /dev/${mddev} 75 mount /dev/${mddev} ${DESTDIR} 76 77 return 0 78} 79 80vm_copy_base() { 81 # Creates a new UFS root filesystem and copies the contents of the 82 # current root filesystem into it. This produces a "clean" disk 83 # image without any remnants of files which were created temporarily 84 # during image-creation and have since been deleted (e.g., downloaded 85 # package archives). 86 87 mkdir -p ${DESTDIR}/old 88 mdold=$(mdconfig -f ${VMBASE}) 89 mount /dev/${mdold} ${DESTDIR}/old 90 91 truncate -s ${VMSIZE} ${VMBASE}.tmp 92 mkdir -p ${DESTDIR}/new 93 mdnew=$(mdconfig -f ${VMBASE}.tmp) 94 newfs /dev/${mdnew} 95 mount /dev/${mdnew} ${DESTDIR}/new 96 97 tar -cf- -C ${DESTDIR}/old . | tar -xUf- -C ${DESTDIR}/new 98 99 umount_loop /dev/${mdold} 100 rmdir ${DESTDIR}/old 101 mdconfig -d -u ${mdold} 102 103 umount_loop /dev/${mdnew} 104 rmdir ${DESTDIR}/new 105 tunefs -j enable /dev/${mdnew} 106 mdconfig -d -u ${mdnew} 107 mv ${VMBASE}.tmp ${VMBASE} 108} 109 110vm_install_base() { 111 # Installs the FreeBSD userland/kernel to the virtual machine disk. 112 113 cd ${WORLDDIR} && \ 114 make DESTDIR=${DESTDIR} \ 115 installworld installkernel distribution || \ 116 err "\n\nCannot install the base system to ${DESTDIR}." 117 118 echo '# Custom /etc/fstab for FreeBSD VM images' \ 119 > ${DESTDIR}/etc/fstab 120 echo '/dev/gpt/rootfs / ufs rw 1 1' \ 121 >> ${DESTDIR}/etc/fstab 122 if [ -z "${NOSWAP}" ]; then 123 echo '/dev/gpt/swapfs none swap sw 0 0' \ 124 >> ${DESTDIR}/etc/fstab 125 fi 126 127 mkdir -p ${DESTDIR}/dev 128 mount -t devfs devfs ${DESTDIR}/dev 129 chroot ${DESTDIR} /usr/bin/newaliases 130 chroot ${DESTDIR} /etc/rc.d/ldconfig forcestart 131 umount_loop ${DESTDIR}/dev 132 133 cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf 134 135 return 0 136} 137 138vm_extra_install_base() { 139 # Prototype. When overridden, runs extra post-installworld commands 140 # as needed, based on the target virtual machine image or cloud 141 # provider image target. 142 143 return 0 144} 145 146vm_extra_enable_services() { 147 if [ ! -z "${VM_RC_LIST}" ]; then 148 for _rcvar in ${VM_RC_LIST}; do 149 echo ${_rcvar}_enable="YES" >> ${DESTDIR}/etc/rc.conf 150 done 151 fi 152 153 return 0 154} 155 156vm_extra_install_packages() { 157 if [ -z "${VM_EXTRA_PACKAGES}" ]; then 158 return 0 159 fi 160 mkdir -p ${DESTDIR}/dev 161 mount -t devfs devfs ${DESTDIR}/dev 162 chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 163 /usr/sbin/pkg bootstrap -y 164 chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 165 /usr/sbin/pkg install -y ${VM_EXTRA_PACKAGES} 166 umount_loop ${DESTDIR}/dev 167 168 return 0 169} 170 171vm_extra_install_ports() { 172 # Prototype. When overridden, installs additional ports within the 173 # virtual machine environment. 174 175 return 0 176} 177 178vm_extra_pre_umount() { 179 # Prototype. When overridden, performs additional tasks within the 180 # virtual machine environment prior to unmounting the filesystem. 181 # Note: When overriding this function, removing resolv.conf in the 182 # disk image must be included. 183 184 rm -f ${DESTDIR}/etc/resolv.conf 185 return 0 186} 187 188vm_extra_pkg_rmcache() { 189 if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then 190 chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ 191 /usr/local/sbin/pkg clean -y -a 192 fi 193 194 return 0 195} 196 197umount_loop() { 198 DIR=$1 199 i=0 200 sync 201 while ! umount ${DIR}; do 202 i=$(( $i + 1 )) 203 if [ $i -ge 10 ]; then 204 # This should never happen. But, it has happened. 205 echo "Cannot umount(8) ${DIR}" 206 echo "Something has gone horribly wrong." 207 return 1 208 fi 209 sleep 1 210 done 211 212 return 0 213} 214 215vm_create_disk() { 216 echo "Creating image... Please wait." 217 echo 218 219 write_partition_layout || return 1 220 221 return 0 222} 223 224vm_extra_create_disk() { 225 226 return 0 227} 228 229