[PATCH] tools: fix libvirt-guests.sh text assignments

Christian Ehrhardt christian.ehrhardt at canonical.com
Thu Aug 20 05:42:28 UTC 2020


On Wed, Aug 19, 2020 at 12:15 PM Christian Ehrhardt
<christian.ehrhardt at canonical.com> wrote:
>
> In libvirt 6.6 stopping guests with libvirt-guests.sh is broken.
> As soon as there is more than one guest one can see
> `systemctl stop libvirt-guests` faiing and in the log we see:
>   libvirt-guests.sh[2455]: Running guests on default URI:
>   libvirt-guests.sh[2457]: /usr/lib/libvirt/libvirt-guests.sh: 120:
>       local: 2a49cb0f-1ff8-44b5-a61d-806b9e52dae2: bad variable name
>   libvirt-guests.sh[2462]: no running guests.
>
> That is due do mutliple guests becoming a list of UUIDs. Without
> recognizing this as one single string the assignment breaks when using 'local'
> (which was recently added in 6.3.0). This is because local is defined as
>   local [option] [name[=value] ... | - ]
> which makes the shell trying handle the further part of the string as
> variable names. In the error above that string isn't a valid variable
> name triggering the issue that is seen.
>
> To resolve that 'textify' all assignments that are strings or potentially
> can become such lists (even if they are not using the local qualifier).

Just to illustrate the problem, this never was great and could cause
warnings/errors,
but amplified due to the 'local' it makes the script break now.

$ cat test.sh
#!/bin/sh

foo () {
    f=2a49cb0f-1ff8-44b5-a61d-806b9e52dae2 2a49cb0f-1ff8-44b5-a61d-806b9e52dae3
    echo f
}

bar () {
    local b=2a49cb0f-1ff8-44b5-a61d-806b9e52dae2
2a49cb0f-1ff8-44b5-a61d-806b9e52dae3
    echo b
}

foo
bar
echo end of script


$ ./test.sh
./test.sh: 4: 2a49cb0f-1ff8-44b5-a61d-806b9e52dae3: not found
f
./test.sh: 9: local: 2a49cb0f-1ff8-44b5-a61d-806b9e52dae3: bad variable name


