1#!/bin/sh 2#- 3# Copyright (c) 2014 The FreeBSD Foundation 4# All rights reserved. 5# 6# This software was developed by Glen Barber under sponsorship 7# from the FreeBSD Foundation. 8# 9# Redistribution and use in source and binary forms, with or without 10# modification, are permitted provided that the following conditions 11# are met: 12# 1. Redistributions of source code must retain the above copyright 13# notice, this list of conditions and the following disclaimer. 14# 2. Redistributions in binary form must reproduce the above copyright 15# notice, this list of conditions and the following disclaimer in the 16# documentation and/or other materials provided with the distribution. 17# 18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28# SUCH DAMAGE. 29# 30# mk-vmimage.sh: Create virtual machine disk images in various formats. 31# 32# $FreeBSD$ 33# 34 35PATH="/bin:/usr/bin:/sbin:/usr/sbin" 36export PATH 37 38usage() { 39 echo "$(basename ${0}) <command> <target> [...]" 40 if [ -z "${MAKEFLAGS}" ]; then 41 echo "It is probably not safe to run this by hand yet..." 42 fi 43 exit 1 44} 45 46panic() { 47 rc="${1}" 48 shift 1 49 msg="${@}" 50 printf "${msg}\n" 51 if [ ! -z "${mddev}" ]; then 52 mdconfig -d -u ${mddev} 53 fi 54 # Do not allow one failure case to chain through any remaining image 55 # builds. 56 exit 0 57} 58 59vm_create_baseimage() { 60 # Creates the UFS root filesystem for the virtual machine disk, 61 # written to the formatted disk image with mkimg(1). 62 i=0 63 mkdir -p ${DESTDIR} 64 truncate -s ${VMSIZE} ${VMBASE} 65 mddev=$(mdconfig -f ${VMBASE}) 66 newfs -j /dev/${mddev} 67 mount /dev/${mddev} ${DESTDIR} 68 cd ${WORLDDIR} && \ 69 ${IMAKE} DESTDIR=${DESTDIR} \ 70 installworld installkernel distribution || \ 71 panic 1 "\n\nCannot install the base system to ${DESTDIR}." 72 chroot ${DESTDIR} /usr/bin/newaliases 73 echo '# Custom /etc/fstab for FreeBSD VM images' \ 74 > ${DESTDIR}/etc/fstab 75 echo '/dev/gpt/rootfs / ufs rw 2 2' \ 76 >> ${DESTDIR}/etc/fstab 77 echo '/dev/gpt/swapfs none swap sw 0 0' \ 78 >> ${DESTDIR}/etc/fstab 79 sync 80 while ! umount ${DESTDIR}; do 81 i=$(( $i + 1 )) 82 if [ $i -ge 10 ]; then 83 # This should never happen. But, it has happened. 84 msg="Cannot umount(8) ${DESTDIR}\n" 85 msg="${msg}Something has gone horribly wrong." 86 panic 1 "${msg}" 87 fi 88 sleep 1 89 done 90 91 return 0 92} 93 94vm_create_vmdisk() { 95 mkimg_version=$(mkimg --version 2>/dev/null | awk '{print $2}') 96 97 # We need mkimg(1) '--version' output, at minimum, to be able to 98 # tell what virtual machine disk image formats are available. 99 # Bail if mkimg(1) reports an empty '--version' value. 100 if [ -z "${mkimg_version}" ]; then 101 msg="Cannot determine mkimg(1) version.\n" 102 msg="${msg}Cannot continue without a known mkimg(1) version." 103 panic 0 "${msg}" 104 fi 105 106 if ! mkimg --formats 2>/dev/null | grep -q ${FORMAT}; then 107 panic 0 "'${FORMAT}' is not supported by this mkimg(1).\n" 108 fi 109 110 case ${FORMAT} in 111 vhd) 112 mkimg_format=vhdf 113 ;; 114 *) 115 mkimg_format=${FORMAT} 116 ;; 117 esac 118 119 mkimg -f ${mkimg_format} -s gpt \ 120 -b /boot/pmbr -p freebsd-boot/bootfs:=/boot/gptboot \ 121 -p freebsd-swap/swapfs::1G \ 122 -p freebsd-ufs/rootfs:=${VMBASE} \ 123 -o ${VMIMAGE} 124 125 return 0 126} 127 128main() { 129 cmd="${1}" 130 131 case ${TARGET}/${TARGET_ARCH} in 132 amd64/amd64|i386/i386) 133 # FALLTHROUGH 134 ;; 135 *) 136 # EX_CANTCREAT 137 return 0 138 ;; 139 esac 140 141 case ${cmd} in 142 vm-base) 143 eval vm_create_baseimage "$@" || return 0 144 ;; 145 vm-image) 146 eval vm_create_vmdisk "$@" || return 0 147 ;; 148 *|\?) 149 usage 150 ;; 151 esac 152 153 return 0 154} 155 156main "$@" 157