xref: /spdk/scripts/vagrant/create_vbox.sh (revision 02e00efc878bf58046830c28dfe3b417597ef68c)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2018 Intel Corporation
4#  All rights reserved.
5#
6# create_vbox.sh
7#
8# Creates a virtual box with vagrant in the $PWD.
9#
10# This script creates a subdirectory called $PWD/<distro> and copies the Vagrantfile
11# into that directory before running 'vagrant up'
12
13set -e
14
15VAGRANT_TARGET="$PWD"
16
17DIR="$(cd "$(dirname $0)" && pwd)"
18SPDK_DIR="$(cd "${DIR}/../../" && pwd)"
19
20# The command line help
21display_help() {
22	echo
23	echo " Usage: ${0##*/} [-b nvme-backing-file] [-n <num-cpus>] [-s <ram-size>] [-x <http-proxy>] [-hvrldcufaoH] <distro>"
24	echo
25	echo "  distro = <centos7 | ubuntu2004 | ubuntu2204 | fedora37 | fedora38 | freebsd12 | freebsd13 | arch | clearlinux | rocky8 | rocky9>"
26	echo
27	echo "  -s <ram-size> in MB             Default: ${SPDK_VAGRANT_VMRAM}"
28	echo "  -n <num-cpus> 1 to 4            Default: ${SPDK_VAGRANT_VMCPU}"
29	echo "  -x <http-proxy>                 Default: \"${SPDK_VAGRANT_HTTP_PROXY}\""
30	echo "  -p <provider>                   \"libvirt\" or \"virtualbox\". Default: ${SPDK_VAGRANT_PROVIDER}"
31	echo "  -b <nvme-backing-file>          Emulated NVMe options."
32	echo "                                  If no -b option is specified then this option defaults to emulating single"
33	echo "                                  NVMe with 1 namespace and assumes path: /var/lib/libvirt/images/nvme_disk.img"
34	echo "                                  -b option can be used multiple times for attaching multiple files to the VM"
35	echo "                                  Parameters for -b option: <path>,<type>,<ns_path1[:ns_path1:...]>,<cmb>,<pmr_file[:pmr_size]>,<zns>,<ms>,<fdp>"
36	echo "                                  Available types: nvme"
37	echo "                                  Default pmr size: 16M"
38	echo "                                  Default cmb: false"
39	echo "                                  Default zns: false"
40	echo "                                  Default ms: none (set to 'true' to enable 64M)"
41	echo "                                  Default fdp: 96M:2:8[:1;2;3:1...] (fdp.runs:fdp.nrg:fdp.nruh:fdp.ruhs)"
42	echo "                                  type, ns_path, cmb, pmr, zns, ms  and fdp can be empty"
43	echo "                                  fdp.ruhs defines fdp.ruhs per ns, e.g.: 4;5;6:1 would set 4;5;6 for ns=1,"
44	echo "                                  and 1 for ns=2."
45	echo "  -c                              Create all above disk, default 0"
46	echo "  -H                              Use hugepages for allocating VM memory. Only for libvirt provider. Default: false."
47	echo "  -u                              Use password authentication to the VM instead of SSH keys."
48	echo "  -l                              Use a local copy of spdk, don't try to rsync from the host."
49	echo "  -a                              Copy spdk/autorun.sh artifacts from VM to host system."
50	echo "  -d                              Deploy a test vm by provisioning all prerequisites for spdk autotest"
51	echo "  -o                              Add network interface for openstack tests"
52	echo "  -N                              Use NFSv4 backend"
53	echo "  --qemu-emulator=<path>          Path to custom QEMU binary. Only works with libvirt provider"
54	echo "  --vagrantfiles-dir=<path>       Destination directory to put Vagrantfile into."
55	echo "  --package-box                   Install all dependencies for SPDK and create a local vagrant box version."
56	echo "  --vagrantfile=<path>            Path to a custom Vagrantfile"
57	echo "  --extra-vagrantfiles=<path>     Comma separated list of files to load from within main Vagrantfile"
58	echo "  -r dry-run"
59	echo "  -h help"
60	echo "  -v verbose"
61	echo "  -f                              Force use of given distro, regardless if it's supported by the script or not."
62	echo "  --box-version                   Version of the vagrant box to select for given distro."
63	echo "  --nic-model                     NIC model supported by QEMU. 'virtio' is the default."
64	echo
65	echo " Examples:"
66	echo
67	echo "  $0 -x http://user:password@host:port fedora37"
68	echo "  $0 -s 2048 -n 2 ubuntu2204"
69	echo "  $0 -rv freebsd"
70	echo "  $0 fedora37"
71	echo "  $0 -b /var/lib/libvirt/images/nvme1.img,nvme,/var/lib/libvirt/images/nvme1n1.img fedora37"
72	echo "  $0 -b none fedora37"
73	echo
74}
75
76is_valid_nic_model() {
77	local models model
78
79	[[ $SPDK_VAGRANT_PROVIDER == libvirt ]] || return 0
80
81	mapfile -t models < <(
82		"${SPDK_QEMU_EMULATOR:-qemu-system-x86_64}" -nic model=? | grep -v "NIC models:"
83	)
84	models+=("virtio")
85
86	for model in "${models[@]}"; do
87		[[ $model == "$NIC_MODEL" ]] && return 0
88	done
89
90	echo "NIC model '$NIC_MODEL' is invalid. List of supported models:" >&2
91	printf '  %s\n' "${models[@]}" >&2
92	return 1
93}
94
95# Set up vagrant proxy. Assumes git-bash on Windows
96# https://stackoverflow.com/questions/19872591/how-to-use-vagrant-in-a-proxy-environment
97SPDK_VAGRANT_HTTP_PROXY=""
98
99VERBOSE=0
100HELP=0
101COPY_SPDK_DIR=1
102COPY_SPDK_ARTIFACTS=0
103DRY_RUN=0
104DEPLOY_TEST_VM=0
105SPDK_VAGRANT_DISTRO="distro"
106SPDK_VAGRANT_VMCPU=4
107SPDK_VAGRANT_VMRAM=4096
108SPDK_VAGRANT_PROVIDER="virtualbox"
109SPDK_QEMU_EMULATOR=""
110SPDK_OPENSTACK_NETWORK=0
111OPTIND=1
112NVME_DISKS_TYPE=""
113NVME_DISKS_NAMESPACES=""
114NVME_FILE=""
115NVME_AUTO_CREATE=0
116VAGRANTFILE_DIR=""
117VAGRANT_PASSWORD_AUTH=0
118VAGRANT_PACKAGE_BOX=0
119VAGRANT_HUGE_MEM=0
120VAGRANTFILE=$DIR/Vagrantfile
121FORCE_DISTRO=false
122NFS4_BACKEND=0
123VAGRANT_BOX_VERSION=""
124EXTRA_VAGRANTFILES=""
125NIC_MODEL=virtio
126
127while getopts ":b:n:s:x:p:uvcraldoHNhf-:" opt; do
128	case "${opt}" in
129		-)
130			case "${OPTARG}" in
131				package-box) VAGRANT_PACKAGE_BOX=1 ;;
132				qemu-emulator=*) SPDK_QEMU_EMULATOR="${OPTARG#*=}" ;;
133				vagrantfiles-dir=*) VAGRANTFILE_DIR="${OPTARG#*=}" ;;
134				vagrantfile=*) [[ -n ${OPTARG#*=} ]] && VAGRANTFILE="${OPTARG#*=}" ;;
135				box-version=*) [[ -n ${OPTARG#*=} ]] && VAGRANT_BOX_VERSION="${OPTARG#*=}" ;;
136				extra-vagrantfiles=*) [[ -n ${OPTARG#*=} ]] && EXTRA_VAGRANTFILES="${OPTARG#*=}" ;;
137				nic-model=*) [[ -n ${OPTARG#*=} ]] && NIC_MODEL="${OPTARG#*=}" ;;
138				*) echo "Invalid argument '$OPTARG'" ;;
139			esac
140			;;
141		x)
142			http_proxy=$OPTARG
143			https_proxy=$http_proxy
144			SPDK_VAGRANT_HTTP_PROXY="${http_proxy}"
145			;;
146		n)
147			SPDK_VAGRANT_VMCPU=$OPTARG
148			;;
149		s)
150			SPDK_VAGRANT_VMRAM=$OPTARG
151			;;
152		p)
153			SPDK_VAGRANT_PROVIDER=$OPTARG
154			;;
155		v)
156			VERBOSE=1
157			;;
158		c)
159			NVME_AUTO_CREATE=1
160			;;
161		r)
162			DRY_RUN=1
163			;;
164		h)
165			display_help >&2
166			exit 0
167			;;
168		a)
169			COPY_SPDK_ARTIFACTS=1
170			;;
171		l)
172			COPY_SPDK_DIR=0
173			;;
174		d)
175			DEPLOY_TEST_VM=1
176			;;
177		o)
178			SPDK_OPENSTACK_NETWORK=1
179			;;
180		b)
181			NVME_FILE+="${OPTARG#*=} "
182			;;
183		u)
184			VAGRANT_PASSWORD_AUTH=1
185			;;
186		H)
187			VAGRANT_HUGE_MEM=1
188			;;
189		f)
190			FORCE_DISTRO=true
191			;;
192		N)
193			NFS4_BACKEND=1
194			;;
195		*)
196			echo "  Invalid argument: -$OPTARG" >&2
197			echo "  Try: \"$0 -h\"" >&2
198			exit 1
199			;;
200	esac
201done
202
203is_valid_nic_model
204
205shift "$((OPTIND - 1))" # Discard the options and sentinel --
206
207SPDK_VAGRANT_DISTRO="$*"
208
209case "${SPDK_VAGRANT_DISTRO}" in
210	centos7) ;&
211	ubuntu2[02]04) ;&
212	fedora3[7-8]) ;&
213	freebsd1[2-3]) ;&
214	rocky[89]) ;&
215	arch | clearlinux) ;;
216	*)
217		if [[ $FORCE_DISTRO == false ]]; then
218			echo "  Invalid argument \"${SPDK_VAGRANT_DISTRO}\"" >&2
219			echo "  Try: \"$0 -h\"" >&2
220			exit 1
221		fi
222		;;
223esac
224export SPDK_VAGRANT_DISTRO
225
226if [ -z "$NVME_FILE" ]; then
227	TMP="/var/lib/libvirt/images/nvme_disk.img"
228	NVME_DISKS_TYPE="nvme"
229else
230	TMP=""
231	for args in $NVME_FILE; do
232		while IFS=, read -r path type namespace cmb pmr zns ms fdp; do
233			TMP+="$path,"
234			if [ -z "$type" ]; then
235				type="nvme"
236			fi
237			NVME_CMB+="$cmb,"
238			NVME_PMR+="$pmr,"
239			NVME_ZNS+="$zns,"
240			NVME_DISKS_TYPE+="$type,"
241			NVME_DISKS_NAMESPACES+="$namespace,"
242			NVME_MS+="$ms,"
243			NVME_FDP+="$fdp,"
244			if [ ${NVME_AUTO_CREATE} = 1 ]; then
245				$SPDK_DIR/scripts/vagrant/create_nvme_img.sh -n $path
246			fi
247		done <<< $args
248	done
249fi
250NVME_FILE=$TMP
251
252if [ ${VERBOSE} = 1 ]; then
253	echo
254	echo DIR=${DIR}
255	echo SPDK_DIR=${SPDK_DIR}
256	echo VAGRANT_TARGET=${VAGRANT_TARGET}
257	echo HELP=$HELP
258	echo DRY_RUN=$DRY_RUN
259	echo NVME_FILE=$NVME_FILE
260	echo NVME_DISKS_TYPE=$NVME_DISKS_TYPE
261	echo NVME_AUTO_CREATE=$NVME_AUTO_CREATE
262	echo NVME_DISKS_NAMESPACES=$NVME_DISKS_NAMESPACES
263	echo NVME_CMB=$NVME_CMB
264	echo NVME_PMR=$NVME_PMR
265	echo NVME_ZNS=$NVME_ZNS
266	echo NVME_MS=$NVME_MS
267	echo NVME_FDP=$NVME_FDP
268	echo SPDK_VAGRANT_DISTRO=$SPDK_VAGRANT_DISTRO
269	echo SPDK_VAGRANT_VMCPU=$SPDK_VAGRANT_VMCPU
270	echo SPDK_VAGRANT_VMRAM=$SPDK_VAGRANT_VMRAM
271	echo SPDK_VAGRANT_PROVIDER=$SPDK_VAGRANT_PROVIDER
272	echo SPDK_VAGRANT_HTTP_PROXY=$SPDK_VAGRANT_HTTP_PROXY
273	echo SPDK_QEMU_EMULATOR=$SPDK_QEMU_EMULATOR
274	echo SPDK_OPENSTACK_NETWORK=$SPDK_OPENSTACK_NETWORK
275	echo VAGRANT_PACKAGE_BOX=$VAGRANT_PACKAGE_BOX
276	echo VAGRANTFILE=$VAGRANTFILE
277	echo FORCE_DISTRO=$FORCE_DISTRO
278	echo VAGRANT_BOX_VERSION=$VAGRANT_BOX_VERSION
279	echo EXTRA_VAGRANTFILES=$EXTRA_VAGRANTFILES
280	echo NIC_MODEL=$NIC_MODEL
281	echo
282fi
283
284export SPDK_VAGRANT_HTTP_PROXY
285export SPDK_VAGRANT_VMCPU
286export SPDK_VAGRANT_VMRAM
287export SPDK_DIR
288export SPDK_OPENSTACK_NETWORK
289export COPY_SPDK_DIR
290export COPY_SPDK_ARTIFACTS
291export DEPLOY_TEST_VM
292export NVME_CMB
293export NVME_PMR
294export NVME_ZNS
295export NVME_MS
296export NVME_FDP
297export NVME_DISKS_TYPE
298export NVME_DISKS_NAMESPACES
299export NVME_FILE
300export VAGRANT_PASSWORD_AUTH
301export VAGRANT_HUGE_MEM
302export FORCE_DISTRO
303export VAGRANT_BOX_VERSION
304export EXTRA_VAGRANTFILES
305export NIC_MODEL
306
307if [ -n "$SPDK_VAGRANT_PROVIDER" ]; then
308	provider="--provider=${SPDK_VAGRANT_PROVIDER}"
309fi
310
311if [ -n "$SPDK_VAGRANT_PROVIDER" ]; then
312	export SPDK_VAGRANT_PROVIDER
313fi
314
315if [ -n "$SPDK_QEMU_EMULATOR" ] && [ "$SPDK_VAGRANT_PROVIDER" == "libvirt" ]; then
316	export SPDK_QEMU_EMULATOR
317fi
318
319if [ ${DRY_RUN} = 1 ]; then
320	echo "Environment Variables"
321	printenv SPDK_VAGRANT_DISTRO
322	printenv SPDK_VAGRANT_VMRAM
323	printenv SPDK_VAGRANT_VMCPU
324	printenv SPDK_VAGRANT_PROVIDER
325	printenv SPDK_VAGRANT_HTTP_PROXY
326	printenv SPDK_QEMU_EMULATOR
327	printenv NVME_DISKS_TYPE
328	printenv NVME_AUTO_CREATE
329	printenv NVME_DISKS_NAMESPACES
330	printenv NVME_FILE
331	printenv SPDK_DIR
332	printenv VAGRANT_HUGE_MEM
333	printenv VAGRANTFILE
334	printenv FORCE_DISTRO
335	printenv VAGRANT_BOX_VERSION
336	printenv EXTRA_VAGRANTFILES
337	printenv NIC_MODEL
338fi
339if [ -z "$VAGRANTFILE_DIR" ]; then
340	VAGRANTFILE_DIR="${VAGRANT_TARGET}/${SPDK_VAGRANT_DISTRO}-${SPDK_VAGRANT_PROVIDER}"
341	export VAGRANTFILE_DIR
342fi
343
344if [ -d "${VAGRANTFILE_DIR}" ]; then
345	echo "Error: ${VAGRANTFILE_DIR} already exists!"
346	exit 1
347fi
348
349if [[ ! -f $VAGRANTFILE ]]; then
350	echo "$VAGRANTFILE is not a regular file!"
351	exit 1
352fi
353
354if [ ${DRY_RUN} != 1 ]; then
355	mkdir -vp "${VAGRANTFILE_DIR}"
356	ln -s "$VAGRANTFILE" "${VAGRANTFILE_DIR}/Vagrantfile"
357	pushd "${VAGRANTFILE_DIR}"
358	if [ -n "${http_proxy}" ]; then
359		export http_proxy
360		export https_proxy
361		if echo "$SPDK_VAGRANT_DISTRO" | grep -q freebsd; then
362			cat > ~/vagrant_pkg.conf << EOF
363pkg_env: {
364http_proxy: ${http_proxy}
365}
366EOF
367		fi
368	fi
369	mkdir -p "${VAGRANTFILE_DIR}/output"
370	vagrant up $provider
371	if [ ${VAGRANT_PACKAGE_BOX} == 1 ]; then
372		vagrant ssh -c 'sudo spdk_repo/spdk/scripts/vagrant/update.sh'
373		vagrant halt
374		vagrant package --output spdk_${SPDK_VAGRANT_DISTRO}.box
375		vagrant box add spdk/${SPDK_VAGRANT_DISTRO} spdk_${SPDK_VAGRANT_DISTRO}.box \
376			&& rm spdk_${SPDK_VAGRANT_DISTRO}.box
377		vagrant destroy
378	fi
379	echo ""
380	echo "  SUCCESS!"
381	echo ""
382	echo "  cd to ${VAGRANTFILE_DIR} and type \"vagrant ssh\" to use."
383	echo "  Use vagrant \"suspend\" and vagrant \"resume\" to stop and start."
384	echo "  Use vagrant \"destroy\" followed by \"rm -rf ${VAGRANTFILE_DIR}\" to destroy all trace of vm."
385	echo ""
386fi
387