Index: head/release/Makefile.vm =================================================================== --- head/release/Makefile.vm (revision 307007) +++ head/release/Makefile.vm (revision 307008) @@ -1,150 +1,151 @@ # # $FreeBSD$ # # # Makefile for building virtual machine and cloud provider disk images. # VMTARGETS= vm-image VMFORMATS?= vhd vmdk qcow2 raw VMSIZE?= 20G +SWAPSIZE?= 1G VMBASE?= vm VHD_DESC= Azure, VirtualPC, Hyper-V, Xen disk image VMDK_DESC= VMWare, VirtualBox disk image QCOW2_DESC= Qemu, KVM disk image RAW_DESC= Unformatted raw disk image CLOUDWARE?= EC2 \ GCE \ VAGRANT-VIRTUALBOX \ VAGRANT-VMWARE AZURE_FORMAT= vhdf AZURE_DESC= Microsoft Azure platform image AZURE_DISK= ${OSRELEASE}.${AZURE_FORMAT} EC2_FORMAT= raw EC2_DESC= Amazon EC2 image EC2_DISK= ${OSRELEASE}.${EC2_FORMAT} GCE_FORMAT= raw GCE_DESC= Google Compute Engine image GCE_DISK= disk.${GCE_FORMAT} OPENSTACK_FORMAT=qcow2 OPENSTACK_DESC= OpenStack platform image OPENSTACK_DISK= ${OSRELEASE}.${OPENSTACK_FORMAT} VAGRANT-VIRTUALBOX_FORMAT= vmdk VAGRANT-VIRTUALBOX_DESC= Vagrant Image for VirtualBox VAGRANT-VIRTUALBOX_DISK= ${OSRELEASE}.vbox.${VAGRANT_FORMAT} VAGRANT-VMWARE_FORMAT= vmdk VAGRANT-VMWARE_DESC= Vagrant Image for VMWare VAGRANT-VMWARE_DISK= ${OSRELEASE}.vmware.${VAGRANT_FORMAT} .if defined(WITH_CLOUDWARE) && !empty(WITH_CLOUDWARE) && !empty(CLOUDWARE) . for _CW in ${CLOUDWARE} CLOUDTARGETS+= cw-${_CW:tl} CLEANDIRS+= cw-${_CW:tl} CLEANFILES+= ${_CW:tl}.img \ ${_CW:tl}.${${_CW:tu}_FORMAT} \ ${_CW:tl}.${${_CW:tu}_FORMAT}.raw \ cw${_CW:tl}-package CLOUDPACKAGE+= cw${_CW:tl}-package ${_CW:tu}IMAGE= ${_CW:tl}.${${_CW:tu}_FORMAT} . if exists(${.CURDIR}/tools/${_CW:tl}.conf) && !defined(${_CW:tu}CONF) ${_CW:tu}CONF?= ${.CURDIR}/tools/${_CW:tl}.conf . endif cw-${_CW:tl}: mkdir -p ${.OBJDIR}/${.TARGET} env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \ -i ${.OBJDIR}/${_CW:tl}.img -s ${VMSIZE} -f ${${_CW}_FORMAT} \ -S ${WORLDDIR} -o ${.OBJDIR}/${${_CW}IMAGE} -c ${${_CW}CONF} touch ${.TARGET} cw${_CW:tl}-package: @# Special target to handle packaging cloud images in the formats @# specific to each hosting provider. .if exists(${.CURDIR}/tools/${_CW:tl}-package.sh) env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ ${.CURDIR}/tools/${_CW:tl}-package.sh \ -D ${DESTDIR} -I ${${_CW}_DISK} -S ${WORLDDIR} .endif touch ${.TARGET} . endfor .endif .if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) CLEANDIRS+= ${VMTARGETS} . for FORMAT in ${VMFORMATS} CLEANFILES+= ${FORMAT}.img CLEANFILES+= ${VMBASE}.${FORMAT} . endfor .endif vm-base: vm-image vm-image: .if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) . for FORMAT in ${VMFORMATS} mkdir -p ${.OBJDIR}/${.TARGET} env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ ${.CURDIR}/scripts/mk-vmimage.sh \ -C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \ -i ${.OBJDIR}/${FORMAT}.img -s ${VMSIZE} -f ${FORMAT} \ -S ${WORLDDIR} -o ${.OBJDIR}/${VMBASE}.${FORMAT} . endfor .endif touch ${.TARGET} vm-cloudware: ${CLOUDTARGETS} list-vmtargets: list-cloudware @${ECHO} @${ECHO} "Supported virtual machine disk image formats:" .for FORMAT in ${VMFORMATS:tu} @${ECHO} " ${FORMAT:tl}: ${${FORMAT}_DESC}" .endfor list-cloudware: .if !empty(CLOUDWARE) @${ECHO} @${ECHO} "Supported cloud hosting provider images:" . for _CW in ${CLOUDWARE} @${ECHO} " ${_CW:tu}: ${${_CW:tu}_DESC}" . endfor .endif vm-install: .if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) mkdir -p ${DESTDIR}/vmimages . for FORMAT in ${VMFORMATS} cp -p ${VMBASE}.${FORMAT} \ ${DESTDIR}/vmimages/${OSRELEASE}.${FORMAT} . endfor . if defined(WITH_COMPRESSED_VMIMAGES) && !empty(WITH_COMPRESSED_VMIMAGES) . for FORMAT in ${VMFORMATS} # Don't keep the originals. There is a copy in ${.OBJDIR} if needed. ${XZ_CMD} ${DESTDIR}/vmimages/${OSRELEASE}.${FORMAT} . endfor . endif cd ${DESTDIR}/vmimages && sha512 ${OSRELEASE}* > \ ${DESTDIR}/vmimages/CHECKSUM.SHA512 cd ${DESTDIR}/vmimages && sha256 ${OSRELEASE}* > \ ${DESTDIR}/vmimages/CHECKSUM.SHA256 .endif vm-release: .if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) ${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${VMTARGETS} .endif cloudware-release: .if defined(WITH_CLOUDWARE) && !empty(WITH_CLOUDWARE) && !empty(CLOUDWARE) ${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${CLOUDTARGETS} .endif .include "${.CURDIR}/Makefile.ec2" .include "${.CURDIR}/Makefile.azure" .include "${.CURDIR}/Makefile.gce" .include "${.CURDIR}/Makefile.vagrant" Index: head/release/tools/vmimage.subr =================================================================== --- head/release/tools/vmimage.subr (revision 307007) +++ head/release/tools/vmimage.subr (revision 307008) @@ -1,234 +1,234 @@ #!/bin/sh # # $FreeBSD$ # # # Common functions for virtual machine image build scripts. # export PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" trap "cleanup" INT QUIT TRAP ABRT TERM write_partition_layout() { if [ -z "${NOSWAP}" ]; then - SWAPOPT="-p freebsd-swap/swapfs::1G" + SWAPOPT="-p freebsd-swap/swapfs::${SWAPSIZE}" fi _OBJDIR="$(make -C ${WORLDDIR} -V .OBJDIR)" if [ -d "${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}" ]; then BOOTFILES="/${_OBJDIR%%/usr/src}/${TARGET}.${TARGET_ARCH}/usr/src/sys/boot" else BOOTFILES="/${_OBJDIR}/sys/boot" fi case "${TARGET}:${TARGET_ARCH}" in amd64:amd64 | i386:i386) mkimg -s gpt -f ${VMFORMAT} \ -b ${BOOTFILES}/i386/pmbr/pmbr \ -p freebsd-boot/bootfs:=${BOOTFILES}/i386/gptboot/gptboot \ ${SWAPOPT} \ -p freebsd-ufs/rootfs:=${VMBASE} \ -o ${VMIMAGE} ;; arm64:aarch64) mkimg -s mbr -f ${VMFORMAT} \ -p efi:=${BOOTFILES}/efi/boot1/boot1.efifat \ -p freebsd:=${VMBASE} \ -o ${VMIMAGE} ;; powerpc:powerpc*) mkimg -s apm -f ${VMFORMAT} \ -p apple-boot/bootfs:=${BOOTFILES}/powerpc/boot1.chrp/boot1.hfs \ ${SWAPOPT} \ -p freebsd-ufs/rootfs:=${VMBASE} \ -o ${VMIMAGE} ;; *) # ENOTSUPP return 1 ;; esac return 0 } err() { printf "${@}\n" cleanup return 1 } cleanup() { if [ -c "${DESTDIR}/dev/null" ]; then umount_loop ${DESTDIR}/dev 2>/dev/null fi umount_loop ${DESTDIR} if [ ! -z "${mddev}" ]; then mdconfig -d -u ${mddev} fi return 0 } vm_create_base() { # Creates the UFS root filesystem for the virtual machine disk, # written to the formatted disk image with mkimg(1). mkdir -p ${DESTDIR} truncate -s ${VMSIZE} ${VMBASE} mddev=$(mdconfig -f ${VMBASE}) newfs -L rootfs /dev/${mddev} mount /dev/${mddev} ${DESTDIR} return 0 } vm_copy_base() { # Creates a new UFS root filesystem and copies the contents of the # current root filesystem into it. This produces a "clean" disk # image without any remnants of files which were created temporarily # during image-creation and have since been deleted (e.g., downloaded # package archives). mkdir -p ${DESTDIR}/old mdold=$(mdconfig -f ${VMBASE}) mount /dev/${mdold} ${DESTDIR}/old truncate -s ${VMSIZE} ${VMBASE}.tmp mkdir -p ${DESTDIR}/new mdnew=$(mdconfig -f ${VMBASE}.tmp) newfs -L rootfs /dev/${mdnew} mount /dev/${mdnew} ${DESTDIR}/new tar -cf- -C ${DESTDIR}/old . | tar -xUf- -C ${DESTDIR}/new umount_loop /dev/${mdold} rmdir ${DESTDIR}/old mdconfig -d -u ${mdold} umount_loop /dev/${mdnew} rmdir ${DESTDIR}/new tunefs -n enable /dev/${mdnew} mdconfig -d -u ${mdnew} mv ${VMBASE}.tmp ${VMBASE} } vm_install_base() { # Installs the FreeBSD userland/kernel to the virtual machine disk. cd ${WORLDDIR} && \ make DESTDIR=${DESTDIR} \ installworld installkernel distribution || \ err "\n\nCannot install the base system to ${DESTDIR}." echo '# Custom /etc/fstab for FreeBSD VM images' \ > ${DESTDIR}/etc/fstab echo "/dev/${ROOTLABEL}/rootfs / ufs rw 1 1" \ >> ${DESTDIR}/etc/fstab if [ -z "${NOSWAP}" ]; then echo '/dev/gpt/swapfs none swap sw 0 0' \ >> ${DESTDIR}/etc/fstab fi mkdir -p ${DESTDIR}/dev mount -t devfs devfs ${DESTDIR}/dev chroot ${DESTDIR} /usr/bin/newaliases chroot ${DESTDIR} /etc/rc.d/ldconfig forcestart umount_loop ${DESTDIR}/dev cp /etc/resolv.conf ${DESTDIR}/etc/resolv.conf return 0 } vm_extra_install_base() { # Prototype. When overridden, runs extra post-installworld commands # as needed, based on the target virtual machine image or cloud # provider image target. return 0 } vm_extra_enable_services() { if [ ! -z "${VM_RC_LIST}" ]; then for _rcvar in ${VM_RC_LIST}; do echo ${_rcvar}_enable="YES" >> ${DESTDIR}/etc/rc.conf done fi return 0 } vm_extra_install_packages() { if [ -z "${VM_EXTRA_PACKAGES}" ]; then return 0 fi mkdir -p ${DESTDIR}/dev mount -t devfs devfs ${DESTDIR}/dev chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ /usr/sbin/pkg bootstrap -y chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ /usr/sbin/pkg install -y ${VM_EXTRA_PACKAGES} umount_loop ${DESTDIR}/dev return 0 } vm_extra_install_ports() { # Prototype. When overridden, installs additional ports within the # virtual machine environment. return 0 } vm_extra_pre_umount() { # Prototype. When overridden, performs additional tasks within the # virtual machine environment prior to unmounting the filesystem. # Note: When overriding this function, removing resolv.conf in the # disk image must be included. rm -f ${DESTDIR}/etc/resolv.conf return 0 } vm_extra_pkg_rmcache() { if [ -e ${DESTDIR}/usr/local/sbin/pkg ]; then chroot ${DESTDIR} env ASSUME_ALWAYS_YES=yes \ /usr/local/sbin/pkg clean -y -a fi return 0 } umount_loop() { DIR=$1 i=0 sync while ! umount ${DIR}; do i=$(( $i + 1 )) if [ $i -ge 10 ]; then # This should never happen. But, it has happened. echo "Cannot umount(8) ${DIR}" echo "Something has gone horribly wrong." return 1 fi sleep 1 done return 0 } vm_create_disk() { echo "Creating image... Please wait." echo write_partition_layout || return 1 return 0 } vm_extra_create_disk() { return 0 }