diff --git a/release/Makefile b/release/Makefile index 6b4517dc4377..8a6ece7d1b58 100644 --- a/release/Makefile +++ b/release/Makefile @@ -23,6 +23,9 @@ # WITH_DVD: if set, generate dvd1.iso # WITH_COMPRESSED_IMAGES: if set, compress installation images with xz(1) # (uncompressed images are not removed) +# WITH_VMIMAGES: if set, build virtual machine images with the release +# WITH_COMPRESSED_VMIMAGES: if set, compress virtual machine disk images +# with xz(1) (extremely time consuming) # TARGET/TARGET_ARCH: architecture of built release # @@ -94,6 +97,11 @@ IMAGES+= memstick.img IMAGES+= mini-memstick.img .endif +VMTARGETS= vm-base vm-image +VMFORMATS?= vhd vmdk qcow2 raw +VMSIZE?= 20G +VMBASE?= vm + CLEANFILES= packagesystem *.txz MANIFEST system ${IMAGES} .if defined(WITH_COMPRESSED_IMAGES) && !empty(WITH_COMPRESSED_IMAGES) . for I in ${IMAGES} @@ -103,7 +111,16 @@ CLEANFILES+= ${I}.xz .if defined(WITH_DVD) && !empty(WITH_DVD) CLEANFILES+= pkg-stage .endif +.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) +CLEANFILES+= ${VMBASE}.img +. for FORMAT in ${VMFORMATS} +CLEANFILES+= ${VMBASE}.${FORMAT} +. endfor +.endif CLEANDIRS= dist ftp release bootonly dvd +.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) +CLEANDIRS+= ${VMTARGETS} +.endif beforeclean: chflags -R noschg . .include @@ -263,6 +280,9 @@ ftp: packagesystem release: ${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} obj ${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${RELEASE_TARGETS} +.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) + ${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} ${VMTARGETS} +.endif install: .if defined(DESTDIR) && !empty(DESTDIR) @@ -277,3 +297,44 @@ install: .endfor cd ${DESTDIR} && sha256 ${OSRELEASE}* > ${DESTDIR}/CHECKSUM.SHA256 cd ${DESTDIR} && md5 ${OSRELEASE}* > ${DESTDIR}/CHECKSUM.MD5 +.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) +# This is very time consuming, so defer it after the images are moved to +# the DESTDIR. +. for FORMAT in ${VMFORMATS} + # Don't keep the originals. There is a copy in ${.OBJDIR} if needed. + ${XZCMD} ${DESTDIR}/vmimages/${OSRELEASE}.${FORMAT} +. endfor +. endif + cd ${DESTDIR}/vmimages && sha256 ${OSRELEASE}* > \ + ${DESTDIR}/vmimages/CHECKSUM.SHA256 + cd ${DESTDIR}/vmimages && md5 ${OSRELEASE}* > \ + ${DESTDIR}/vmimages/CHECKSUM.MD5 +.endif + +vm-base: +.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) +. if exists(${.CURDIR}/${TARGET}/mk-vmimage.sh) + env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ + ${.CURDIR}/${TARGET}/mk-vmimage.sh ${.TARGET} \ + ${VMBASE}.img ${WORLDDIR} ${.OBJDIR}/${.TARGET} ${VMSIZE} +. endif +.endif + touch ${.TARGET} + +vm-image: vm-base +.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES) +. if exists(${.CURDIR}/${TARGET}/mk-vmimage.sh) +. for FORMAT in ${VMFORMATS} + env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ + ${.CURDIR}/${TARGET}/mk-vmimage.sh ${.TARGET} \ + ${VMBASE}.img ${FORMAT} ${VMBASE}.${FORMAT} +. endfor +. endif +.endif + touch ${.TARGET} diff --git a/release/amd64/mk-vmimage.sh b/release/amd64/mk-vmimage.sh new file mode 100755 index 000000000000..6ee148248cd5 --- /dev/null +++ b/release/amd64/mk-vmimage.sh @@ -0,0 +1,188 @@ +#!/bin/sh +#- +# Copyright (c) 2014 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Glen Barber under sponsorship +# from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# mk-vmimage.sh: Create virtual machine disk images in various formats. +# +# $FreeBSD$ +# + +PATH="/bin:/usr/bin:/sbin:/usr/sbin" +export PATH + +usage_vm_base() { + echo -n "$(basename ${0}) vm-base " + echo " " + return 0 +} + +usage_vm_image() { + echo -n "$(basename ${0}) vm-image " + echo " " + return 0 +} + +usage() { + echo "Usage:" + echo "$(basename ${0}) [vm-base|vm-image] [...]" + echo + usage_vm_base + echo + usage_vm_image + exit 1 +} + +panic() { + rc="${1}" + shift 1 + msg="${@}" + printf "${msg}\n" + if [ ! -z "${mddev}" ]; then + mdconfig -d -u ${mddev} + fi + # Do not allow one failure case to chain through any remaining image + # builds. + exit 0 +} + +vm_create_baseimage() { + # Creates the UFS root filesystem for the virtual machine disk, + # written to the formatted disk image with mkimg(1). + # + # Arguments: + # vm-base + + VMBASE="${1}" + WORLDDIR="${2}" + DESTDIR="${3}" + VMSIZE="${4}" + + if [ -z "${VMBASE}" -o -z "${WORLDDIR}" -o -z "${DESTDIR}" \ + -o -z "${VMSIZE}" ]; then + usage + fi + + i=0 + mkdir -p ${DESTDIR} + truncate -s ${VMSIZE} ${VMBASE} + mddev=$(mdconfig -f ${VMBASE}) + newfs -j /dev/${mddev} + mount /dev/${mddev} ${DESTDIR} + cd ${WORLDDIR} && \ + make DESTDIR=${DESTDIR} \ + installworld installkernel distribution || \ + panic 1 "\n\nCannot install the base system to ${DESTDIR}." + chroot ${DESTDIR} /usr/bin/newaliases + echo '# Custom /etc/fstab for FreeBSD VM images' \ + > ${DESTDIR}/etc/fstab + echo '/dev/gpt/rootfs / ufs rw 2 2' \ + >> ${DESTDIR}/etc/fstab + echo '/dev/gpt/swapfs none swap sw 0 0' \ + >> ${DESTDIR}/etc/fstab + sync + while ! umount ${DESTDIR}; do + i=$(( $i + 1 )) + if [ $i -ge 10 ]; then + # This should never happen. But, it has happened. + msg="Cannot umount(8) ${DESTDIR}\n" + msg="${msg}Something has gone horribly wrong." + panic 1 "${msg}" + fi + sleep 1 + done + + return 0 +} + +vm_create_vmdisk() { + # Creates the virtual machine disk image from the raw disk image. + # + # Arguments: + # vm-image " + + VMBASE="${1}" + FORMAT="${2}" + VMIMAGE="${3}" + + if [ -z "${VMBASE}" -o -z "${FORMAT}" -o -z "${VMIMAGE}" ]; then + usage + fi + + mkimg_version=$(mkimg --version 2>/dev/null | awk '{print $2}') + + # We need mkimg(1) '--version' output, at minimum, to be able to + # tell what virtual machine disk image formats are available. + # Bail if mkimg(1) reports an empty '--version' value. + if [ -z "${mkimg_version}" ]; then + msg="Cannot determine mkimg(1) version.\n" + msg="${msg}Cannot continue without a known mkimg(1) version." + panic 0 "${msg}" + fi + + if ! mkimg --formats 2>/dev/null | grep -q ${FORMAT}; then + panic 0 "'${FORMAT}' is not supported by this mkimg(1).\n" + fi + + case ${FORMAT} in + vhd) + mkimg_format=vhdf + ;; + *) + mkimg_format=${FORMAT} + ;; + esac + + mkimg -f ${mkimg_format} -s gpt \ + -b /boot/pmbr -p freebsd-boot/bootfs:=/boot/gptboot \ + -p freebsd-swap/swapfs::1G \ + -p freebsd-ufs/rootfs:=${VMBASE} \ + -o ${VMIMAGE} + + return 0 +} + +main() { + cmd="${1}" + shift 1 + + case ${cmd} in + vm-base) + eval vm_create_baseimage "$@" || return 0 + ;; + vm-image) + eval vm_create_vmdisk "$@" || return 0 + ;; + *|\?) + usage + ;; + esac + + return 0 +} + +main "$@" diff --git a/release/i386/mk-vmimage.sh b/release/i386/mk-vmimage.sh new file mode 100755 index 000000000000..6ee148248cd5 --- /dev/null +++ b/release/i386/mk-vmimage.sh @@ -0,0 +1,188 @@ +#!/bin/sh +#- +# Copyright (c) 2014 The FreeBSD Foundation +# All rights reserved. +# +# This software was developed by Glen Barber under sponsorship +# from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# mk-vmimage.sh: Create virtual machine disk images in various formats. +# +# $FreeBSD$ +# + +PATH="/bin:/usr/bin:/sbin:/usr/sbin" +export PATH + +usage_vm_base() { + echo -n "$(basename ${0}) vm-base " + echo " " + return 0 +} + +usage_vm_image() { + echo -n "$(basename ${0}) vm-image " + echo " " + return 0 +} + +usage() { + echo "Usage:" + echo "$(basename ${0}) [vm-base|vm-image] [...]" + echo + usage_vm_base + echo + usage_vm_image + exit 1 +} + +panic() { + rc="${1}" + shift 1 + msg="${@}" + printf "${msg}\n" + if [ ! -z "${mddev}" ]; then + mdconfig -d -u ${mddev} + fi + # Do not allow one failure case to chain through any remaining image + # builds. + exit 0 +} + +vm_create_baseimage() { + # Creates the UFS root filesystem for the virtual machine disk, + # written to the formatted disk image with mkimg(1). + # + # Arguments: + # vm-base + + VMBASE="${1}" + WORLDDIR="${2}" + DESTDIR="${3}" + VMSIZE="${4}" + + if [ -z "${VMBASE}" -o -z "${WORLDDIR}" -o -z "${DESTDIR}" \ + -o -z "${VMSIZE}" ]; then + usage + fi + + i=0 + mkdir -p ${DESTDIR} + truncate -s ${VMSIZE} ${VMBASE} + mddev=$(mdconfig -f ${VMBASE}) + newfs -j /dev/${mddev} + mount /dev/${mddev} ${DESTDIR} + cd ${WORLDDIR} && \ + make DESTDIR=${DESTDIR} \ + installworld installkernel distribution || \ + panic 1 "\n\nCannot install the base system to ${DESTDIR}." + chroot ${DESTDIR} /usr/bin/newaliases + echo '# Custom /etc/fstab for FreeBSD VM images' \ + > ${DESTDIR}/etc/fstab + echo '/dev/gpt/rootfs / ufs rw 2 2' \ + >> ${DESTDIR}/etc/fstab + echo '/dev/gpt/swapfs none swap sw 0 0' \ + >> ${DESTDIR}/etc/fstab + sync + while ! umount ${DESTDIR}; do + i=$(( $i + 1 )) + if [ $i -ge 10 ]; then + # This should never happen. But, it has happened. + msg="Cannot umount(8) ${DESTDIR}\n" + msg="${msg}Something has gone horribly wrong." + panic 1 "${msg}" + fi + sleep 1 + done + + return 0 +} + +vm_create_vmdisk() { + # Creates the virtual machine disk image from the raw disk image. + # + # Arguments: + # vm-image " + + VMBASE="${1}" + FORMAT="${2}" + VMIMAGE="${3}" + + if [ -z "${VMBASE}" -o -z "${FORMAT}" -o -z "${VMIMAGE}" ]; then + usage + fi + + mkimg_version=$(mkimg --version 2>/dev/null | awk '{print $2}') + + # We need mkimg(1) '--version' output, at minimum, to be able to + # tell what virtual machine disk image formats are available. + # Bail if mkimg(1) reports an empty '--version' value. + if [ -z "${mkimg_version}" ]; then + msg="Cannot determine mkimg(1) version.\n" + msg="${msg}Cannot continue without a known mkimg(1) version." + panic 0 "${msg}" + fi + + if ! mkimg --formats 2>/dev/null | grep -q ${FORMAT}; then + panic 0 "'${FORMAT}' is not supported by this mkimg(1).\n" + fi + + case ${FORMAT} in + vhd) + mkimg_format=vhdf + ;; + *) + mkimg_format=${FORMAT} + ;; + esac + + mkimg -f ${mkimg_format} -s gpt \ + -b /boot/pmbr -p freebsd-boot/bootfs:=/boot/gptboot \ + -p freebsd-swap/swapfs::1G \ + -p freebsd-ufs/rootfs:=${VMBASE} \ + -o ${VMIMAGE} + + return 0 +} + +main() { + cmd="${1}" + shift 1 + + case ${cmd} in + vm-base) + eval vm_create_baseimage "$@" || return 0 + ;; + vm-image) + eval vm_create_vmdisk "$@" || return 0 + ;; + *|\?) + usage + ;; + esac + + return 0 +} + +main "$@" diff --git a/release/release.conf.sample b/release/release.conf.sample index bdd5a8a05d91..c79ed9f87003 100644 --- a/release/release.conf.sample +++ b/release/release.conf.sample @@ -77,3 +77,24 @@ PORTBRANCH="ports/head@rHEAD" ## as TARGET/TARGET_ARCH. #CHROOT_MAKEENV= +## Set to a non-empty value to build virtual machine images as part of the +## release build. +#WITH_VMIMAGES= + +## Set to a non-empty value to compress virtual machine images with xz(1) +## as part of the release build. +#WITH_COMPRESSED_VMIMAGES= + +## If WITH_VMIMAGES is set to a non-empty value, this is the name of the +## file to use for the installed userland/kernel. +#VMBASE="vm" + +## If WITH_VMIMAGES is set to a non-empty value, this is the size of the +## virtual machine disk filesystem. Valid size values are described in +## the truncate(1) manual page. +#VMSIZE="20G" + +## If WITH_VMIMAGES is set to a non-empty value, this is a list of disk +## image formats to create. Valid values are listed in the mkimg(1) +## manual page, as well as 'mkimg --formats' output. +#VMFORMATS="vhdf vmdk qcow2 raw" diff --git a/release/release.sh b/release/release.sh index e99c403d22b0..87b36974070a 100755 --- a/release/release.sh +++ b/release/release.sh @@ -89,6 +89,11 @@ NOPORTS= WITH_DVD= WITH_COMPRESSED_IMAGES= +# Set to non-empty value to build virtual machine images as part of +# the release. +WITH_VMIMAGES= +WITH_COMPRESSED_VMIMAGES= + usage() { echo "Usage: $0 [-c release.conf]" exit 1 @@ -169,7 +174,7 @@ CHROOT_DMAKEFLAGS="${CONF_FILES}" RELEASE_WMAKEFLAGS="${MAKE_FLAGS} ${WORLD_FLAGS} ${ARCH_FLAGS} ${CONF_FILES}" RELEASE_KMAKEFLAGS="${MAKE_FLAGS} ${KERNEL_FLAGS} KERNCONF=\"${KERNEL}\" ${ARCH_FLAGS} ${CONF_FILES}" RELEASE_RMAKEFLAGS="${ARCH_FLAGS} KERNCONF=\"${KERNEL}\" ${CONF_FILES} \ - ${DOCPORTS} WITH_DVD=${WITH_DVD}" + ${DOCPORTS} WITH_DVD=${WITH_DVD} WITH_VMIMAGES=${WITH_VMIMAGES}" # Force src checkout if configured FORCE_SRC_KEY= @@ -274,4 +279,5 @@ eval chroot ${CHROOTDIR} make -C /usr/src ${RELEASE_KMAKEFLAGS} buildkernel eval chroot ${CHROOTDIR} make -C /usr/src/release ${RELEASE_RMAKEFLAGS} \ release eval chroot ${CHROOTDIR} make -C /usr/src/release ${RELEASE_RMAKEFLAGS} \ - install DESTDIR=/R WITH_COMPRESSED_IMAGES=${WITH_COMPRESSED_IMAGES} + install DESTDIR=/R WITH_COMPRESSED_IMAGES=${WITH_COMPRESSED_IMAGES} \ + WITH_COMPRESSED_VMIMAGES=${WITH_COMPRESSED_VMIMAGES} diff --git a/share/man/man7/release.7 b/share/man/man7/release.7 index 8fc75f3da4eb..93aec89618a9 100644 --- a/share/man/man7/release.7 +++ b/share/man/man7/release.7 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 11, 2014 +.Dd October 2, 2014 .Dt RELEASE 7 .Os .Sh NAME @@ -351,6 +351,61 @@ Set to the target directory within to check out .Va ${UBOOTSRC}/${UBOOTBRANCH} . .El +.Sh VIRTUAL MACHINE DISK IMAGES +The following +.Fa release.conf +variables are relevant only to virtual machine disk image builds: +.Bl -tag -width Ev +.It Va WITH_VMIMAGES +Set to a non-null value to build virtual machine disk images as part +of the release build. +.Va WITH_VMIMAGES +may also be specified as an envirionment variable passed to +.Xr make 1 . +.Pp +The option requires +.Xr mkimg 1 +version 20140927 or later. +.It Va WITH_COMPRESSED_VMIMAGES +Set to a non-null value to compress the virtual machine disk images with +.Xr xz 1 +as part of the +.Cm install +.Xr make 1 +target. +Note that compressing virtual machine disk images may take a very long +time on some systems. +.It Va VMBASE +Set to change the name of the resulting virtual machine disk image file. +The default value is +.Va vm . +.It Va VMSIZE +Set to change the size of the virtual machine disk capacity. +The default value is +.Va 20G . +See +.Xr truncate 1 +for valid values. +.Pp +Virtual machine disk images are, by default, created as sparse images. +When +.Va WITH_COMPRESSED_VMIMAGES +is used, the resulting files compressed with +.Xr xz 1 +compress to roughly the same size, regardless of the specified disk image +size. +.It Va VMFORMATS +Set to the target virtual disk image format(s) to create. +By default, the +.Va vhdf , Va vmdk , Va qcow2 , +and +.Va raw +formats are created. +See +.Xr mkimg 1 +for valid format values +.Pq requires version 20140927 or later . +.El .Sh MAKEFILE TARGETS The release makefile .Pq Pa src/release/Makefile @@ -407,6 +462,14 @@ Creates a directory named .Pa ftp containing the distribution files used in network installations and suitable for upload to an FTP mirror. +.It Cm vm-image +Creates virtual machine disk images in various formats. +The +.Cm vm-image +target requires the +.Va WITH_VMIMAGES +.Xr make 1 +envirionment variable to be set to a non-null value. .El .Pp Major subtargets called by targets above: