~smoser/curtin/trunk.lp1716028-better-file-locking

« back to all changes in this revision

Viewing changes to tools/xkvm

  • Committer: Scott Moser
  • Date: 2017-09-12 02:47:05 UTC
  • Revision ID: smoser@ubuntu.com-20170912024705-yyh2fk4t08q0ap50
initial close commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
312
312
           -drive "${pflash_common},file=$nvram${nvram_ro:+,${nvram_ro}}" )
313
313
}
314
314
 
 
315
inargs() {
 
316
    # inargs(needle, [ haystack [ more [ haystack [ ... ] ] ] ]
 
317
    local needle="$1" i=""
 
318
    shift;
 
319
    for i in "$@"; do
 
320
        [ "$i" = "$needle" ] && return 0
 
321
    done
 
322
    return 1
 
323
}
 
324
 
 
325
is_drive_opt() {
 
326
    inargs "${1%%=*}" \
 
327
        addr aio bps bps_max bus cache copy-on-read cyls file format \
 
328
        group "if" index iops iops_max iops_size media serial snapshot \
 
329
        werror
 
330
}
 
331
 
 
332
add_file_equal() {
 
333
    # given a --drive= argument, if there is no 'file=' and
 
334
    # one of the tokens is a file, improve that to have 'file=<that>'
 
335
    local file="" i="" ret=""
 
336
    case ",$1" in
 
337
        *,file=*) _RET="$1"; return 0;;
 
338
    esac
 
339
    IFS=","; set -- $1; IFS="$oifs"
 
340
    for i in "$@"; do
 
341
        if [ "${i#*=}" = "$i" -a -f "$i" -a -z "$file" ]; then
 
342
            file="$i"
 
343
            ret="file=$file${ret:+,${ret}}"
 
344
        else
 
345
            ret="${ret:+${ret},}$i"
 
346
        fi
 
347
    done
 
348
    _RET="$ret"
 
349
}
 
