]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - share/examples/bhyve/vmrun.sh
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / share / examples / bhyve / vmrun.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2013 NetApp, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 #    notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 #    notice, this list of conditions and the following disclaimer in the
13 #    documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 # SUCH DAMAGE.
26 #
27 # $FreeBSD$
28 #
29
30 LOADER=/usr/sbin/bhyveload
31 BHYVECTL=/usr/sbin/bhyvectl
32 FBSDRUN=/usr/sbin/bhyve
33
34 DEFAULT_MEMSIZE=512M
35 DEFAULT_CPUS=2
36 DEFAULT_TAPDEV=tap0
37 DEFAULT_CONSOLE=stdio
38
39 DEFAULT_VIRTIO_DISK="./diskdev"
40 DEFAULT_ISOFILE="./release.iso"
41
42 errmsg() {
43         echo "*** $1"
44 }
45
46 usage() {
47         local msg=$1
48
49         echo "Usage: vmrun.sh [-ahi] [-c <CPUs>] [-C <console>] [-d <disk file>]"
50         echo "                [-e <name=value>] [-g <gdbport> ] [-H <directory>]"
51         echo "                [-I <location of installation iso>] [-l <loader>]"
52         echo "                [-m <memsize>] [-t <tapdev>] <vmname>"
53         echo ""
54         echo "       -h: display this help message"
55         echo "       -a: force memory mapped local APIC access"
56         echo "       -c: number of virtual cpus (default is ${DEFAULT_CPUS})"
57         echo "       -C: console device (default is ${DEFAULT_CONSOLE})"
58         echo "       -d: virtio diskdev file (default is ${DEFAULT_VIRTIO_DISK})"
59         echo "       -e: set FreeBSD loader environment variable"
60         echo "       -g: listen for connection from kgdb at <gdbport>"
61         echo "       -H: host filesystem to export to the loader"
62         echo "       -i: force boot of the Installation CDROM image"
63         echo "       -I: Installation CDROM image location (default is ${DEFAULT_ISOFILE})"
64         echo "       -l: the OS loader to use (default is /boot/userboot.so)"
65         echo "       -m: memory size (default is ${DEFAULT_MEMSIZE})"
66         echo "       -p: pass-through a host PCI device at bus/slot/func (e.g. 10/0/0)"
67         echo "       -t: tap device for virtio-net (default is $DEFAULT_TAPDEV)"
68         echo ""
69         [ -n "$msg" ] && errmsg "$msg"
70         exit 1
71 }
72
73 if [ `id -u` -ne 0 ]; then
74         errmsg "This script must be executed with superuser privileges"
75         exit 1
76 fi
77
78 kldstat -n vmm > /dev/null 2>&1 
79 if [ $? -ne 0 ]; then
80         errmsg "vmm.ko is not loaded"
81         exit 1
82 fi
83
84 force_install=0
85 isofile=${DEFAULT_ISOFILE}
86 memsize=${DEFAULT_MEMSIZE}
87 console=${DEFAULT_CONSOLE}
88 cpus=${DEFAULT_CPUS}
89 tap_total=0
90 disk_total=0
91 gdbport=0
92 loader_opt=""
93 bhyverun_opt="-H -A -P"
94 pass_total=0
95
96 while getopts ac:C:d:e:g:hH:iI:l:m:p:t: c ; do
97         case $c in
98         a)
99                 bhyverun_opt="${bhyverun_opt} -a"
100                 ;;
101         c)
102                 cpus=${OPTARG}
103                 ;;
104         C)
105                 console=${OPTARG}
106                 ;;
107         d)
108                 disk_dev=${OPTARG%%,*}
109                 disk_opts=${OPTARG#${disk_dev}}
110                 eval "disk_dev${disk_total}=\"${disk_dev}\""
111                 eval "disk_opts${disk_total}=\"${disk_opts}\""
112                 disk_total=$(($disk_total + 1))
113                 ;;
114         e)
115                 loader_opt="${loader_opt} -e ${OPTARG}"
116                 ;;
117         g)      
118                 gdbport=${OPTARG}
119                 ;;
120         H)
121                 host_base=`realpath ${OPTARG}`
122                 ;;
123         i)
124                 force_install=1
125                 ;;
126         I)
127                 isofile=${OPTARG}
128                 ;;
129         l)
130                 loader_opt="${loader_opt} -l ${OPTARG}"
131                 ;;
132         m)
133                 memsize=${OPTARG}
134                 ;;
135         p)
136                 eval "pass_dev${pass_total}=\"${OPTARG}\""
137                 pass_total=$(($pass_total + 1))
138                 ;;
139         t)
140                 eval "tap_dev${tap_total}=\"${OPTARG}\""
141                 tap_total=$(($tap_total + 1))
142                 ;;
143         *)
144                 usage
145                 ;;
146         esac
147 done
148
149 if [ $tap_total -eq 0 ] ; then
150     tap_total=1
151     tap_dev0="${DEFAULT_TAPDEV}"
152 fi
153 if [ $disk_total -eq 0 ] ; then
154     disk_total=1
155     disk_dev0="${DEFAULT_VIRTIO_DISK}"
156
157 fi
158
159 shift $((${OPTIND} - 1))
160
161 if [ $# -ne 1 ]; then
162         usage "virtual machine name not specified"
163 fi
164
165 vmname="$1"
166 if [ -n "${host_base}" ]; then
167         loader_opt="${loader_opt} -h ${host_base}"
168 fi
169
170 # If PCI passthru devices are configured then guest memory must be wired
171 if [ ${pass_total} -gt 0 ]; then
172         loader_opt="${loader_opt} -S"
173         bhyverun_opt="${bhyverun_opt} -S"
174 fi
175
176 make_and_check_diskdev()
177 {
178     local virtio_diskdev="$1"
179     # Create the virtio diskdev file if needed
180     if [ ! -f ${virtio_diskdev} ]; then
181             echo "virtio disk device file \"${virtio_diskdev}\" does not exist."
182             echo "Creating it ..."
183             truncate -s 8G ${virtio_diskdev} > /dev/null
184     fi
185
186     if [ ! -r ${virtio_diskdev} ]; then
187             echo "virtio disk device file \"${virtio_diskdev}\" is not readable"
188             exit 1
189     fi
190
191     if [ ! -w ${virtio_diskdev} ]; then
192             echo "virtio disk device file \"${virtio_diskdev}\" is not writable"
193             exit 1
194     fi
195 }
196
197 echo "Launching virtual machine \"$vmname\" ..."
198
199 first_diskdev="$disk_dev0"
200
201 ${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1
202
203 while [ 1 ]; do
204
205         file -s ${first_diskdev} | grep "boot sector" > /dev/null
206         rc=$?
207         if [ $rc -ne 0 ]; then
208                 file -s ${first_diskdev} | grep ": Unix Fast File sys" > /dev/null
209                 rc=$?
210         fi
211         if [ $rc -ne 0 ]; then
212                 need_install=1
213         else
214                 need_install=0
215         fi
216
217         if [ $force_install -eq 1 -o $need_install -eq 1 ]; then
218                 if [ ! -r ${isofile} ]; then
219                         echo -n "Installation CDROM image \"${isofile}\" "
220                         echo    "is not readable"
221                         exit 1
222                 fi
223                 BOOTDISKS="-d ${isofile}"
224                 installer_opt="-s 31:0,ahci-cd,${isofile}"
225         else
226                 BOOTDISKS=""
227                 i=0
228                 while [ $i -lt $disk_total ] ; do
229                         eval "disk=\$disk_dev${i}"
230                         if [ -r ${disk} ] ; then
231                                 BOOTDISKS="$BOOTDISKS -d ${disk} "
232                         fi
233                         i=$(($i + 1))
234                 done
235                 installer_opt=""
236         fi
237
238         ${LOADER} -c ${console} -m ${memsize} ${BOOTDISKS} ${loader_opt} \
239                 ${vmname}
240         bhyve_exit=$?
241         if [ $bhyve_exit -ne 0 ]; then
242                 break
243         fi
244
245         #
246         # Build up args for additional tap and disk devices now.
247         #
248         nextslot=2  # slot 0 is hostbridge, slot 1 is lpc
249         devargs=""  # accumulate disk/tap args here
250         i=0
251         while [ $i -lt $tap_total ] ; do
252             eval "tapname=\$tap_dev${i}"
253             devargs="$devargs -s $nextslot:0,virtio-net,${tapname} "
254             nextslot=$(($nextslot + 1))
255             i=$(($i + 1))
256         done
257
258         i=0
259         while [ $i -lt $disk_total ] ; do
260             eval "disk=\$disk_dev${i}"
261             eval "opts=\$disk_opts${i}"
262             make_and_check_diskdev "${disk}"
263             devargs="$devargs -s $nextslot:0,virtio-blk,${disk}${opts} "
264             nextslot=$(($nextslot + 1))
265             i=$(($i + 1))
266         done
267
268         i=0
269         while [ $i -lt $pass_total ] ; do
270             eval "pass=\$pass_dev${i}"
271             devargs="$devargs -s $nextslot:0,passthru,${pass} "
272             nextslot=$(($nextslot + 1))
273             i=$(($i + 1))
274         done
275
276         ${FBSDRUN} -c ${cpus} -m ${memsize} ${bhyverun_opt}             \
277                 -g ${gdbport}                                           \
278                 -s 0:0,hostbridge                                       \
279                 -s 1:0,lpc                                              \
280                 ${devargs}                                              \
281                 -l com1,${console}                                      \
282                 ${installer_opt}                                        \
283                 ${vmname}
284
285         bhyve_exit=$?
286         # bhyve returns the following status codes:
287         #  0 - VM has been reset
288         #  1 - VM has been powered off
289         #  2 - VM has been halted
290         #  3 - VM generated a triple fault
291         #  all other non-zero status codes are errors
292         #
293         if [ $bhyve_exit -ne 0 ]; then
294                 break
295         fi
296 done
297
298
299 case $bhyve_exit in
300         0|1|2)
301                 # Cleanup /dev/vmm entry when bhyve did not exit
302                 # due to an error.
303                 ${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1
304                 ;;
305 esac
306
307 exit $bhyve_exit