mk-vmimage.sh revision 272795
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: projects/release-vmimage/release/amd64/mk-vmimage.sh 272795 2014-10-09 04:10:58Z gjb $ 33# 34 35PATH="/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin" 36export PATH 37 38vm_prebuild_setup() { 39 return 0 40} 41 42vm_setup() { 43 return 0 44} 45 46vm_postbuild_setup() { 47 return 0 48} 49 50usage_vm_base() { 51 echo -n "$(basename ${0}) vm-base <base image> <source tree>" 52 echo " <dest dir> <disk image size>" 53 return 0 54} 55 56usage_vm_image() { 57 echo -n "$(basename ${0}) vm-image <base image> <image format>" 58 echo " <output image>" 59 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 # Run anything that is needed before the virtual machine disk image 96 # is created. 97 vm_prebuild_setup 98 # Creates the UFS root filesystem for the virtual machine disk, 99 # written to the formatted disk image with mkimg(1). 100 # 101 # Arguments: 102 # vm-base <base image> <source tree> <dest dir> <disk image size> 103 104 VMBASE="${1}" 105 WORLDDIR="${2}" 106 DESTDIR="${3}" 107 VMSIZE="${4}" 108 109 if [ -z "${VMBASE}" -o -z "${WORLDDIR}" -o -z "${DESTDIR}" \ 110 -o -z "${VMSIZE}" ]; then 111 usage 112 fi 113 114 i=0 115 mkdir -p ${DESTDIR} 116 truncate -s ${VMSIZE} ${VMBASE} 117 mddev=$(mdconfig -f ${VMBASE}) 118 newfs -j /dev/${mddev} 119 mount /dev/${mddev} ${DESTDIR} 120 cd ${WORLDDIR} && \ 121 make DESTDIR=${DESTDIR} \ 122 installworld installkernel distribution || \ 123 panic "\n\nCannot install the base system to ${DESTDIR}." 124 chroot ${DESTDIR} /usr/bin/newaliases 125 echo '# Custom /etc/fstab for FreeBSD VM images' \ 126 > ${DESTDIR}/etc/fstab 127 echo '/dev/gpt/rootfs / ufs rw 2 2' \ 128 >> ${DESTDIR}/etc/fstab 129 echo '/dev/gpt/swapfs none swap sw 0 0' \ 130 >> ${DESTDIR}/etc/fstab 131 # Run anything that is needed while the virtual machine disk image 132 # userland filesystem is still mounted as a md(4) device. 133 vm_setup 134 sync 135 while ! umount ${DESTDIR}; do 136 i=$(( $i + 1 )) 137 if [ $i -ge 10 ]; then 138 # This should never happen. But, it has happened. 139 msg="Cannot umount(8) ${DESTDIR}\n" 140 msg="${msg}Something has gone horribly wrong." 141 panic "${msg}" 142 fi 143 sleep 1 144 done 145 146 return 0 147} 148 149vm_create_vmdisk() { 150 # Creates the virtual machine disk image from the raw disk image. 151 # 152 # Arguments: 153 # vm-image <base image> <image format> <output image>" 154 155 VMBASE="${1}" 156 FORMAT="${2}" 157 VMIMAGE="${3}" 158 159 if [ -z "${VMBASE}" -o -z "${FORMAT}" -o -z "${VMIMAGE}" ]; then 160 usage 161 fi 162 163 mkimg_version=$(mkimg --version 2>/dev/null | awk '{print $2}') 164 165 # We need mkimg(1) '--version' output, at minimum, to be able to 166 # tell what virtual machine disk image formats are available. 167 # Bail if mkimg(1) reports an empty '--version' value. 168 if [ -z "${mkimg_version}" ]; then 169 msg="Cannot determine mkimg(1) version.\n" 170 msg="${msg}Cannot continue without a known mkimg(1) version." 171 panic "${msg}" 172 fi 173 174 if ! mkimg --formats 2>/dev/null | grep -q ${FORMAT}; then 175 panic "'${FORMAT}' is not supported by this mkimg(1).\n" 176 fi 177 178 case ${FORMAT} in 179 vhd) 180 mkimg_format=vhdf 181 ;; 182 *) 183 mkimg_format=${FORMAT} 184 ;; 185 esac 186 187 mkimg -f ${mkimg_format} -s gpt \ 188 -b /boot/pmbr -p freebsd-boot/bootfs:=/boot/gptboot \ 189 -p freebsd-swap/swapfs::1G \ 190 -p freebsd-ufs/rootfs:=${VMBASE} \ 191 -o ${VMIMAGE} 192 193 # Run anything that is needed for the virtual machine disk image 194 # after it has been created. 195 vm_postbuild_setup 196 return 0 197} 198 199main() { 200 vm_config= 201 while getopts "c:" arg; do 202 case ${arg} in 203 c) 204 vm_config="${OPTARG}" 205 ;; 206 *) 207 ;; 208 esac 209 done 210 shift $(( ${OPTIND} - 1 )) 211 212 cmd="${1}" 213 shift 1 214 215 if [ ! -z "${vm_config}" ]; then 216 if [ ! -e "${vm_config}" ]; then 217 panic "Configuration file ${vm_config} not found." 218 fi 219 . ${vm_config} 220 fi 221 222 case ${cmd} in 223 vm-base) 224 eval vm_create_baseimage "$@" || return 0 225 ;; 226 vm-image) 227 eval vm_create_vmdisk "$@" || return 0 228 ;; 229 *|\?) 230 usage 231 ;; 232 esac 233 234 return 0 235} 236 237main "$@" 238