350
 
 
351
get_drive_opts() {
 
352
    local i="" ret="" oifs=""
 
353
    IFS=","; set -- $1; IFS="$oifs"
 
354
    for i in "$@"; do
 
355
        is_drive_opt "$i" && ret="${ret:+$ret,}$i"
 
356
    done
 
357
    _RET=${ret#,}
 
358
}
 
359
 
 
360
get_device_opts() {
 
361
    local i="" ret="" oifs=""
 
362
    IFS=","; set -- $1; IFS="$oifs"
 
363
    for i in "$@"; do
 
364
        is_drive_opt "$i" || ret="${ret:+$ret,}$i"
 
365
    done
 
366
    _RET=${ret#,}
 
367
}
 
368
 
 
369
extract_opt() {
 
370
    local name="$1" i=""
 
371
    IFS=","; set -- $2; IFS="$oifs"
 
372
    for i in "$@"; do
 
373
        [ "${i%%=*}" = "$name" ] && _RET=${i#*=} && return 0
 
374
    done
 
375
    return 1
 
376
}
 
377
 
 
378
get_format() {
 
379
    local out="" fmt=""
 
380
    out=$(LANG=C qemu-img info "$1") &&
 
381
        fmt=$(echo "$out" | awk '$0 ~ /^file format:/ { print $3 }') &&
 
382
        [ -n "$fmt" ] || {
 
383
            error "failed to determine format of $file";
 
384
            return 1;
 
385
        }
 
386
    _RET="$fmt"
 
387
    return
 
388
}
 
389
 
 
390
args_from_disks() {
 
391
    # convert the '--disk' type argument into '-drive' and '-device'
 
392
    local disks="" drives="" devices="" disk="" ret="" arg="" i=0
 
393
    local drive_opts ffile="" driveid out="" fmt=""
 
394
    declare -A drives   # associative by id
 
395
    declare -A file2id
 
396
    disks=( "$@" )
 
397
    drives=( )
 
398
    devices=( )
 
399
    while [ $i -lt "${#disks[@]}" ] && arg=${disks[$i]} && i=$(($i+1)); do
 
400
 
 
401
        add_file_equal "$arg"
 
402
        arg="${_RET}"
 
403
        get_drive_opts "$arg"
 
404
        drive_opts="${_RET}"
 
405
        echo "drive_opts=\"${_RET}\""
 
406
 
 
407
        local other_drive_args="" other_id=""
 
408
        local  id="" file="" ffile="" fid=""
 
409
        if extract_opt file "$drive_opts"; then
 
410
            file=$_RET
 
411
            ffile=$file
 
412
            if [ -f "$file" ]; then
 
413
                ffile=$(readlink -f "$file") ||
 
414
                    fail "failed readlink -f $file"
 
415
            fi
 
416
        fi
 
417
        echo "file=$file ffile=$ffile"
 
418
 
 
419
        extract_opt id "$drive_opts" && id="$_RET"
 
420
        # id file 
 
421
        #  Y   Y  raise error
 
422
        #  Y   N  mention, use other
 
423
        #  N   Y  use other.
 
424
        if [ -n "$ffile" ]; then
 
425
            other_id=${file2id[$ffile]}
 
426
            if [ -n "$other_id" ]; then
 
427
                other_drive_opts=${drives[$other_id]}
 
428
            fi
 
429
        fi
 
430
        new_drive=false
 
431
 
 
432
        if [ -n "$other_id" -a "${other_id}" != "$id" -a -n "$id" ]; then
 
433
            error "file $file ($ffile) used by differing ids ($other_id, $id):"
 
434
            error "   $other_drive_opts"
 
435
            error "   $drive_opts"
 
436
            return 1
 
437
        fi
 
438
 
 
439
        if [ -n "$other_id" -a -z "$id" ]; then
 
440
            debug 1 "no id in '$drive_opts', and '$file' used before" \
 
441
                "with $other_drive_opts (id=$other_id). using that for id."
 
442
            id="$other_id"
 
443
            # would be good to compare drive opts and error if they
 
444
            # were meaningfully different.
 
445
            drive_opts="${other_drive_opts}"
 
446
 
 
447
            ## LP: #1716028
 
448
            #if ! extract_opt share-rw "$drive_opts"; then
 
449
            #    drive_opts="${drive_opts:+${drive_opts},}share-rw=on"
 
450
            #    drives[$id]=$drive_opts
 
451
            #fi
 
452
        else
 
453
            new_drive=true
 
454
        fi
 
455
 
 
456
        if [ -z "$id" ]; then
 
457
            id=$(printf "drive%02d" "$i")
 
458
            drive_opts="id=$id${drive_opts:+,${drive_opts}}"
 
459
        fi
 
460
 
 
461
        if $new_drive; then
 
462
            fmt=raw
 
463
            # support 'format' or 'fmt' (legacy)
 
464
            if [ -n "$file" ] && extract_opt fmt "$drive_opts"; then
 
465
                drive_opts=${drive_opts/${_RET}/format=${_RET#*=}/}
 
466
            fi
 
467
            if [ -n "$file" ] && ! extract_opt format "$drive_opts"; then
 
468
                get_format "$file" && fmt=${_RET} || {
 
469
                    error "failed to get format for $file."
 
470
                    return
 
471
                }
 
472
                drive_opts="${drive_opts},format=$fmt"
 
473
            fi
 
474
            drive_opts="${drive_opts:+${drive_opts},}if=none"
 
475
        fi
 
476
 
 
477
        get_device_opts "$arg"
 
478
        dev_opts="drive=${id}${_RET:+,${_RET}},share-rw=on"
 
479
 
 
480
        if ! extract_opt serial "$dev_opts"; then
 
481
            serial="sn-$id"
 
482
            dev_opts="${dev_opts},serial=sn-$id"
 
483
        fi
 
484
 
 
485
        # $def_disk_driver is inherited from scope
 
486
        if extract_opt "if" "$dev_opts"; then
 
487
            case "$_RET" in
 
488
                if=virtio) dev_opts="${dev_opts/${_RET}/if=virtio-blk}";;
 
489
                if=scsi) dev_opts="${dev_opts/${_RET}/if=scsi-hd}";;
 
490
                if=pflash) dev_opts="${dev_opts/${_RET}/if=}";;
 
491
            esac
 
492
        else
 
493
            dev_opts="${dev_opts:+${dev_opts},}driver=$def_disk_driver"
 
494
        fi
 
495
 
 
496
        # make sure there is a bus= or index=
 
497
        local bus="" unit="" index=""
 
498
        extract_opt bus "$dev_opts" && bus=$_RET
 
499
        extract_opt unit "$dev_opts" && unit=$_RET
 
500
        extract_opt index "$dev_opts" && unit=$_RET
 
501
        if [ -n "$bus" -o "$unit" ] && [ -n "$index" ]; then
 
502
            error "bus and index can't be specified together: $arg"
 
503
            return 1
 
504
        elif [ -z "$bus" -a -z "$unit" -a -z "$index" ]; then
 
505
            dev_opts="${dev_opts:+${dev_opts},}index=$i"
 
506
        elif [ -n "$bus" -a -z "$unit" ]; then
 
507
            dev_opts="${dev_opts:+${dev_opts},}unit=$i"
 
508
        fi
 
509
 
 
510
        if $new_drive; then
 
511
            debug 1 "new drive: $file id=$id ${drive_opts}"
 
512
            if [ -n "$ffile" ]; then
 
513
                file2id[$ffile]=$id
 
514
            fi
 
515
            drives[$id]="$drive_opts"
 
516
        fi
 
517
        
 
518
        devices[${#devices[@]}]="$dev_opts"
 
519
    done
 
520
    local ret=""
 
521
    unset _RET
 
522
 
 
523
    for i in "${!drives[@]}"; do
 
524
        _RET[${#_RET[@]}]="-drive"
 
525
        _RET[${#_RET[@]}]="${drives[$i]}"
 
526
        #_RET[${#_RET[@]}]="-blockdev"
 
527
        #t=${drives[$i]}
 
528
        #t=${t/id=/node-name=}
 
529
        #t=$t,driver=file
 
530
        #t=${t/file=/filename=}
 
531
        #_RET[${#_RET[@]}]="$t"
 
532
    done
 
533
    for i in "${devices[@]}"; do
 
534
        _RET[${#_RET[@]}]="-device"
 
535
        _RET[${#_RET[@]}]="$i"
 
536
    done
 
537
}
 
538
 
315
539
main() {
316
540
    local short_opts="hd:n:v"
317
541
    local long_opts="bios:,help,dowait,disk:,dry-run,kvm:,no-dowait,netdev:,uefi,uefi-nvram:,verbose"
407
631
        { error "failed to get bios opts"; return 1; }
408
632
    bios_opts=( "${_RET[@]}" )
409
633
 
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
 
634
    args_from_disks "${diskdevs[@]}"
 
635
    diskargs=( "${_RET[@]}" )
480
636
 
481
637
    local mnics_vflag=""
482
638
    for((i=0;i<${VERBOSITY}-1;i++)); do mnics_vflag="${mnics_vflag}v"; done