mk-vmimage.sh revision 272794
1133066Sdfr#!/bin/sh 2133066Sdfr#- 3133066Sdfr# Copyright (c) 2014 The FreeBSD Foundation 4133066Sdfr# All rights reserved. 5133066Sdfr# 6133066Sdfr# This software was developed by Glen Barber under sponsorship 7133066Sdfr# from the FreeBSD Foundation. 8133066Sdfr# 9133066Sdfr# Redistribution and use in source and binary forms, with or without 10133066Sdfr# modification, are permitted provided that the following conditions 11133066Sdfr# are met: 12133066Sdfr# 1. Redistributions of source code must retain the above copyright 13133066Sdfr# notice, this list of conditions and the following disclaimer. 14133066Sdfr# 2. Redistributions in binary form must reproduce the above copyright 15133066Sdfr# notice, this list of conditions and the following disclaimer in the 16133066Sdfr# documentation and/or other materials provided with the distribution. 17133066Sdfr# 18133066Sdfr# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19133066Sdfr# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20133066Sdfr# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21133066Sdfr# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22133066Sdfr# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23133066Sdfr# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24133066Sdfr# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25133066Sdfr# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26133066Sdfr# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27133066Sdfr# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28133066Sdfr# SUCH DAMAGE. 29133066Sdfr# 30133066Sdfr# mk-vmimage.sh: Create virtual machine disk images in various formats. 31133066Sdfr# 32133066Sdfr# $FreeBSD: projects/release-vmimage/release/amd64/mk-vmimage.sh 272794 2014-10-09 03:50:38Z gjb $ 33133066Sdfr# 34133066Sdfr 35133066SdfrPATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 36133066Sdfrexport PATH 37133066Sdfr 38133066Sdfrvm_prebuild_setup() { 39133066Sdfr return 0 40133066Sdfr} 41133066Sdfr 42133066Sdfrvm_setup() { 43133066Sdfr return 0 44133066Sdfr} 45133066Sdfr 46133066Sdfrvm_postbuild_setup() { 47133066Sdfr return 0 48133066Sdfr} 49133066Sdfr 50133066Sdfrusage_vm_base() { 51133066Sdfr echo -n "$(basename ${0}) vm-base <base image> <source tree>" 52133066Sdfr echo " <dest dir> <disk image size>" 53133066Sdfr return 0 54133066Sdfr} 55133066Sdfr 56133066Sdfrusage_vm_image() { 57133066Sdfr echo -n "$(basename ${0}) vm-image <base image> <image format>" 58133066Sdfr echo " <output image>" 59133066Sdfr return 0 60} 61 62usage() { 63 echo "Usage:" 64 echo "$(basename ${0}) [vm-base|vm-image] [...]" 65 echo 66 usage_vm_base 67 echo 68 usage_vm_image 69 exit 1 70} 71 72panic() { 73 msg="${@}" 74 printf "${msg}\n" 75 if [ ! -z "${mddev}" ]; then 76 mdconfig -d -u ${mddev} 77 fi 78 case ${cmd} in 79 vm-base) 80 # If the vm-base target fails, the vm-image target 81 # cannot possibly succeed. Touch the .TARGET file 82 # so it is not attempted. 83 touch vm-image 84 ;; 85 *) 86 # FALLTHROUGH 87 ;; 88 esac 89 # Do not allow one failure case to chain through any remaining image 90 # builds. 91 return 1 92} 93 94vm_create_baseimage() { 95 # Creates the UFS root filesystem for the virtual machine disk, 96 # written to the formatted disk image with mkimg(1). 97 # 98 # Arguments: 99 # vm-base <base image> <source tree> <dest dir> <disk image size> 100 101 VMBASE="${1}" 102 WORLDDIR="${2}" 103 DESTDIR="${3}" 104 VMSIZE="${4}" 105 106 if [ -z "${VMBASE}" -o -z "${WORLDDIR}" -o -z "${DESTDIR}" \ 107 -o -z "${VMSIZE}" ]; then 108 usage 109 fi 110 111 i=0 112 mkdir -p ${DESTDIR} 113 truncate -s ${VMSIZE} ${VMBASE} 114 mddev=$(mdconfig -f ${VMBASE}) 115 newfs -j /dev/${mddev} 116 mount /dev/${mddev} ${DESTDIR} 117 cd ${WORLDDIR} && \ 118 make DESTDIR=${DESTDIR} \ 119 installworld installkernel distribution || \ 120 panic "\n\nCannot install the base system to ${DESTDIR}." 121 chroot ${DESTDIR} /usr/bin/newaliases 122 echo '# Custom /etc/fstab for FreeBSD VM images' \ 123 > ${DESTDIR}/etc/fstab 124 echo '/dev/gpt/rootfs / ufs rw 2 2' \ 125 >> ${DESTDIR}/etc/fstab 126 echo '/dev/gpt/swapfs none swap sw 0 0' \ 127 >> ${DESTDIR}/etc/fstab 128 sync 129 while ! umount ${DESTDIR}; do 130 i=$(( $i + 1 )) 131 if [ $i -ge 10 ]; then 132 # This should never happen. But, it has happened. 133 msg="Cannot umount(8) ${DESTDIR}\n" 134 msg="${msg}Something has gone horribly wrong." 135 panic "${msg}" 136 fi 137 sleep 1 138 done 139 140 return 0 141} 142 143vm_create_vmdisk() { 144 # Creates the virtual machine disk image from the raw disk image. 145 # 146 # Arguments: 147 # vm-image <base image> <image format> <output image>" 148 149 VMBASE="${1}" 150 FORMAT="${2}" 151 VMIMAGE="${3}" 152 153 if [ -z "${VMBASE}" -o -z "${FORMAT}" -o -z "${VMIMAGE}" ]; then 154 usage 155 fi 156 157 mkimg_version=$(mkimg --version 2>/dev/null | awk '{print $2}') 158 159 # We need mkimg(1) '--version' output, at minimum, to be able to 160 # tell what virtual machine disk image formats are available. 161 # Bail if mkimg(1) reports an empty '--version' value. 162 if [ -z "${mkimg_version}" ]; then 163 msg="Cannot determine mkimg(1) version.\n" 164 msg="${msg}Cannot continue without a known mkimg(1) version." 165 panic "${msg}" 166 fi 167 168 if ! mkimg --formats 2>/dev/null | grep -q ${FORMAT}; then 169 panic "'${FORMAT}' is not supported by this mkimg(1).\n" 170 fi 171 172 case ${FORMAT} in 173 vhd) 174 mkimg_format=vhdf 175 ;; 176 *) 177 mkimg_format=${FORMAT} 178 ;; 179 esac 180 181 mkimg -f ${mkimg_format} -s gpt \ 182 -b /boot/pmbr -p freebsd-boot/bootfs:=/boot/gptboot \ 183 -p freebsd-swap/swapfs::1G \ 184 -p freebsd-ufs/rootfs:=${VMBASE} \ 185 -o ${VMIMAGE} 186 187 return 0 188} 189 190main() { 191 vm_config= 192 while getopts "c:" arg; do 193 case ${arg} in 194 c) 195 vm_config="${OPTARG}" 196 ;; 197 *) 198 ;; 199 esac 200 done 201 shift $(( ${OPTIND} - 1 )) 202 203 cmd="${1}" 204 shift 1 205 206 if [ ! -z "${vm_config}" ]; then 207 if [ ! -e "${vm_config}" ]; then 208 panic "Configuration file ${vm_config} not found." 209 fi 210 . ${vm_config} 211 fi 212 213 case ${cmd} in 214 vm-base) 215 eval vm_create_baseimage "$@" || return 0 216 ;; 217 vm-image) 218 eval vm_create_vmdisk "$@" || return 0 219 ;; 220 *|\?) 221 usage 222 ;; 223 esac 224 225 return 0 226} 227 228main "$@" 229