Merge ~powersj/cloud-init:add-xkvm into cloud-init:master

Proposed by Joshua Powers
Status: Merged
Merged at revision: a4c1d578070145023ae88a9f79f8517e36b52559
Proposed branch: ~powersj/cloud-init:add-xkvm
Merge into: cloud-init:master
Diff against target: 670 lines (+664/-0)
1 file modified
tools/xkvm (+664/-0)
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
cloud-init Commiters Pending
Review via email: mp+330536@code.launchpad.net

Commit message

tools: Add xkvm script, wrapper around qemu-system

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:210024716c2173249539ff9847cbca36e89555c7
https://jenkins.ubuntu.com/server/job/cloud-init-ci/282/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/282/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chad Smith (chad.smith) :

There was an error fetching revisions from git servers. Please try again in a few minutes. If the problem persists, contact Launchpad support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/tools/xkvm b/tools/xkvm
0new file mode 1007550new file mode 100755
index 0000000..a30ba91
--- /dev/null
+++ b/tools/xkvm
@@ -0,0 +1,664 @@
1#!/bin/bash
2
3set -f
4
5VERBOSITY=0
6KVM_PID=""
7DRY_RUN=false
8TEMP_D=""
9DEF_BRIDGE="virbr0"
10TAPDEVS=( )
11# OVS_CLEANUP gets populated with bridge:devname pairs used with ovs
12OVS_CLEANUP=( )
13MAC_PREFIX="52:54:00:12:34"
14KVM="kvm"
15declare -A KVM_DEVOPTS
16
17error() { echo "$@" 1>&2; }
18fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
19
20bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
21randmac() {
22 # return random mac addr within final 3 tokens
23 local random=""
24 random=$(printf "%02x:%02x:%02x" \
25 "$((${RANDOM}%256))" "$((${RANDOM}%256))" "$((${RANDOM}%256))")
26 padmac "$random"
27}
28
29cleanup() {
30 [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
31 [ -z "${KVM_PID}" ] || kill "$KVM_PID"
32 if [ ${#TAPDEVS[@]} -ne 0 ]; then
33 local name item
34 for item in "${TAPDEVS[@]}"; do
35 [ "${item}" = "skip" ] && continue
36 debug 1 "removing" "$item"
37 name="${item%:*}"
38 if $DRY_RUN; then
39 error ip tuntap del mode tap "$name"
40 else
41 ip tuntap del mode tap "$name"
42 fi
43 [ $? -eq 0 ] || error "failed removal of $name"
44 done
45 if [ ${#OVS_CLEANUP[@]} -ne 0 ]; then
46 # with linux bridges, there seems to be no harm in just deleting
47 # the device (not detaching from the bridge). However, with
48 # ovs, you have to remove them from the bridge, or later it
49 # will refuse to add the same name.
50 error "cleaning up ovs ports: ${OVS_CLEANUP[@]}"
51 if ${DRY_RUN}; then
52 error sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
53 else
54 sudo "$0" tap-control ovs-cleanup "${OVS_CLEANUP[@]}"
55 fi
56 fi
57 fi
58}
59
60debug() {
61 local level=${1}; shift;
62 [ "${level}" -gt "${VERBOSITY}" ] && return
63 error "${@}"
64}
65
66Usage() {
67 cat <<EOF
68Usage: ${0##*/} [ options ] -- kvm-args [ ... ]
69
70 run kvm with a tap interface.
71
72 options:
73 -n | --netdev NETDEV netdev can be 'user' or a bridge.
74 default is to bridge to $DEF_BRIDGE
75 -d | --disk DISK.img attach DISK.img as a disk (via virtio)
76 --dry-run only report what would be done
77
78 --uefi boot with efi
79 --uefi-nvram=FILE boot with efi, using nvram settings in FILE
80 if FILE not present, copy from defaults.
81
82 NETDEV:
83 Above, 'NETDEV' is a comma delimited string
84 The first field must be
85 * bridge name: (br0 or virbr0): attach a device to this bridge
86 * literal 'user': use qemu user networking
87
88 Additional fields are optional, and can be anything that is acceptable
89 to kvm either as:
90 * '-device virtio-net-pci' option (see 'kvm -device virtio-net-pci,?')
91 * '-net [user|tap]' option
92
93 Example:
94 * xkvm --netdev br0,macaddr=:05 -- -drive file=disk.img,if=virtio -curses
95 attach a tap device to bridge 'br0' with mac address
96 '${MAC_PREFIX}:05'
97
98 * xkvm --netdev user,mac=random --netdev br1,model=e1000,mac=auto -- -curses
99 attach virtio user networking nic with random mac address
100 attach tap device to br1 bridge as e1000 with unspecified mac
101
102 * xkvm --disk disk1.img
103EOF
104}
105
106isdevopt() {
107 local model="$1" input="${2%%=*}"
108 local out="" opt="" opts=()
109 if [ -z "${KVM_DEVOPTS[$model]}" ]; then
110 out=$($KVM -device "$model,?" 2>&1) &&
111 out=$(echo "$out" | sed -e "s,[^.]*[.],," -e 's,=.*,,') &&
112 KVM_DEVOPTS[$model]="$out" ||
113 { error "bad device model $model?"; exit 1; }
114 fi
115 opts=( ${KVM_DEVOPTS[$model]} )
116 for opt in "${opts[@]}"; do
117 [ "$input" = "$opt" ] && return 0
118 done
119 return 1
120}
121
122padmac() {
123 # return a full mac, given a subset.
124 # assume whatever is input is the last portion to be
125 # returned, and fill it out with entries from MAC_PREFIX
126 local mac="$1" num="$2" prefix="${3:-$MAC_PREFIX}" itoks="" ptoks=""
127 # if input is empty set to :$num
128 [ -n "$mac" ] || mac=$(printf "%02x" "$num") || return
129 itoks=( ${mac//:/ } )
130 ptoks=( ${prefix//:/ } )
131 rtoks=( )
132 for r in ${ptoks[@]:0:6-${#itoks[@]}} ${itoks[@]}; do
133 rtoks[${#rtoks[@]}]="0x$r"
134 done
135 _RET=$(printf "%02x:%02x:%02x:%02x:%02x:%02x" "${rtoks[@]}")
136}
137
138make_nics_Usage() {
139 cat <<EOF
140Usage: ${0##*/} tap-control make-nics [options] bridge [bridge [..]]
141
142 make a tap device on each of bridges requested
143 outputs: 'tapname:type' for each input, or 'skip' if nothing needed.
144
145 type is one of 'brctl' or 'ovs'
146EOF
147}
148
149make_nics() {
150 # takes input of list of bridges to create a tap device on
151 # and echos either 'skip' or
152 # <tapname>:<type> for each tap created
153 # type is one of "ovs" or "brctl"
154 local short_opts="v"
155 local long_opts="--verbose"
156 local getopt_out=""
157 getopt_out=$(getopt --name "${0##*/} make-nics" \
158 --options "${short_opts}" --long "${long_opts}" -- "$@") &&
159 eval set -- "${getopt_out}" || { make_nics_Usage 1>&2; return 1; }
160
161 local cur="" next=""
162 while [ $# -ne 0 ]; do
163 cur=${1}; next=${2};
164 case "$cur" in
165 -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
166 --) shift; break;;
167 esac
168 shift;
169 done
170
171 [ $# -ne 0 ] || {
172 make_nics_Usage 1>&2; error "must give bridge";
173 return 1;
174 }
175
176 local owner="" ovsbrs="" tap="" tapnum="0" brtype="" bridge=""
177 [ "$(id -u)" = "0" ] || { error "must be root for make-nics"; return 1; }
178 owner="${SUDO_USER:-root}"
179 ovsbrs=""
180 if command -v ovs-vsctl >/dev/null 2>&1; then
181 out=$(ovs-vsctl list-br)
182 out=$(echo "$out" | sed "s/\n/,/")
183 ovsbrs=",$out,"
184 fi
185 for bridge in "$@"; do
186 [ "$bridge" = "user" ] && echo skip && continue
187 [ "${ovsbrs#*,${bridge},}" != "$ovsbrs" ] &&
188 btype="ovs" || btype="brctl"
189 tapnum=0;
190 while [ -e /sys/class/net/tapvm$tapnum ]; do tapnum=$(($tapnum+1)); done
191 tap="tapvm$tapnum"
192 debug 1 "creating $tap:$btype on $bridge" 1>&2
193 ip tuntap add mode tap user "$owner" "$tap" ||
194 { error "failed to create tap '$tap' for '$owner'"; return 1; }
195 ip link set "$tap" up 1>&2 || {
196 error "failed to bring up $tap";
197 ip tuntap del mode tap "$tap";
198 return 1;
199 }
200 if [ "$btype" = "ovs" ]; then
201 ovs-vsctl add-port "$bridge" "$tap" 1>&2 || {
202 error "failed: ovs-vsctl add-port $bridge $tap";
203 ovs-vsctl del-port "$bridge" "$tap"
204 return 1;
205 }
206 else
207 ip link set "$tap" master "$bridge" 1>&2 || {
208 error "failed to add tap '$tap' to '$bridge'"
209 ip tuntap del mode tap "$tap";
210 return 1
211 }
212 fi
213 echo "$tap:$btype"
214 done
215}
216
217ovs_cleanup() {
218 [ "$(id -u)" = "0" ] ||
219 { error "must be root for ovs-cleanup"; return 1; }
220 local item="" errors=0
221 # TODO: if get owner (SUDO_USERNAME) and if that isn't
222 # the owner, then do not delete.
223 for item in "$@"; do
224 name=${item#*:}
225 bridge=${item%:*}
226 ovs-vsctl del-port "$bridge" "$name" || errors=$((errors+1))
227 done
228 return $errors
229}
230
231quote_cmd() {
232 local quote='"' x="" vline=""
233 for x in "$@"; do
234 if [ "${x#* }" != "${x}" ]; then
235 if [ "${x#*$quote}" = "${x}" ]; then
236 x="\"$x\""
237 else
238 x="'$x'"
239 fi
240 fi
241 vline="${vline} $x"
242 done
243 echo "$vline"
244}
245
246get_bios_opts() {
247 # get_bios_opts(bios, uefi, nvram)
248 # bios is a explicit bios to boot.
249 # uefi is boolean indicating uefi
250 # nvram is optional and indicates that ovmf vars should be copied
251 # to that file if it does not exist. if it exists, use it.
252 local bios="$1" uefi="${2:-false}" nvram="$3"
253 local ovmf_dir="/usr/share/OVMF"
254 local bios_opts="" pflash_common="if=pflash,format=raw"
255 unset _RET
256 _RET=( )
257 if [ -n "$bios" ]; then
258 _RET=( -drive "${pflash_common},file=$bios" )
259 return 0
260 elif ! $uefi; then
261 return 0
262 fi
263
264 # ovmf in older releases (14.04) shipped only a single file
265 # /usr/share/ovmf/OVMF.fd
266 # newer ovmf ships split files
267 # /usr/share/OVMF/OVMF_CODE.fd
268 # /usr/share/OVMF/OVMF_VARS.fd
269 # with single file, pass only one file and read-write
270 # with split, pass code as readonly and vars as read-write
271 local joined="/usr/share/ovmf/OVMF.fd"
272 local code="/usr/share/OVMF/OVMF_CODE.fd"
273 local vars="/usr/share/OVMF/OVMF_VARS.fd"
274 local split="" nvram_src=""
275 if [ -e "$code" -o -e "$vars" ]; then
276 split=true
277 nvram_src="$vars"
278 elif [ -e "$joined" ]; then
279 split=false
280 nvram_src="$joined"
281 elif [ -n "$nvram" -a -e "$nvram" ]; then
282 error "WARN: nvram given, but did not find expected ovmf files."
283 error " assuming this is code and vars (OVMF.fd)"
284 split=false
285 else
286 error "uefi support requires ovmf bios: apt-get install -qy ovmf"
287 return 1
288 fi
289
290 if [ -n "$nvram" ]; then
291 if [ ! -f "$nvram" ]; then
292 cp "$nvram_src" "$nvram" ||
293 { error "failed copy $nvram_src to $nvram"; return 1; }
294 debug 1 "copied $nvram_src to $nvram"
295 fi
296 else
297 debug 1 "uefi without --uefi-nvram storage." \
298 "nvram settings likely will not persist."
299 nvram="${nvram_src}"
300 fi
301
302 if [ ! -w "$nvram" ]; then
303 debug 1 "nvram file ${nvram} is readonly"
304 nvram_ro="readonly"
305 fi
306
307 if $split; then
308 # to ensure bootability firmware must be first, then variables
309 _RET=( -drive "${pflash_common},file=$code,readonly" )
310 fi
311 _RET=( "${_RET[@]}"
312 -drive "${pflash_common},file=$nvram${nvram_ro:+,${nvram_ro}}" )
313}
314
315main() {
316 local short_opts="hd:n:v"
317 local long_opts="bios:,help,dowait,disk:,dry-run,kvm:,no-dowait,netdev:,uefi,uefi-nvram:,verbose"
318 local getopt_out=""
319 getopt_out=$(getopt --name "${0##*/}" \
320 --options "${short_opts}" --long "${long_opts}" -- "$@") &&
321 eval set -- "${getopt_out}" || { bad_Usage; return 1; }
322
323 local bridge="$DEF_BRIDGE" oifs="$IFS"
324 local netdevs="" need_tap="" ret="" p="" i="" pt="" cur="" conn=""
325 local kvm="" kvmcmd="" archopts=""
326 local def_disk_driver=${DEF_DISK_DRIVER:-"virtio-blk"}
327 local def_netmodel=${DEF_NETMODEL:-"virtio-net-pci"}
328 local bios="" uefi=false uefi_nvram=""
329
330 archopts=( )
331 kvmcmd=( )
332 netdevs=( )
333 addargs=( )
334 diskdevs=( )
335 diskargs=( )
336
337 # dowait: run qemu-system with a '&' and then 'wait' on the pid.
338 # the reason to do this or not do this has to do with interactivity
339 # if detached with &, then user input will not go to xkvm.
340 # if *not* detached, then signal handling is blocked until
341 # the foreground subprocess returns. which means we can't handle
342 # a sigterm and kill the qemu-system process.
343 # We default to dowait=false if input and output are a terminal
344 local dowait=""
345 [ -t 0 -a -t 1 ] && dowait=false || dowait=true
346 while [ $# -ne 0 ]; do
347 cur=${1}; next=${2};
348 case "$cur" in
349 -h|--help) Usage; exit 0;;
350 -d|--disk)
351 diskdevs[${#diskdevs[@]}]="$next"; shift;;
352 --dry-run) DRY_RUN=true;;
353 --kvm) kvm="$next"; shift;;
354 -n|--netdev)
355 netdevs[${#netdevs[@]}]=$next; shift;;
356 -v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
357 --dowait) dowait=true;;
358 --no-dowait) dowait=false;;
359 --bios) bios="$next"; shift;;
360 --uefi) uefi=true;;
361 --uefi-nvram) uefi=true; uefi_nvram="$next"; shift;;
362 --) shift; break;;
363 esac
364 shift;
365 done
366
367 [ ${#netdevs[@]} -eq 0 ] && netdevs=( "${DEF_BRIDGE}" )
368 pt=( "$@" )
369
370 local kvm_pkg="" virtio_scsi_bus="virtio-scsi-pci"
371 [ -n "$kvm" ] && kvm_pkg="none"
372 case $(uname -m) in
373 i?86)
374 [ -n "$kvm" ] ||
375 { kvm="qemu-system-i386"; kvm_pkg="qemu-system-x86"; }
376 ;;
377 x86_64)
378 [ -n "$kvm" ] ||
379 { kvm="qemu-system-x86_64"; kvm_pkg="qemu-system-x86"; }
380 ;;
381 s390x)
382 [ -n "$kvm" ] ||
383 { kvm="qemu-system-s390x"; kvm_pkg="qemu-system-misc"; }
384 def_netmodel=${DEF_NETMODEL:-"virtio-net-ccw"}
385 virtio_scsi_bus="virtio-scsi-ccw"
386 ;;
387 ppc64*)
388 [ -n "$kvm" ] ||
389 { kvm="qemu-system-ppc64"; kvm_pkg="qemu-system-ppc"; }
390 def_netmodel="virtio-net-pci"
391 # virtio seems functional on in 14.10, but might want scsi here
392 #def_diskif="scsi"
393 archopts=( "${archopts[@]}" -machine pseries,usb=off )
394 archopts=( "${archopts[@]}" -device spapr-vscsi )
395 ;;
396 *) kvm=qemu-system-$(uname -m);;
397 esac
398 KVM="$kvm"
399 kvmcmd=( $kvm -enable-kvm )
400
401 local bios_opts=""
402 if [ -n "$bios" ] && $uefi; then
403 error "--uefi (or --uefi-nvram) is incompatible with --bios"
404 return 1
405 fi
406 get_bios_opts "$bios" "$uefi" "$uefi_nvram" ||
407 { error "failed to get bios opts"; return 1; }
408 bios_opts=( "${_RET[@]}" )
409
410 local out="" fmt="" bus="" unit="" index="" serial="" driver="" devopts=""
411 local busorindex="" driveopts="" cur="" val="" file=""
412 for((i=0;i<${#diskdevs[@]};i++)); do
413 cur=${diskdevs[$i]}
414 IFS=","; set -- $cur; IFS="$oifs"
415 driver=""
416 id=$(printf "disk%02d" "$i")
417 file=""
418 fmt=""
419 bus=""
420 unit=""
421 index=""
422 serial=""
423 for tok in "$@"; do
424 [ "${tok#*=}" = "${tok}" -a -f "${tok}" -a -z "$file" ] && file="$tok"
425 val=${tok#*=}
426 case "$tok" in
427 driver=*) driver=$val;;
428 if=virtio) driver=virtio-blk;;
429 if=scsi) driver=scsi-hd;;
430 if=pflash) driver=;;
431 if=sd|if=mtd|floppy) fail "do not know what to do with $tok on $cur";;
432 id=*) id=$val;;
433 file=*) file=$val;;
434 fmt=*|format=*) fmt=$val;;
435 serial=*) serial=$val;;
436 bus=*) bus=$val;;
437 unit=*) unit=$val;;
438 index=*) index=$val;;
439 esac
440 done
441 [ -z "$file" ] && fail "did not read a file from $cur"
442 if [ -f "$file" -a -z "$fmt" ]; then
443 out=$(LANG=C qemu-img info "$file") &&
444 fmt=$(echo "$out" | awk '$0 ~ /^file format:/ { print $3 }') ||
445 { error "failed to determine format of $file"; return 1; }
446 else
447 fmt=raw
448 fi
449 if [ -z "$driver" ]; then
450 driver="$def_disk_driver"
451 fi
452 if [ -z "$serial" ]; then
453 serial="${file##*/}"
454 fi
455
456 # make sure we add either bus= or index=
457 if [ -n "$bus" -o "$unit" ] && [ -n "$index" ]; then
458 fail "bus and index cant be specified together: $cur"
459 elif [ -z "$bus" -a -z "$unit" -a -z "$index" ]; then
460 index=$i
461 elif [ -n "$bus" -a -z "$unit" ]; then
462 unit=$i
463 fi
464
465 busorindex="${bus:+bus=$bus,unit=$unit}${index:+index=${index}}"
466 diskopts="file=${file},id=$id,if=none,format=$fmt,$busorindex"
467 devopts="$driver,drive=$id${serial:+,serial=${serial}}"
468 for tok in "$@"; do
469 case "$tok" in
470 id=*|if=*|driver=*|$file|file=*) continue;;
471 fmt=*|format=*) continue;;
472 serial=*|bus=*|unit=*|index=*) continue;;
473 esac
474 isdevopt "$driver" "$tok" && devopts="${devopts},$tok" ||
475 diskopts="${diskopts},${tok}"
476 done
477
478 diskargs=( "${diskargs[@]}" -drive "$diskopts" -device "$devopts" )
479 done
480
481 local mnics_vflag=""
482 for((i=0;i<${VERBOSITY}-1;i++)); do mnics_vflag="${mnics_vflag}v"; done
483 [ -n "$mnics_vflag" ] && mnics_vflag="-${mnics_vflag}"
484
485 # now go through and split out options
486 # -device virtio-net-pci,netdev=virtnet0,mac=52:54:31:15:63:02
487 # -netdev type=tap,id=virtnet0,vhost=on,script=/etc/kvm/kvm-ifup.br0,downscript=no
488 local netopts="" devopts="" id="" need_taps=0 model=""
489 local device_args netdev_args
490 device_args=( )
491 netdev_args=( )
492 connections=( )
493 for((i=0;i<${#netdevs[@]};i++)); do
494 id=$(printf "net%02d" "$i")
495 netopts="";
496 devopts=""
497 # mac=auto is 'unspecified' (let qemu assign one)
498 mac="auto"
499 #vhost="off"
500
501 IFS=","; set -- ${netdevs[$i]}; IFS="$oifs"
502 bridge=$1; shift;
503 if [ "$bridge" = "user" ]; then
504 netopts="type=user"
505 ntype="user"
506 connections[$i]="user"
507 else
508 need_taps=1
509 ntype="tap"
510 netopts="type=tap"
511 connections[$i]="$bridge"
512 fi
513 netopts="${netopts},id=$id"
514 [ "$ntype" = "tap" ] && netopts="${netopts},script=no,downscript=no"
515
516 model="${def_netmodel}"
517 for tok in "$@"; do
518 [ "${tok#model=}" = "${tok}" ] && continue
519 case "${tok#model=}" in
520 virtio) model=virtio-net-pci;;
521 *) model=${tok#model=};;
522 esac
523 done
524
525 for tok in "$@"; do
526 case "$tok" in
527 mac=*) mac="${tok#mac=}"; continue;;
528 macaddr=*) mac=${tok#macaddr=}; continue;;
529 model=*) continue;;
530 esac
531
532 isdevopt "$model" "$tok" && devopts="${devopts},$tok" ||
533 netopts="${netopts},${tok}"
534 done
535 devopts=${devopts#,}
536 netopts=${netopts#,}
537
538 if [ "$mac" != "auto" ]; then
539 [ "$mac" = "random" ] && randmac && mac="$_RET"
540 padmac "$mac" "$i"
541 devopts="${devopts:+${devopts},}mac=$_RET"
542 fi
543 devopts="$model,netdev=$id${devopts:+,${devopts}}"
544 #netopts="${netopts},vhost=${vhost}"
545
546 device_args[$i]="$devopts"
547 netdev_args[$i]="$netopts"
548 done
549
550 trap cleanup EXIT
551
552 reqs=( "$kvm" )
553 pkgs=( "$kvm_pkg" )
554 for((i=0;i<${#reqs[@]};i++)); do
555 req=${reqs[$i]}
556 pkg=${pkgs[$i]}
557 [ "$pkg" = "none" ] && continue
558 command -v "$req" >/dev/null || {
559 missing="${missing:+${missing} }${req}"
560 missing_pkgs="${missing_pkgs:+${missing_pkgs} }$pkg"
561 }
562 done
563 if [ -n "$missing" ]; then
564 local reply cmd=""
565 cmd=( sudo apt-get --quiet install ${missing_pkgs} )
566 error "missing prereqs: $missing";
567 error "install them now with the following?: ${cmd[*]}"
568 read reply && [ "$reply" = "y" -o "$reply" = "Y" ] ||
569 { error "run: apt-get install ${missing_pkgs}"; return 1; }
570 "${cmd[@]}" || { error "failed to install packages"; return 1; }
571 fi
572
573 if [ $need_taps -ne 0 ]; then
574 local missing="" missing_pkgs="" reqs="" req="" pkgs="" pkg=""
575 for i in "${connections[@]}"; do
576 [ "$i" = "user" -o -e "/sys/class/net/$i" ] ||
577 missing="${missing} $i"
578 done
579 [ -z "$missing" ] || {
580 error "cannot create connection on: ${missing# }."
581 error "bridges do not exist.";
582 return 1;
583 }
584 error "creating tap devices: ${connections[*]}"
585 if $DRY_RUN; then
586 error "sudo $0 tap-control make-nics" \
587 $mnics_vflag "${connections[@]}"
588 taps=""
589 for((i=0;i<${#connections[@]};i++)); do
590 if [ "${connections[$i]}" = "user" ]; then
591 taps="${taps} skip"
592 else
593 taps="${taps} dryruntap$i:brctl"
594 fi
595 done
596 else
597 taps=$(sudo "$0" tap-control make-nics \
598 ${mnics_vflag} "${connections[@]}") ||
599 { error "$failed to make-nics ${connections[*]}"; return 1; }
600 fi
601 TAPDEVS=( ${taps} )
602 for((i=0;i<${#TAPDEVS[@]};i++)); do
603 cur=${TAPDEVS[$i]}
604 [ "${cur#*:}" = "ovs" ] || continue
605 conn=${connections[$i]}
606 OVS_CLEANUP[${#OVS_CLEANUP[@]}]="${conn}:${cur%:*}"
607 done
608
609 debug 2 "tapdevs='${TAPDEVS[@]}'"
610 [ ${#OVS_CLEANUP[@]} -eq 0 ] || error "OVS_CLEANUP='${OVS_CLEANUP[*]}'"
611
612 for((i=0;i<${#TAPDEVS[@]};i++)); do
613 cur=${TAPDEVS[$i]}
614 [ "$cur" = "skip" ] && continue
615 netdev_args[$i]="${netdev_args[$i]},ifname=${cur%:*}";
616 done
617 fi
618
619 netargs=()
620 for((i=0;i<${#device_args[@]};i++)); do
621 netargs=( "${netargs[@]}" -device "${device_args[$i]}"
622 -netdev "${netdev_args[$i]}")
623 done
624
625 local bus_devices
626 bus_devices=( -device "$virtio_scsi_bus,id=virtio-scsi-xkvm" )
627 cmd=( "${kvmcmd[@]}" "${archopts[@]}"
628 "${bios_opts[@]}"
629 "${bus_devices[@]}"
630 "${netargs[@]}"
631 "${diskargs[@]}" "${pt[@]}" )
632 local pcmd=$(quote_cmd "${cmd[@]}")
633 error "$pcmd"
634 ${DRY_RUN} && return 0
635
636 if $dowait; then
637 "${cmd[@]}" &
638 KVM_PID=$!
639 debug 1 "kvm pid=$KVM_PID. my pid=$$"
640 wait
641 ret=$?
642 KVM_PID=""
643 else
644 "${cmd[@]}"
645 ret=$?
646 fi
647 return $ret
648}
649
650
651if [ "$1" = "tap-control" ]; then
652 shift
653 mode=$1
654 shift || fail "must give mode to tap-control"
655 case "$mode" in
656 make-nics) make_nics "$@";;
657 ovs-cleanup) ovs_cleanup "$@";;
658 *) fail "tap mode must be either make-nics or ovs-cleanup";;
659 esac
660else
661 main "$@"
662fi
663
664# vi: ts=4 expandtab

Subscribers

People subscribed via source and target branches