|
Packit |
bc9a3a |
#!/bin/bash
|
|
Packit |
bc9a3a |
# This file is part of cloud-init.
|
|
Packit |
bc9a3a |
# See LICENSE file for copyright and license info.
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
set -f
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
VERBOSITY=0
|
|
Packit |
bc9a3a |
KVM_PID=""
|
|
Packit |
bc9a3a |
DRY_RUN=false
|
|
Packit |
bc9a3a |
TEMP_D=""
|
|
Packit |
bc9a3a |
DEF_BRIDGE="virbr0"
|
|
Packit |
bc9a3a |
TAPDEVS=( )
|
|
Packit |
bc9a3a |
# OVS_CLEANUP gets populated with bridge:devname pairs used with ovs
|
|
Packit |
bc9a3a |
OVS_CLEANUP=( )
|
|
Packit |
bc9a3a |
MAC_PREFIX="52:54:00:12:34"
|
|
Packit |
bc9a3a |
# allow this to be set externally.
|
|
Packit |
bc9a3a |
_QEMU_SUPPORTS_FILE_LOCKING="${_QEMU_SUPPORTS_FILE_LOCKING}"
|
|
Packit |
bc9a3a |
KVM="kvm"
|
|
Packit |
bc9a3a |
declare -A KVM_DEVOPTS
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
error() { echo "$@" 1>&2; }
|
|
Packit |
bc9a3a |
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
|
|
Packit |
bc9a3a |
randmac() {
|
|
Packit |
bc9a3a |
# return random mac addr within final 3 tokens
|
|
Packit |
bc9a3a |
local random=""
|
|
Packit |
bc9a3a |
random=$(printf "%02x:%02x:%02x" \
|
|
Packit |
bc9a3a |
"$((${RANDOM}%256))" "$((${RANDOM}%256))" "$((${RANDOM}%256))")
|
|
Packit |
bc9a3a |
padmac "$random"
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
cleanup() {
|
|
Packit |
bc9a3a |
[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
|
|
Packit |
bc9a3a |
[ -z "${KVM_PID}" ] || kill "$KVM_PID"
|
|
Packit |
bc9a3a |
if [ ${#TAPDEVS[@]} -ne 0 ]; then
|
|
Packit |
bc9a3a |
local name item
|
|
Packit |
bc9a3a |
for item in "${TAPDEVS[@]}"; do
|
|
Packit |
bc9a3a |
[ "${item}" = "skip" ] && continue
|
|
Packit |
bc9a3a |
debug 1 "removing" "$item"
|
|
Packit |
bc9a3a |
name="${item%:*}"
|
|
Packit |
bc9a3a |
if $DRY_RUN; then
|
|
Packit |
bc9a3a |
error ip tuntap del mode tap "$name"
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
ip tuntap del mode tap "$name"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
[ $? -eq 0 ] || error "failed removal of $name"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
if [ ${#OVS_CLEANUP[@]} -ne 0 ]; then
|
|
Packit |
bc9a3a |
# with linux bridges, there seems to be no harm in just deleting
|
|
Packit |
bc9a3a |
# the device (not detaching from the bridge). However, with
|
|
Packit |
bc9a3a |
# ovs, you have to remove them from the bridge, or later it
|
|
Packit |
bc9a3a |
# will refuse to add the same name.
|
|
Packit |
bc9a3a |
error "cleaning up ovs ports: ${OVS_CLEANUP[@]}"
|
|
Packit |
bc9a3a |
if ${DRY_RUN}; then
|
|
Packit |
bc9a3a |
error sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
debug() {
|
|
Packit |
bc9a3a |
local level=${1}; shift;
|
|
Packit |
bc9a3a |
[ "${level}" -gt "${VERBOSITY}" ] && return
|
|
Packit |
bc9a3a |
error "${@}"
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
Usage() {
|
|
Packit |
bc9a3a |
cat <
|
|
Packit |
bc9a3a |
Usage: ${0##*/} [ options ] -- kvm-args [ ... ]
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
run kvm with a tap interface.
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
options:
|
|
Packit |
bc9a3a |
-n | --netdev NETDEV netdev can be 'user' or a bridge.
|
|
Packit |
bc9a3a |
default is to bridge to $DEF_BRIDGE
|
|
Packit |
bc9a3a |
-d | --disk DISK.img attach DISK.img as a disk (via virtio)
|
|
Packit |
bc9a3a |
--dry-run only report what would be done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
--uefi boot with efi
|
|
Packit |
bc9a3a |
--uefi-nvram=FILE boot with efi, using nvram settings in FILE
|
|
Packit |
bc9a3a |
if FILE not present, copy from defaults.
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
NETDEV:
|
|
Packit |
bc9a3a |
Above, 'NETDEV' is a comma delimited string
|
|
Packit |
bc9a3a |
The first field must be
|
|
Packit |
bc9a3a |
* bridge name: (br0 or virbr0): attach a device to this bridge
|
|
Packit |
bc9a3a |
* literal 'user': use qemu user networking
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
Additional fields are optional, and can be anything that is acceptable
|
|
Packit |
bc9a3a |
to kvm either as:
|
|
Packit |
bc9a3a |
* '-device virtio-net-pci' option (see 'kvm -device virtio-net-pci,?')
|
|
Packit |
bc9a3a |
* '-net [user|tap]' option
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
Example:
|
|
Packit |
bc9a3a |
* xkvm --netdev br0,macaddr=:05 -- -drive file=disk.img,if=virtio -curses
|
|
Packit |
bc9a3a |
attach a tap device to bridge 'br0' with mac address
|
|
Packit |
bc9a3a |
'${MAC_PREFIX}:05'
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
* xkvm --netdev user,mac=random --netdev br1,model=e1000,mac=auto -- -curses
|
|
Packit |
bc9a3a |
attach virtio user networking nic with random mac address
|
|
Packit |
bc9a3a |
attach tap device to br1 bridge as e1000 with unspecified mac
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
* xkvm --disk disk1.img
|
|
Packit |
bc9a3a |
EOF
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
isdevopt() {
|
|
Packit |
bc9a3a |
local model="$1" input="${2%%=*}"
|
|
Packit |
bc9a3a |
local out="" opt="" opts=()
|
|
Packit |
bc9a3a |
if [ -z "${KVM_DEVOPTS[$model]}" ]; then
|
|
Packit |
bc9a3a |
out=$($KVM -device "$model,?" 2>&1) &&
|
|
Packit |
bc9a3a |
out=$(echo "$out" | sed -e "s,[^.]*[.],," -e 's,=.*,,') &&
|
|
Packit |
bc9a3a |
KVM_DEVOPTS[$model]="$out" ||
|
|
Packit |
bc9a3a |
{ error "bad device model $model?"; exit 1; }
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
opts=( ${KVM_DEVOPTS[$model]} )
|
|
Packit |
bc9a3a |
for opt in "${opts[@]}"; do
|
|
Packit |
bc9a3a |
[ "$input" = "$opt" ] && return 0
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
return 1
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
qemu_supports_file_locking() {
|
|
Packit |
bc9a3a |
# hackily check if qemu has file.locking in -drive params (LP: #1716028)
|
|
Packit |
bc9a3a |
if [ -z "$_QEMU_SUPPORTS_FILE_LOCKING" ]; then
|
|
Packit |
bc9a3a |
# The only way we could find to check presense of file.locking is
|
|
Packit |
bc9a3a |
# qmp (query-qmp-schema). Simply checking if the virtio-blk driver
|
|
Packit |
bc9a3a |
# supports 'share-rw' is expected to be equivalent and simpler.
|
|
Packit |
bc9a3a |
isdevopt virtio-blk share-rw &&
|
|
Packit |
bc9a3a |
_QEMU_SUPPORTS_FILE_LOCKING=true ||
|
|
Packit |
bc9a3a |
_QEMU_SUPPORTS_FILE_LOCKING=false
|
|
Packit |
bc9a3a |
debug 1 "qemu supports file locking = ${_QEMU_SUPPORTS_FILE_LOCKING}"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
[ "$_QEMU_SUPPORTS_FILE_LOCKING" = "true" ]
|
|
Packit |
bc9a3a |
return
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
padmac() {
|
|
Packit |
bc9a3a |
# return a full mac, given a subset.
|
|
Packit |
bc9a3a |
# assume whatever is input is the last portion to be
|
|
Packit |
bc9a3a |
# returned, and fill it out with entries from MAC_PREFIX
|
|
Packit |
bc9a3a |
local mac="$1" num="$2" prefix="${3:-$MAC_PREFIX}" itoks="" ptoks=""
|
|
Packit |
bc9a3a |
# if input is empty set to :$num
|
|
Packit |
bc9a3a |
[ -n "$mac" ] || mac=$(printf "%02x" "$num") || return
|
|
Packit |
bc9a3a |
itoks=( ${mac//:/ } )
|
|
Packit |
bc9a3a |
ptoks=( ${prefix//:/ } )
|
|
Packit |
bc9a3a |
rtoks=( )
|
|
Packit |
bc9a3a |
for r in ${ptoks[@]:0:6-${#itoks[@]}} ${itoks[@]}; do
|
|
Packit |
bc9a3a |
rtoks[${#rtoks[@]}]="0x$r"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
_RET=$(printf "%02x:%02x:%02x:%02x:%02x:%02x" "${rtoks[@]}")
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
make_nics_Usage() {
|
|
Packit |
bc9a3a |
cat <
|
|
Packit |
bc9a3a |
Usage: ${0##*/} tap-control make-nics [options] bridge [bridge [..]]
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
make a tap device on each of bridges requested
|
|
Packit |
bc9a3a |
outputs: 'tapname:type' for each input, or 'skip' if nothing needed.
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
type is one of 'brctl' or 'ovs'
|
|
Packit |
bc9a3a |
EOF
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
make_nics() {
|
|
Packit |
bc9a3a |
# takes input of list of bridges to create a tap device on
|
|
Packit |
bc9a3a |
# and echos either 'skip' or
|
|
Packit |
bc9a3a |
# <tapname>:<type> for each tap created
|
|
Packit |
bc9a3a |
# type is one of "ovs" or "brctl"
|
|
Packit |
bc9a3a |
local short_opts="v"
|
|
Packit |
bc9a3a |
local long_opts="--verbose"
|
|
Packit |
bc9a3a |
local getopt_out=""
|
|
Packit |
bc9a3a |
getopt_out=$(getopt --name "${0##*/} make-nics" \
|
|
Packit |
bc9a3a |
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
|
|
Packit |
bc9a3a |
eval set -- "${getopt_out}" || { make_nics_Usage 1>&2; return 1; }
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local cur="" next=""
|
|
Packit |
bc9a3a |
while [ $# -ne 0 ]; do
|
|
Packit |
bc9a3a |
cur=${1}; next=${2};
|
|
Packit |
bc9a3a |
case "$cur" in
|
|
Packit |
bc9a3a |
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
|
|
Packit |
bc9a3a |
--) shift; break;;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
shift;
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
[ $# -ne 0 ] || {
|
|
Packit |
bc9a3a |
make_nics_Usage 1>&2; error "must give bridge";
|
|
Packit |
bc9a3a |
return 1;
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local owner="" ovsbrs="" tap="" tapnum="0" brtype="" bridge=""
|
|
Packit |
bc9a3a |
[ "$(id -u)" = "0" ] || { error "must be root for make-nics"; return 1; }
|
|
Packit |
bc9a3a |
owner="${SUDO_USER:-root}"
|
|
Packit |
bc9a3a |
ovsbrs=""
|
|
Packit |
bc9a3a |
if command -v ovs-vsctl >/dev/null 2>&1; then
|
|
Packit |
bc9a3a |
out=$(ovs-vsctl list-br)
|
|
Packit |
bc9a3a |
out=$(echo "$out" | sed "s/\n/,/")
|
|
Packit |
bc9a3a |
ovsbrs=",$out,"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
for bridge in "$@"; do
|
|
Packit |
bc9a3a |
[ "$bridge" = "user" ] && echo skip && continue
|
|
Packit |
bc9a3a |
[ "${ovsbrs#*,${bridge},}" != "$ovsbrs" ] &&
|
|
Packit |
bc9a3a |
btype="ovs" || btype="brctl"
|
|
Packit |
bc9a3a |
tapnum=0;
|
|
Packit |
bc9a3a |
while [ -e /sys/class/net/tapvm$tapnum ]; do tapnum=$(($tapnum+1)); done
|
|
Packit |
bc9a3a |
tap="tapvm$tapnum"
|
|
Packit |
bc9a3a |
debug 1 "creating $tap:$btype on $bridge" 1>&2
|
|
Packit |
bc9a3a |
ip tuntap add mode tap user "$owner" "$tap" ||
|
|
Packit |
bc9a3a |
{ error "failed to create tap '$tap' for '$owner'"; return 1; }
|
|
Packit |
bc9a3a |
ip link set "$tap" up 1>&2 || {
|
|
Packit |
bc9a3a |
error "failed to bring up $tap";
|
|
Packit |
bc9a3a |
ip tuntap del mode tap "$tap";
|
|
Packit |
bc9a3a |
return 1;
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
if [ "$btype" = "ovs" ]; then
|
|
Packit |
bc9a3a |
ovs-vsctl add-port "$bridge" "$tap" 1>&2 || {
|
|
Packit |
bc9a3a |
error "failed: ovs-vsctl add-port $bridge $tap";
|
|
Packit |
bc9a3a |
ovs-vsctl del-port "$bridge" "$tap"
|
|
Packit |
bc9a3a |
return 1;
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
ip link set "$tap" master "$bridge" 1>&2 || {
|
|
Packit |
bc9a3a |
error "failed to add tap '$tap' to '$bridge'"
|
|
Packit |
bc9a3a |
ip tuntap del mode tap "$tap";
|
|
Packit |
bc9a3a |
return 1
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
echo "$tap:$btype"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
ovs_cleanup() {
|
|
Packit |
bc9a3a |
[ "$(id -u)" = "0" ] ||
|
|
Packit |
bc9a3a |
{ error "must be root for ovs-cleanup"; return 1; }
|
|
Packit |
bc9a3a |
local item="" errors=0
|
|
Packit |
bc9a3a |
# TODO: if get owner (SUDO_USERNAME) and if that isn't
|
|
Packit |
bc9a3a |
# the owner, then do not delete.
|
|
Packit |
bc9a3a |
for item in "$@"; do
|
|
Packit |
bc9a3a |
name=${item#*:}
|
|
Packit |
bc9a3a |
bridge=${item%:*}
|
|
Packit |
bc9a3a |
ovs-vsctl del-port "$bridge" "$name" || errors=$((errors+1))
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
return $errors
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
quote_cmd() {
|
|
Packit |
bc9a3a |
local quote='"' x="" vline=""
|
|
Packit |
bc9a3a |
for x in "$@"; do
|
|
Packit |
bc9a3a |
if [ "${x#* }" != "${x}" ]; then
|
|
Packit |
bc9a3a |
if [ "${x#*$quote}" = "${x}" ]; then
|
|
Packit |
bc9a3a |
x="\"$x\""
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
x="'$x'"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
vline="${vline} $x"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
echo "$vline"
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
get_bios_opts() {
|
|
Packit |
bc9a3a |
# get_bios_opts(bios, uefi, nvram)
|
|
Packit |
bc9a3a |
# bios is a explicit bios to boot.
|
|
Packit |
bc9a3a |
# uefi is boolean indicating uefi
|
|
Packit |
bc9a3a |
# nvram is optional and indicates that ovmf vars should be copied
|
|
Packit |
bc9a3a |
# to that file if it does not exist. if it exists, use it.
|
|
Packit |
bc9a3a |
local bios="$1" uefi="${2:-false}" nvram="$3"
|
|
Packit |
bc9a3a |
local ovmf_dir="/usr/share/OVMF"
|
|
Packit |
bc9a3a |
local bios_opts="" pflash_common="if=pflash,format=raw"
|
|
Packit |
bc9a3a |
unset _RET
|
|
Packit |
bc9a3a |
_RET=( )
|
|
Packit |
bc9a3a |
if [ -n "$bios" ]; then
|
|
Packit |
bc9a3a |
_RET=( -drive "${pflash_common},file=$bios" )
|
|
Packit |
bc9a3a |
return 0
|
|
Packit |
bc9a3a |
elif ! $uefi; then
|
|
Packit |
bc9a3a |
return 0
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
# ovmf in older releases (14.04) shipped only a single file
|
|
Packit |
bc9a3a |
# /usr/share/ovmf/OVMF.fd
|
|
Packit |
bc9a3a |
# newer ovmf ships split files
|
|
Packit |
bc9a3a |
# /usr/share/OVMF/OVMF_CODE.fd
|
|
Packit |
bc9a3a |
# /usr/share/OVMF/OVMF_VARS.fd
|
|
Packit |
bc9a3a |
# with single file, pass only one file and read-write
|
|
Packit |
bc9a3a |
# with split, pass code as readonly and vars as read-write
|
|
Packit |
bc9a3a |
local joined="/usr/share/ovmf/OVMF.fd"
|
|
Packit |
bc9a3a |
local code="/usr/share/OVMF/OVMF_CODE.fd"
|
|
Packit |
bc9a3a |
local vars="/usr/share/OVMF/OVMF_VARS.fd"
|
|
Packit |
bc9a3a |
local split="" nvram_src=""
|
|
Packit |
bc9a3a |
if [ -e "$code" -o -e "$vars" ]; then
|
|
Packit |
bc9a3a |
split=true
|
|
Packit |
bc9a3a |
nvram_src="$vars"
|
|
Packit |
bc9a3a |
elif [ -e "$joined" ]; then
|
|
Packit |
bc9a3a |
split=false
|
|
Packit |
bc9a3a |
nvram_src="$joined"
|
|
Packit |
bc9a3a |
elif [ -n "$nvram" -a -e "$nvram" ]; then
|
|
Packit |
bc9a3a |
error "WARN: nvram given, but did not find expected ovmf files."
|
|
Packit |
bc9a3a |
error " assuming this is code and vars (OVMF.fd)"
|
|
Packit |
bc9a3a |
split=false
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
error "uefi support requires ovmf bios: apt-get install -qy ovmf"
|
|
Packit |
bc9a3a |
return 1
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if [ -n "$nvram" ]; then
|
|
Packit |
bc9a3a |
if [ ! -f "$nvram" ]; then
|
|
Packit |
bc9a3a |
cp "$nvram_src" "$nvram" ||
|
|
Packit |
bc9a3a |
{ error "failed copy $nvram_src to $nvram"; return 1; }
|
|
Packit |
bc9a3a |
debug 1 "copied $nvram_src to $nvram"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
debug 1 "uefi without --uefi-nvram storage." \
|
|
Packit |
bc9a3a |
"nvram settings likely will not persist."
|
|
Packit |
bc9a3a |
nvram="${nvram_src}"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if [ ! -w "$nvram" ]; then
|
|
Packit |
bc9a3a |
debug 1 "nvram file ${nvram} is readonly"
|
|
Packit |
bc9a3a |
nvram_ro="readonly"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if $split; then
|
|
Packit |
bc9a3a |
# to ensure bootability firmware must be first, then variables
|
|
Packit |
bc9a3a |
_RET=( -drive "${pflash_common},file=$code,readonly" )
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
_RET=( "${_RET[@]}"
|
|
Packit |
bc9a3a |
-drive "${pflash_common},file=$nvram${nvram_ro:+,${nvram_ro}}" )
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
main() {
|
|
Packit |
bc9a3a |
local short_opts="hd:n:v"
|
|
Packit |
bc9a3a |
local long_opts="bios:,help,dowait,disk:,dry-run,kvm:,no-dowait,netdev:,uefi,uefi-nvram:,verbose"
|
|
Packit |
bc9a3a |
local getopt_out=""
|
|
Packit |
bc9a3a |
getopt_out=$(getopt --name "${0##*/}" \
|
|
Packit |
bc9a3a |
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
|
|
Packit |
bc9a3a |
eval set -- "${getopt_out}" || { bad_Usage; return 1; }
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local bridge="$DEF_BRIDGE" oifs="$IFS"
|
|
Packit |
bc9a3a |
local netdevs="" need_tap="" ret="" p="" i="" pt="" cur="" conn=""
|
|
Packit |
bc9a3a |
local kvm="" kvmcmd="" archopts=""
|
|
Packit |
bc9a3a |
local def_disk_driver=${DEF_DISK_DRIVER:-"virtio-blk"}
|
|
Packit |
bc9a3a |
local def_netmodel=${DEF_NETMODEL:-"virtio-net-pci"}
|
|
Packit |
bc9a3a |
local bios="" uefi=false uefi_nvram=""
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
archopts=( )
|
|
Packit |
bc9a3a |
kvmcmd=( )
|
|
Packit |
bc9a3a |
netdevs=( )
|
|
Packit |
bc9a3a |
addargs=( )
|
|
Packit |
bc9a3a |
diskdevs=( )
|
|
Packit |
bc9a3a |
diskargs=( )
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
# dowait: run qemu-system with a '&' and then 'wait' on the pid.
|
|
Packit |
bc9a3a |
# the reason to do this or not do this has to do with interactivity
|
|
Packit |
bc9a3a |
# if detached with &, then user input will not go to xkvm.
|
|
Packit |
bc9a3a |
# if *not* detached, then signal handling is blocked until
|
|
Packit |
bc9a3a |
# the foreground subprocess returns. which means we can't handle
|
|
Packit |
bc9a3a |
# a sigterm and kill the qemu-system process.
|
|
Packit |
bc9a3a |
# We default to dowait=false if input and output are a terminal
|
|
Packit |
bc9a3a |
local dowait=""
|
|
Packit |
bc9a3a |
[ -t 0 -a -t 1 ] && dowait=false || dowait=true
|
|
Packit |
bc9a3a |
while [ $# -ne 0 ]; do
|
|
Packit |
bc9a3a |
cur=${1}; next=${2};
|
|
Packit |
bc9a3a |
case "$cur" in
|
|
Packit |
bc9a3a |
-h|--help) Usage; exit 0;;
|
|
Packit |
bc9a3a |
-d|--disk)
|
|
Packit |
bc9a3a |
diskdevs[${#diskdevs[@]}]="$next"; shift;;
|
|
Packit |
bc9a3a |
--dry-run) DRY_RUN=true;;
|
|
Packit |
bc9a3a |
--kvm) kvm="$next"; shift;;
|
|
Packit |
bc9a3a |
-n|--netdev)
|
|
Packit |
bc9a3a |
netdevs[${#netdevs[@]}]=$next; shift;;
|
|
Packit |
bc9a3a |
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
|
|
Packit |
bc9a3a |
--dowait) dowait=true;;
|
|
Packit |
bc9a3a |
--no-dowait) dowait=false;;
|
|
Packit |
bc9a3a |
--bios) bios="$next"; shift;;
|
|
Packit |
bc9a3a |
--uefi) uefi=true;;
|
|
Packit |
bc9a3a |
--uefi-nvram) uefi=true; uefi_nvram="$next"; shift;;
|
|
Packit |
bc9a3a |
--) shift; break;;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
shift;
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
[ ${#netdevs[@]} -eq 0 ] && netdevs=( "${DEF_BRIDGE}" )
|
|
Packit |
bc9a3a |
pt=( "$@" )
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local kvm_pkg="" virtio_scsi_bus="virtio-scsi-pci" virtio_rng_device="virtio-rng-pci"
|
|
Packit |
bc9a3a |
[ -n "$kvm" ] && kvm_pkg="none"
|
|
Packit |
bc9a3a |
case $(uname -m) in
|
|
Packit |
bc9a3a |
i?86)
|
|
Packit |
bc9a3a |
[ -n "$kvm" ] ||
|
|
Packit |
bc9a3a |
{ kvm="qemu-system-i386"; kvm_pkg="qemu-system-x86"; }
|
|
Packit |
bc9a3a |
;;
|
|
Packit |
bc9a3a |
x86_64)
|
|
Packit |
bc9a3a |
[ -n "$kvm" ] ||
|
|
Packit |
bc9a3a |
{ kvm="qemu-system-x86_64"; kvm_pkg="qemu-system-x86"; }
|
|
Packit |
bc9a3a |
;;
|
|
Packit |
bc9a3a |
s390x)
|
|
Packit |
bc9a3a |
[ -n "$kvm" ] ||
|
|
Packit |
bc9a3a |
{ kvm="qemu-system-s390x"; kvm_pkg="qemu-system-misc"; }
|
|
Packit |
bc9a3a |
def_netmodel=${DEF_NETMODEL:-"virtio-net-ccw"}
|
|
Packit |
bc9a3a |
# disable virtio-scsi-bus
|
|
Packit |
bc9a3a |
virtio_scsi_bus="virtio-scsi-ccw"
|
|
Packit |
bc9a3a |
virtio_blk_bus="virtio-blk-ccw"
|
|
Packit |
bc9a3a |
virtio_rng_device="virtio-rng-ccw"
|
|
Packit |
bc9a3a |
;;
|
|
Packit |
bc9a3a |
ppc64*)
|
|
Packit |
bc9a3a |
[ -n "$kvm" ] ||
|
|
Packit |
bc9a3a |
{ kvm="qemu-system-ppc64"; kvm_pkg="qemu-system-ppc"; }
|
|
Packit |
bc9a3a |
def_netmodel="virtio-net-pci"
|
|
Packit |
bc9a3a |
# virtio seems functional on in 14.10, but might want scsi here
|
|
Packit |
bc9a3a |
#def_diskif="scsi"
|
|
Packit |
bc9a3a |
archopts=( "${archopts[@]}" -machine pseries,usb=off )
|
|
Packit |
bc9a3a |
archopts=( "${archopts[@]}" -device spapr-vscsi )
|
|
Packit |
bc9a3a |
;;
|
|
Packit |
bc9a3a |
*) kvm=qemu-system-$(uname -m);;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
KVM="$kvm"
|
|
Packit |
bc9a3a |
kvmcmd=( $kvm -enable-kvm )
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local bios_opts=""
|
|
Packit |
bc9a3a |
if [ -n "$bios" ] && $uefi; then
|
|
Packit |
bc9a3a |
error "--uefi (or --uefi-nvram) is incompatible with --bios"
|
|
Packit |
bc9a3a |
return 1
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
get_bios_opts "$bios" "$uefi" "$uefi_nvram" ||
|
|
Packit |
bc9a3a |
{ error "failed to get bios opts"; return 1; }
|
|
Packit |
bc9a3a |
bios_opts=( "${_RET[@]}" )
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local out="" fmt="" bus="" unit="" index="" serial="" driver="" devopts=""
|
|
Packit |
bc9a3a |
local busorindex="" driveopts="" cur="" val="" file="" wwn=""
|
|
Packit |
bc9a3a |
for((i=0;i<${#diskdevs[@]};i++)); do
|
|
Packit |
bc9a3a |
cur=${diskdevs[$i]}
|
|
Packit |
bc9a3a |
IFS=","; set -- $cur; IFS="$oifs"
|
|
Packit |
bc9a3a |
driver=""
|
|
Packit |
bc9a3a |
id=$(printf "disk%02d" "$i")
|
|
Packit |
bc9a3a |
file=""
|
|
Packit |
bc9a3a |
fmt=""
|
|
Packit |
bc9a3a |
bus=""
|
|
Packit |
bc9a3a |
unit=""
|
|
Packit |
bc9a3a |
index=""
|
|
Packit |
bc9a3a |
serial=""
|
|
Packit |
bc9a3a |
wwn=""
|
|
Packit |
bc9a3a |
for tok in "$@"; do
|
|
Packit |
bc9a3a |
[ "${tok#*=}" = "${tok}" -a -f "${tok}" -a -z "$file" ] && file="$tok"
|
|
Packit |
bc9a3a |
val=${tok#*=}
|
|
Packit |
bc9a3a |
case "$tok" in
|
|
Packit |
bc9a3a |
driver=*) driver=$val;;
|
|
Packit |
bc9a3a |
if=virtio) driver=virtio-blk;;
|
|
Packit |
bc9a3a |
if=scsi) driver=scsi-hd;;
|
|
Packit |
bc9a3a |
if=pflash) driver=;;
|
|
Packit |
bc9a3a |
if=sd|if=mtd|floppy) fail "do not know what to do with $tok on $cur";;
|
|
Packit |
bc9a3a |
id=*) id=$val;;
|
|
Packit |
bc9a3a |
file=*) file=$val;;
|
|
Packit |
bc9a3a |
fmt=*|format=*) fmt=$val;;
|
|
Packit |
bc9a3a |
serial=*) serial=$val;;
|
|
Packit |
bc9a3a |
wwn=*) wwn=$val;;
|
|
Packit |
bc9a3a |
bus=*) bus=$val;;
|
|
Packit |
bc9a3a |
unit=*) unit=$val;;
|
|
Packit |
bc9a3a |
index=*) index=$val;;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
[ -z "$file" ] && fail "did not read a file from $cur"
|
|
Packit |
bc9a3a |
if [ -f "$file" -a -z "$fmt" ]; then
|
|
Packit |
bc9a3a |
out=$(LANG=C qemu-img info "$file") &&
|
|
Packit |
bc9a3a |
fmt=$(echo "$out" | awk '$0 ~ /^file format:/ { print $3 }') ||
|
|
Packit |
bc9a3a |
{ error "failed to determine format of $file"; return 1; }
|
|
Packit |
bc9a3a |
elif [ -z "$fmt" ]; then
|
|
Packit |
bc9a3a |
fmt=raw
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
if [ -z "$driver" ]; then
|
|
Packit |
bc9a3a |
driver="$def_disk_driver"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
if [ -z "$serial" ]; then
|
|
Packit |
bc9a3a |
# use filename as serial if not provided a wwn
|
|
Packit |
bc9a3a |
if [ -n "$wwn" ]; then
|
|
Packit |
bc9a3a |
serial="$wwn"
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
serial="${file##*/}"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
# make sure we add either bus= or index=
|
|
Packit |
bc9a3a |
if [ -n "$bus" -o "$unit" ] && [ -n "$index" ]; then
|
|
Packit |
bc9a3a |
fail "bus and index cant be specified together: $cur"
|
|
Packit |
bc9a3a |
elif [ -z "$bus" -a -z "$unit" -a -z "$index" ]; then
|
|
Packit |
bc9a3a |
index=$i
|
|
Packit |
bc9a3a |
elif [ -n "$bus" -a -z "$unit" ]; then
|
|
Packit |
bc9a3a |
unit=$i
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
busorindex="${bus:+bus=$bus,unit=$unit}${index:+index=${index}}"
|
|
Packit |
bc9a3a |
diskopts="file=${file},id=$id,if=none,format=$fmt,$busorindex"
|
|
Packit |
bc9a3a |
devopts="$driver,drive=$id${serial:+,serial=${serial}}"
|
|
Packit |
bc9a3a |
for tok in "$@"; do
|
|
Packit |
bc9a3a |
case "$tok" in
|
|
Packit |
bc9a3a |
id=*|if=*|driver=*|$file|file=*) continue;;
|
|
Packit |
bc9a3a |
fmt=*|format=*) continue;;
|
|
Packit |
bc9a3a |
serial=*|bus=*|unit=*|index=*) continue;;
|
|
Packit |
bc9a3a |
file.locking=*)
|
|
Packit |
bc9a3a |
qemu_supports_file_locking || {
|
|
Packit |
bc9a3a |
debug 2 "qemu has no file locking." \
|
|
Packit |
bc9a3a |
"Dropping '$tok' from: $cur"
|
|
Packit |
bc9a3a |
continue
|
|
Packit |
bc9a3a |
};;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
isdevopt "$driver" "$tok" && devopts="${devopts},$tok" ||
|
|
Packit |
bc9a3a |
diskopts="${diskopts},${tok}"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
case $driver in
|
|
Packit |
bc9a3a |
virtio-blk-ccw)
|
|
Packit |
bc9a3a |
# disable scsi when using virtio-blk-ccw
|
|
Packit |
bc9a3a |
devopts="${devopts},scsi=off";;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
diskargs=( "${diskargs[@]}" -drive "$diskopts" -device "$devopts" )
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local mnics_vflag=""
|
|
Packit |
bc9a3a |
for((i=0;i<${VERBOSITY}-1;i++)); do mnics_vflag="${mnics_vflag}v"; done
|
|
Packit |
bc9a3a |
[ -n "$mnics_vflag" ] && mnics_vflag="-${mnics_vflag}"
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
# now go through and split out options
|
|
Packit |
bc9a3a |
# -device virtio-net-pci,netdev=virtnet0,mac=52:54:31:15:63:02
|
|
Packit |
bc9a3a |
# -netdev type=tap,id=virtnet0,vhost=on,script=/etc/kvm/kvm-ifup.br0,downscript=no
|
|
Packit |
bc9a3a |
local netopts="" devopts="" id="" need_taps=0 model=""
|
|
Packit |
bc9a3a |
local device_args netdev_args
|
|
Packit |
bc9a3a |
device_args=( )
|
|
Packit |
bc9a3a |
netdev_args=( )
|
|
Packit |
bc9a3a |
connections=( )
|
|
Packit |
bc9a3a |
for((i=0;i<${#netdevs[@]};i++)); do
|
|
Packit |
bc9a3a |
id=$(printf "net%02d" "$i")
|
|
Packit |
bc9a3a |
netopts="";
|
|
Packit |
bc9a3a |
devopts=""
|
|
Packit |
bc9a3a |
# mac=auto is 'unspecified' (let qemu assign one)
|
|
Packit |
bc9a3a |
mac="auto"
|
|
Packit |
bc9a3a |
#vhost="off"
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
IFS=","; set -- ${netdevs[$i]}; IFS="$oifs"
|
|
Packit |
bc9a3a |
bridge=$1; shift;
|
|
Packit |
bc9a3a |
if [ "$bridge" = "user" ]; then
|
|
Packit |
bc9a3a |
netopts="type=user"
|
|
Packit |
bc9a3a |
ntype="user"
|
|
Packit |
bc9a3a |
connections[$i]="user"
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
need_taps=1
|
|
Packit |
bc9a3a |
ntype="tap"
|
|
Packit |
bc9a3a |
netopts="type=tap"
|
|
Packit |
bc9a3a |
connections[$i]="$bridge"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
netopts="${netopts},id=$id"
|
|
Packit |
bc9a3a |
[ "$ntype" = "tap" ] && netopts="${netopts},script=no,downscript=no"
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
model="${def_netmodel}"
|
|
Packit |
bc9a3a |
for tok in "$@"; do
|
|
Packit |
bc9a3a |
[ "${tok#model=}" = "${tok}" ] && continue
|
|
Packit |
bc9a3a |
case "${tok#model=}" in
|
|
Packit |
bc9a3a |
virtio) model=virtio-net-pci;;
|
|
Packit |
bc9a3a |
*) model=${tok#model=};;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
for tok in "$@"; do
|
|
Packit |
bc9a3a |
case "$tok" in
|
|
Packit |
bc9a3a |
mac=*) mac="${tok#mac=}"; continue;;
|
|
Packit |
bc9a3a |
macaddr=*) mac=${tok#macaddr=}; continue;;
|
|
Packit |
bc9a3a |
model=*) continue;;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
isdevopt "$model" "$tok" && devopts="${devopts},$tok" ||
|
|
Packit |
bc9a3a |
netopts="${netopts},${tok}"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
devopts=${devopts#,}
|
|
Packit |
bc9a3a |
netopts=${netopts#,}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if [ "$mac" != "auto" ]; then
|
|
Packit |
bc9a3a |
[ "$mac" = "random" ] && randmac && mac="$_RET"
|
|
Packit |
bc9a3a |
padmac "$mac" "$i"
|
|
Packit |
bc9a3a |
devopts="${devopts:+${devopts},}mac=$_RET"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
devopts="$model,netdev=$id${devopts:+,${devopts}}"
|
|
Packit |
bc9a3a |
#netopts="${netopts},vhost=${vhost}"
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
device_args[$i]="$devopts"
|
|
Packit |
bc9a3a |
netdev_args[$i]="$netopts"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
trap cleanup EXIT
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
reqs=( "$kvm" )
|
|
Packit |
bc9a3a |
pkgs=( "$kvm_pkg" )
|
|
Packit |
bc9a3a |
for((i=0;i<${#reqs[@]};i++)); do
|
|
Packit |
bc9a3a |
req=${reqs[$i]}
|
|
Packit |
bc9a3a |
pkg=${pkgs[$i]}
|
|
Packit |
bc9a3a |
[ "$pkg" = "none" ] && continue
|
|
Packit |
bc9a3a |
command -v "$req" >/dev/null || {
|
|
Packit |
bc9a3a |
missing="${missing:+${missing} }${req}"
|
|
Packit |
bc9a3a |
missing_pkgs="${missing_pkgs:+${missing_pkgs} }$pkg"
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
if [ -n "$missing" ]; then
|
|
Packit |
bc9a3a |
local reply cmd=""
|
|
Packit |
bc9a3a |
cmd=( sudo apt-get --quiet install ${missing_pkgs} )
|
|
Packit |
bc9a3a |
error "missing prereqs: $missing";
|
|
Packit |
bc9a3a |
error "install them now with the following?: ${cmd[*]}"
|
|
Packit |
bc9a3a |
read reply && [ "$reply" = "y" -o "$reply" = "Y" ] ||
|
|
Packit |
bc9a3a |
{ error "run: apt-get install ${missing_pkgs}"; return 1; }
|
|
Packit |
bc9a3a |
"${cmd[@]}" || { error "failed to install packages"; return 1; }
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if [ $need_taps -ne 0 ]; then
|
|
Packit |
bc9a3a |
local missing="" missing_pkgs="" reqs="" req="" pkgs="" pkg=""
|
|
Packit |
bc9a3a |
for i in "${connections[@]}"; do
|
|
Packit |
bc9a3a |
[ "$i" = "user" -o -e "/sys/class/net/$i" ] ||
|
|
Packit |
bc9a3a |
missing="${missing} $i"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
[ -z "$missing" ] || {
|
|
Packit |
bc9a3a |
error "cannot create connection on: ${missing# }."
|
|
Packit |
bc9a3a |
error "bridges do not exist.";
|
|
Packit |
bc9a3a |
return 1;
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
error "creating tap devices: ${connections[*]}"
|
|
Packit |
bc9a3a |
if $DRY_RUN; then
|
|
Packit |
bc9a3a |
error "sudo $0 tap-control make-nics" \
|
|
Packit |
bc9a3a |
$mnics_vflag "${connections[@]}"
|
|
Packit |
bc9a3a |
taps=""
|
|
Packit |
bc9a3a |
for((i=0;i<${#connections[@]};i++)); do
|
|
Packit |
bc9a3a |
if [ "${connections[$i]}" = "user" ]; then
|
|
Packit |
bc9a3a |
taps="${taps} skip"
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
taps="${taps} dryruntap$i:brctl"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
taps=$(sudo "$0" tap-control make-nics \
|
|
Packit |
bc9a3a |
${mnics_vflag} "${connections[@]}") ||
|
|
Packit |
bc9a3a |
{ error "$failed to make-nics ${connections[*]}"; return 1; }
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
TAPDEVS=( ${taps} )
|
|
Packit |
bc9a3a |
for((i=0;i<${#TAPDEVS[@]};i++)); do
|
|
Packit |
bc9a3a |
cur=${TAPDEVS[$i]}
|
|
Packit |
bc9a3a |
[ "${cur#*:}" = "ovs" ] || continue
|
|
Packit |
bc9a3a |
conn=${connections[$i]}
|
|
Packit |
bc9a3a |
OVS_CLEANUP[${#OVS_CLEANUP[@]}]="${conn}:${cur%:*}"
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
debug 2 "tapdevs='${TAPDEVS[@]}'"
|
|
Packit |
bc9a3a |
[ ${#OVS_CLEANUP[@]} -eq 0 ] || error "OVS_CLEANUP='${OVS_CLEANUP[*]}'"
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
for((i=0;i<${#TAPDEVS[@]};i++)); do
|
|
Packit |
bc9a3a |
cur=${TAPDEVS[$i]}
|
|
Packit |
bc9a3a |
[ "$cur" = "skip" ] && continue
|
|
Packit |
bc9a3a |
netdev_args[$i]="${netdev_args[$i]},ifname=${cur%:*}";
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
netargs=()
|
|
Packit |
bc9a3a |
for((i=0;i<${#device_args[@]};i++)); do
|
|
Packit |
bc9a3a |
netargs=( "${netargs[@]}" -device "${device_args[$i]}"
|
|
Packit |
bc9a3a |
-netdev "${netdev_args[$i]}")
|
|
Packit |
bc9a3a |
done
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
local bus_devices
|
|
Packit |
bc9a3a |
if [ -n "${virtio_scsi_bus}" ]; then
|
|
Packit |
bc9a3a |
bus_devices=( -device "$virtio_scsi_bus,id=virtio-scsi-xkvm" )
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
local rng_devices
|
|
Packit |
bc9a3a |
rng_devices=( -object "rng-random,filename=/dev/urandom,id=objrng0"
|
|
Packit |
bc9a3a |
-device "$virtio_rng_device,rng=objrng0,id=rng0" )
|
|
Packit |
bc9a3a |
cmd=( "${kvmcmd[@]}" "${archopts[@]}"
|
|
Packit |
bc9a3a |
"${bios_opts[@]}"
|
|
Packit |
bc9a3a |
"${bus_devices[@]}"
|
|
Packit |
bc9a3a |
"${rng_devices[@]}"
|
|
Packit |
bc9a3a |
"${netargs[@]}"
|
|
Packit |
bc9a3a |
"${diskargs[@]}" "${pt[@]}" )
|
|
Packit |
bc9a3a |
local pcmd=$(quote_cmd "${cmd[@]}")
|
|
Packit |
bc9a3a |
error "$pcmd"
|
|
Packit |
bc9a3a |
${DRY_RUN} && return 0
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if $dowait; then
|
|
Packit |
bc9a3a |
"${cmd[@]}" &
|
|
Packit |
bc9a3a |
KVM_PID=$!
|
|
Packit |
bc9a3a |
debug 1 "kvm pid=$KVM_PID. my pid=$$"
|
|
Packit |
bc9a3a |
wait
|
|
Packit |
bc9a3a |
ret=$?
|
|
Packit |
bc9a3a |
KVM_PID=""
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
"${cmd[@]}"
|
|
Packit |
bc9a3a |
ret=$?
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
return $ret
|
|
Packit |
bc9a3a |
}
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
if [ "$1" = "tap-control" ]; then
|
|
Packit |
bc9a3a |
shift
|
|
Packit |
bc9a3a |
mode=$1
|
|
Packit |
bc9a3a |
shift || fail "must give mode to tap-control"
|
|
Packit |
bc9a3a |
case "$mode" in
|
|
Packit |
bc9a3a |
make-nics) make_nics "$@";;
|
|
Packit |
bc9a3a |
ovs-cleanup) ovs_cleanup "$@";;
|
|
Packit |
bc9a3a |
*) fail "tap mode must be either make-nics or ovs-cleanup";;
|
|
Packit |
bc9a3a |
esac
|
|
Packit |
bc9a3a |
else
|
|
Packit |
bc9a3a |
main "$@"
|
|
Packit |
bc9a3a |
fi
|
|
Packit |
bc9a3a |
|
|
Packit |
bc9a3a |
# vi: ts=4 expandtab syntax=sh
|