← Back to team overview

cloud-init-dev team mailing list archive

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

 


Diff comments:

> diff --git a/tools/xkvm b/tools/xkvm
> new file mode 100755
> index 0000000..a30ba91
> --- /dev/null
> +++ b/tools/xkvm
> @@ -0,0 +1,664 @@
> +#!/bin/bash
> +

Can you add a header comment here explaning what this is and how it's intended for use?

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


-- 
https://code.launchpad.net/~powersj/cloud-init/+git/cloud-init/+merge/330536
Your team cloud-init commiters is requested to review the proposed merge of ~powersj/cloud-init:add-xkvm into cloud-init:master.


References