> Fixes: 08071ec0 "tools: variables clean-up in libvirt-guests script"
>
> Signed-off-by: Christian Ehrhardt <christian.ehrhardt at canonical.com>
> ---
>  tools/libvirt-guests.sh.in | 136 ++++++++++++++++++-------------------
>  1 file changed, 68 insertions(+), 68 deletions(-)
>
> diff --git a/tools/libvirt-guests.sh.in b/tools/libvirt-guests.sh.in
> index 534c4d5e0f..d69df908d2 100644
> --- a/tools/libvirt-guests.sh.in
> +++ b/tools/libvirt-guests.sh.in
> @@ -30,9 +30,9 @@ test ! -r "$sysconfdir"/rc.d/init.d/functions ||
>
>  export TEXTDOMAIN="@PACKAGE@" TEXTDOMAINDIR="@localedir@"
>
> -URIS=default
> -ON_BOOT=start
> -ON_SHUTDOWN=suspend
> +URIS="default"
> +ON_BOOT="start"
> +ON_SHUTDOWN="suspend"
>  SHUTDOWN_TIMEOUT=300
>  PARALLEL_SHUTDOWN=0
>  START_DELAY=0
> @@ -65,7 +65,7 @@ retval() {
>  # If URI is "default" virsh is called without the "-c" argument
>  # (using libvirt's default connection)
>  run_virsh() {
> -    local uri=$1
> +    local uri="$1"
>      shift
>
>      if [ "x$uri" = xdefault ]; then
> @@ -86,7 +86,7 @@ run_virsh_c() {
>  # check if URI is reachable
>  test_connect()
>  {
> -    local uri=$1
> +    local uri="$1"
>
>      if run_virsh "$uri" connect 2>/dev/null; then
>          return 0;
> @@ -103,9 +103,9 @@ test_connect()
>  # --transient: list only transient guests
>  # [none]: list both persistent and transient guests
>  list_guests() {
> -    local uri=$1
> -    local persistent=$2
> -    local list=$(run_virsh_c "$uri" list --uuid $persistent)
> +    local uri="$1"
> +    local persistent="$2"
> +    local list="$(run_virsh_c "$uri" list --uuid $persistent)"
>
>      if [ $? -ne 0 ]; then
>          RETVAL=1
> @@ -118,8 +118,8 @@ list_guests() {
>  # guest_name URI UUID
>  # return name of guest UUID on URI
>  guest_name() {
> -    local uri=$1
> -    local uuid=$2
> +    local uri="$1"
> +    local uuid="$2"
>
>      run_virsh "$uri" domname "$uuid" 2>/dev/null
>  }
> @@ -128,17 +128,17 @@ guest_name() {
>  # check if guest UUID on URI is running
>  # Result is returned by variable "guest_running"
>  guest_is_on() {
> -    local uri=$1
> -    local uuid=$2
> -    local id=$(run_virsh "$uri" domid "$uuid")
> +    local uri="$1"
> +    local uuid="$2"
> +    local id="$(run_virsh "$uri" domid "$uuid")"
>
> -    guest_running=false
> +    guest_running="false"
>      if [ $? -ne 0 ]; then
>          RETVAL=1
>          return 1
>      fi
>
> -    [ -n "$id" ] && [ "x$id" != x- ] && guest_running=true
> +    [ -n "$id" ] && [ "x$id" != x- ] && guest_running="true"
>      return 0
>  }
>
> @@ -151,9 +151,9 @@ started() {
>  # start
>  # Start or resume the guests
>  start() {
> -    local isfirst=true
> +    local isfirst="true"
>      local bypass=
> -    local sync_time=false
> +    local sync_time="false"
>      local uri=
>      local list=
>
> @@ -167,10 +167,10 @@ start() {
>          return 0
>      fi
>
> -    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
> -    test "x$SYNC_TIME" = x0 || sync_time=true
> +    test "x$BYPASS_CACHE" = x0 || bypass="--bypass-cache"
> +    test "x$SYNC_TIME" = x0 || sync_time="true"
>      while read uri list; do
> -        local configured=false
> +        local configured="false"
>          local confuri=
>          local guest=
>
> @@ -178,7 +178,7 @@ start() {
>          for confuri in $URIS; do
>              set +f
>              if [ "x$confuri" = "x$uri" ]; then
> -                configured=true
> +                configured="true"
>                  break
>              fi
>          done
> @@ -192,14 +192,14 @@ start() {
>
>          eval_gettext "Resuming guests on \$uri URI..."; echo
>          for guest in $list; do
> -            local name=$(guest_name "$uri" "$guest")
> +            local name="$(guest_name "$uri" "$guest")"
>              eval_gettext "Resuming guest \$name: "
>              if guest_is_on "$uri" "$guest"; then
>                  if "$guest_running"; then
>                      gettext "already active"; echo
>                  else
>                      if "$isfirst"; then
> -                        isfirst=false
> +                        isfirst="false"
>                      else
>                          sleep $START_DELAY
>                      fi
> @@ -223,25 +223,25 @@ start() {
>  # was saved.
>  suspend_guest()
>  {
> -    local uri=$1
> -    local guest=$2
> -    local name=$(guest_name "$uri" "$guest")
> -    local label=$(eval_gettext "Suspending \$name: ")
> +    local uri="$1"
> +    local guest="$2"
> +    local name="$(guest_name "$uri" "$guest")"
> +    local label="$(eval_gettext "Suspending \$name: ")"
>      local bypass=
>      local slept=0
>
> -    test "x$BYPASS_CACHE" = x0 || bypass=--bypass-cache
> +    test "x$BYPASS_CACHE" = x0 || bypass="--bypass-cache"
>      printf '%s...\n' "$label"
>      run_virsh "$uri" managedsave $bypass "$guest" >/dev/null &
> -    local virsh_pid=$!
> +    local virsh_pid="$!"
>      while true; do
>          sleep 1
>          kill -0 "$virsh_pid" >/dev/null 2>&1 || break
>
>          slept=$(($slept + 1))
>          if [ $(($slept % 5)) -eq 0 ]; then
> -            local progress=$(run_virsh_c "$uri" domjobinfo "$guest" 2>/dev/null | \
> -                    awk '/^Data processed:/{print $3, $4}')
> +            local progress="$(run_virsh_c "$uri" domjobinfo "$guest" 2>/dev/null | \
> +                    awk '/^Data processed:/{print $3, $4}')"
>              if [ -n "$progress" ]; then
>                  printf '%s%s\n' "$label" "$progress"
>              else
> @@ -257,11 +257,11 @@ suspend_guest()
>  # was successfully shutdown or the timeout defined by $SHUTDOWN_TIMEOUT expired.
>  shutdown_guest()
>  {
> -    local uri=$1
> -    local guest=$2
> -    local name=$(guest_name "$uri" "$guest")
> -    local timeout=$SHUTDOWN_TIMEOUT
> -    local check_timeout=false
> +    local uri="$1"
> +    local guest="$2"
> +    local name="$(guest_name "$uri" "$guest")"
> +    local timeout="$SHUTDOWN_TIMEOUT"
> +    local check_timeout="false"
>      local format=
>      local slept=
>
> @@ -270,11 +270,11 @@ shutdown_guest()
>      retval run_virsh "$uri" shutdown "$guest" >/dev/null || return
>
>      if [ $timeout -gt 0 ]; then
> -        check_timeout=true
> -        format=$(eval_gettext "Waiting for guest %s to shut down, %d seconds left\n")
> +        check_timeout="true"
> +        format="$(eval_gettext "Waiting for guest %s to shut down, %d seconds left\n")"
>      else
>          slept=0
> -        format=$(eval_gettext "Waiting for guest %s to shut down\n")
> +        format="$(eval_gettext "Waiting for guest %s to shut down\n")"
>      fi
>      while ! $check_timeout || [ "$timeout" -gt 0 ]; do
>          sleep 1
> @@ -309,9 +309,9 @@ shutdown_guest()
>  # was issued to libvirt to allow parallel shutdown.
>  shutdown_guest_async()
>  {
> -    local uri=$1
> -    local guest=$2
> -    local name=$(guest_name "$uri" "$guest")
> +    local uri="$1"
> +    local guest="$2"
> +    local name="$(guest_name "$uri" "$guest")"
>
>      eval_gettext "Starting shutdown on guest: \$name"
>      echo
> @@ -332,8 +332,8 @@ guest_count()
>  # Result is returned in "guests_shutting_down"
>  check_guests_shutdown()
>  {
> -    local uri=$1
> -    local guests_to_check=$2
> +    local uri="$1"
> +    local guests_to_check="$2"
>      local guest=
>
>      guests_shutting_down=
> @@ -354,9 +354,9 @@ check_guests_shutdown()
>  # a shutdown complete notice for guests that have finished
>  print_guests_shutdown()
>  {
> -    local uri=$1
> -    local before=$2
> -    local after=$3
> +    local uri="$1"
> +    local before="$2"
> +    local after="$3"
>      local guest=
>
>      for guest in $before; do
> @@ -364,7 +364,7 @@ print_guests_shutdown()
>              *" $guest "*) continue;;
>          esac
>
> -        local name=$(guest_name "$uri" "$guest")
> +        local name="$(guest_name "$uri" "$guest")"
>          if [ -n "$name" ]; then
>              eval_gettext "Shutdown of guest \$name complete."
>              echo
> @@ -376,28 +376,28 @@ print_guests_shutdown()
>  # Shutdown guests GUESTS on machine URI in parallel
>  shutdown_guests_parallel()
>  {
> -    local uri=$1
> -    local guests=$2
> +    local uri="$1"
> +    local guests="$2"
>      local on_shutdown=
> -    local check_timeout=false
> -    local timeout=$SHUTDOWN_TIMEOUT
> +    local check_timeout="false"
> +    local timeout="$SHUTDOWN_TIMEOUT"
>      local slept=
>      local format=
>
>      if [ $timeout -gt 0 ]; then
> -        check_timeout=true
> -        format=$(eval_gettext "Waiting for %d guests to shut down, %d seconds left\n")
> +        check_timeout="true"
> +        format="$(eval_gettext "Waiting for %d guests to shut down, %d seconds left\n")"
>      else
>          slept=0
> -        format=$(eval_gettext "Waiting for %d guests to shut down\n")
> +        format="$(eval_gettext "Waiting for %d guests to shut down\n")"
>      fi
>      while [ -n "$on_shutdown" ] || [ -n "$guests" ]; do
>          while [ -n "$guests" ] &&
>                [ $(guest_count "$on_shutdown") -lt "$PARALLEL_SHUTDOWN" ]; do
>              set -- $guests
> -            local guest=$1
> +            local guest="$1"
>              shift
> -            guests=$*
> +            guests="$*"
>              if [ -z "$(echo $on_shutdown | grep $guest)" ] &&
>                 [ -n "$(guest_name "$uri" "$guest")" ]; then
>                  shutdown_guest_async "$uri" "$guest"
> @@ -428,7 +428,7 @@ shutdown_guests_parallel()
>              fi
>          fi
>
> -        local on_shutdown_prev=$on_shutdown
> +        local on_shutdown_prev="$on_shutdown"
>          check_guests_shutdown "$uri" "$on_shutdown"
>          on_shutdown="$guests_shutting_down"
>          print_guests_shutdown "$uri" "$on_shutdown_prev" "$on_shutdown"
> @@ -438,14 +438,14 @@ shutdown_guests_parallel()
>  # stop
>  # Shutdown or save guests on the configured uris
>  stop() {
> -    local suspending=true
> +    local suspending="true"
>      local uri=
>
>      # last stop was not followed by start
>      [ -f "$LISTFILE" ] && return 0
>
>      if [ "x$ON_SHUTDOWN" = xshutdown ]; then
> -        suspending=false
> +        suspending="false"
>          if [ $SHUTDOWN_TIMEOUT -lt 0 ]; then
>              gettext "SHUTDOWN_TIMEOUT must be equal or greater than 0"
>              echo
> @@ -463,13 +463,13 @@ stop() {
>
>          eval_gettext "Running guests on \$uri URI: "
>
> -        local list=$(list_guests "$uri")
> +        local list="$(list_guests "$uri")"
>          if [ $? -eq 0 ]; then
>              local empty=true
>              for uuid in $list; do
>                  "$empty" || printf ", "
>                  printf %s "$(guest_name "$uri" "$uuid")"
> -                empty=false
> +                empty="false"
>              done
>
>              if "$empty"; then
> @@ -479,15 +479,15 @@ stop() {
>          fi
>
>          if "$suspending"; then
> -            local transient=$(list_guests "$uri" "--transient")
> +            local transient="$(list_guests "$uri" "--transient")"
>              if [ $? -eq 0 ]; then
> -                local empty=true
> +                local empty="true"
>                  local uuid=
>
>                  for uuid in $transient; do
>                      if "$empty"; then
>                          eval_gettext "Not suspending transient guests on URI: \$uri: "
> -                        empty=false
> +                        empty="false"
>                      else
>                          printf ", "
>                      fi
> @@ -495,7 +495,7 @@ stop() {
>                  done
>                  echo
>                  # reload domain list to contain only persistent guests
> -                list=$(list_guests "$uri" "--persistent")
> +                list="$(list_guests "$uri" "--persistent")"
>                  if [ $? -ne 0 ]; then
>                      eval_gettext "Failed to list persistent guests on \$uri"
>                      echo
> @@ -582,7 +582,7 @@ rh_status() {
>  # usage [val]
>  # Display usage string, then exit with VAL (defaults to 2).
>  usage() {
> -    local program_name=$0
> +    local program_name="$0"
>      eval_gettext "Usage: \$program_name {start|stop|status|restart|"\
>  "condrestart|try-restart|reload|force-reload|gueststatus|shutdown}"; echo
>      exit ${1-2}
> @@ -612,7 +612,7 @@ case "$1" in
>          rh_status
>          ;;
>      shutdown)
> -        ON_SHUTDOWN=shutdown
> +        ON_SHUTDOWN="shutdown"
>          stop
>          ;;
>      *)
> --
> 2.28.0
>


-- 
Christian Ehrhardt
Staff Engineer, Ubuntu Server
Canonical Ltd




More information about the libvir-list mailing list