]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - share/examples/bhyve/vmrun.sh
MFC: r314694
[FreeBSD/stable/10.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 "       -u: RTC keeps UTC time"
69         echo "       -w: ignore unimplemented MSRs"
70         echo ""
71         [ -n "$msg" ] && errmsg "$msg"
72         exit 1
73 }
74
75 if [ `id -u` -ne 0 ]; then
76         errmsg "This script must be executed with superuser privileges"
77         exit 1
78 fi
79
80 kldstat -n vmm > /dev/null 2>&1 
81 if [ $? -ne 0 ]; then
82         errmsg "vmm.ko is not loaded"
83         exit 1
84 fi
85
86 force_install=0
87 isofile=${DEFAULT_ISOFILE}
88 memsize=${DEFAULT_MEMSIZE}
89 console=${DEFAULT_CONSOLE}
90 cpus=${DEFAULT_CPUS}
91 tap_total=0
92 disk_total=0
93 gdbport=0
94 loader_opt=""
95 bhyverun_opt="-H -A -P"
96 pass_total=0
97
98 while getopts ac:C:d:e:g:hH:iI:l:m:p:t:uw c ; do
99         case $c in
100         a)
101                 bhyverun_opt="${bhyverun_opt} -a"
102                 ;;
103         c)
104                 cpus=${OPTARG}
105                 ;;
106         C)
107                 console=${OPTARG}
108                 ;;
109         d)
110                 disk_dev=${OPTARG%%,*}
111                 disk_opts=${OPTARG#${disk_dev}}
112                 eval "disk_dev${disk_total}=\"${disk_dev}\""
113                 eval "disk_opts${disk_total}=\"${disk_opts}\""
114                 disk_total=$(($disk_total + 1))
115                 ;;
116         e)
117                 loader_opt="${loader_opt} -e ${OPTARG}"
118                 ;;
119         g)      
120                 gdbport=${OPTARG}
121                 ;;
122         H)
123                 host_base=`realpath ${OPTARG}`
124                 ;;
125         i)
126                 force_install=1
127                 ;;
128         I)
129                 isofile=${OPTARG}
130                 ;;
131         l)
132                 loader_opt="${loader_opt} -l ${OPTARG}"
133                 ;;
134         m)
135                 memsize=${OPTARG}
136                 ;;
137         p)
138                 eval "pass_dev${pass_total}=\"${OPTARG}\""
139                 pass_total=$(($pass_total + 1))
140                 ;;
141         t)
142                 eval "tap_dev${tap_total}=\"${OPTARG}\""
143                 tap_total=$(($tap_total + 1))
144                 ;;
145         u)      
146                 bhyverun_opt="${bhyverun_opt} -u"
147                 ;;
148         w)
149                 bhyverun_opt="${bhyverun_opt} -w"
150                 ;;
151         *)
152                 usage
153                 ;;
154         esac
155 done
156
157 if [ $tap_total -eq 0 ] ; then
158     tap_total=1
159     tap_dev0="${DEFAULT_TAPDEV}"
160 fi
161 if [ $disk_total -eq 0 ] ; then
162     disk_total=1
163     disk_dev0="${DEFAULT_VIRTIO_DISK}"
164
165 fi
166
167 shift $((${OPTIND} - 1))
168
169 if [ $# -ne 1 ]; then
170         usage "virtual machine name not specified"
171 fi
172
173 vmname="$1"
174 if [ -n "${host_base}" ]; then
175         loader_opt="${loader_opt} -h ${host_base}"
176 fi
177
178 # If PCI passthru devices are configured then guest memory must be wired
179 if [ ${pass_total} -gt 0 ]; then
180         loader_opt="${loader_opt} -S"
181         bhyverun_opt="${bhyverun_opt} -S"
182 fi
183
184 make_and_check_diskdev()
185 {
186     local virtio_diskdev="$1"
187     # Create the virtio diskdev file if needed
188     if [ ! -e ${virtio_diskdev} ]; then
189             echo "virtio disk device file \"${virtio_diskdev}\" does not exist."
190             echo "Creating it ..."
191             truncate -s 8G ${virtio_diskdev} > /dev/null
192     fi
193
194     if [ ! -r ${virtio_diskdev} ]; then
195             echo "virtio disk device file \"${virtio_diskdev}\" is not readable"
196             exit 1
197     fi
198
199     if [ ! -w ${virtio_diskdev} ]; then
200             echo "virtio disk device file \"${virtio_diskdev}\" is not writable"
201             exit 1
202     fi
203 }
204
205 echo "Launching virtual machine \"$vmname\" ..."
206
207 first_diskdev="$disk_dev0"
208
209 ${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1
210
211 while [ 1 ]; do
212
213         file -s ${first_diskdev} | grep "boot sector" > /dev/null
214         rc=$?
215         if [ $rc -ne 0 ]; then
216                 file -s ${first_diskdev} | grep ": Unix Fast File sys" > /dev/null
217                 rc=$?
218         fi
219         if [ $rc -ne 0 ]; then
220                 need_install=1
221         else
222                 need_install=0
223         fi
224
225         if [ $force_install -eq 1 -o $need_install -eq 1 ]; then
226                 if [ ! -r ${isofile} ]; then
227                         echo -n "Installation CDROM image \"${isofile}\" "
228                         echo    "is not readable"
229                         exit 1
230                 fi
231                 BOOTDISKS="-d ${isofile}"
232                 installer_opt="-s 31:0,ahci-cd,${isofile}"
233         else
234                 BOOTDISKS=""
235                 i=0
236                 while [ $i -lt $disk_total ] ; do
237                         eval "disk=\$disk_dev${i}"
238                         if [ -r ${disk} ] ; then
239                                 BOOTDISKS="$BOOTDISKS -d ${disk} "
240                         fi
241                         i=$(($i + 1))
242                 done
243                 installer_opt=""
244         fi
245
246         ${LOADER} -c ${console} -m ${memsize} ${BOOTDISKS} ${loader_opt} \
247                 ${vmname}
248         bhyve_exit=$?
249         if [ $bhyve_exit -ne 0 ]; then
250                 break
251         fi
252
253         #
254         # Build up args for additional tap and disk devices now.
255         #
256         nextslot=2  # slot 0 is hostbridge, slot 1 is lpc
257         devargs=""  # accumulate disk/tap args here
258         i=0
259         while [ $i -lt $tap_total ] ; do
260             eval "tapname=\$tap_dev${i}"
261             devargs="$devargs -s $nextslot:0,virtio-net,${tapname} "
262             nextslot=$(($nextslot + 1))
263             i=$(($i + 1))
264         done
265
266         i=0
267         while [ $i -lt $disk_total ] ; do
268             eval "disk=\$disk_dev${i}"
269             eval "opts=\$disk_opts${i}"
270             make_and_check_diskdev "${disk}"
271             devargs="$devargs -s $nextslot:0,virtio-blk,${disk}${opts} "
272             nextslot=$(($nextslot + 1))
273             i=$(($i + 1))
274         done
275
276         i=0
277         while [ $i -lt $pass_total ] ; do
278             eval "pass=\$pass_dev${i}"
279             devargs="$devargs -s $nextslot:0,passthru,${pass} "
280             nextslot=$(($nextslot + 1))
281             i=$(($i + 1))
282         done
283
284         ${FBSDRUN} -c ${cpus} -m ${memsize} ${bhyverun_opt}             \
285                 -g ${gdbport}                                           \
286                 -s 0:0,hostbridge                                       \
287                 -s 1:0,lpc                                              \
288                 ${devargs}                                              \
289                 -l com1,${console}                                      \
290                 ${installer_opt}                                        \
291                 ${vmname}
292
293         bhyve_exit=$?
294         # bhyve returns the following status codes:
295         #  0 - VM has been reset
296         #  1 - VM has been powered off
297         #  2 - VM has been halted
298         #  3 - VM generated a triple fault
299         #  all other non-zero status codes are errors
300         #
301         if [ $bhyve_exit -ne 0 ]; then
302                 break
303         fi
304 done
305
306
307 case $bhyve_exit in
308         0|1|2)
309                 # Cleanup /dev/vmm entry when bhyve did not exit
310                 # due to an error.
311                 ${BHYVECTL} --vm=${vmname} --destroy > /dev/null 2>&1
312                 ;;
313 esac
314
315 exit $bhyve_exit