[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-users] Xen 4.2.2 /etc/init.d/xendomains save and restore of domains does not work



I have created a created a solution that save and restore domains with xl in sxp and json
format. It is only tested on my System:
    Debian squeeze
    Kernel 3.9.8 von kernel.org
    Xen 4.2.2

As the base for my working I took xendomains
( http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=543a2657182dbb9237d1feeb1d3193096ab2cb2d )

My System has 5 domains started by symlinks in /etc/xen/auto/*
the domain config file names differ from the domain name

domain fwgw     /etc/xen/auto/00_fwgw   ->   /etc/xen/fwgw.cfg  etc.

The new "version" contains some comments starting with #AG
This comments are a little bit unordered loud thinking about my idea an can be removed and
sometimes the old implementation. They can be removed


There is one question about an eval instruction where I am not sure if it is save:

+ #AG I am not a fan of using eval on variables with uncheck content.
+          #AG Some body could name a domain like "$(touch /tmp/dummy)"
+ #AG that is possible xl create --dryrun --defconfig ... except such a domain names
+          #AG I did  not try to create i finally
+ #AG I tryed some some combination to do a hack on this expression but I always failed. + #AG I think the `\´ in front of `$´ makes it save but I am not shure if this is always right.
            eval "
            case \"\$name\" in


Ordered auto starting of domains is not yet implemented. I think about using alphabetic order of /etc/xen/auto/* for starting and reverse order for stopping. I think to implement more dependencies
would be to complicated for xendomains and a big project for its own.

The patch fix the sxp -1 domain id bug by using xl list -l <domainname> ...
The patch fix the empty state problem by using xl list <domainname> ...


I replaced the LIST_GREP expression by a function which translate the sxp/json formated output from xl list -l to a stream of lines of `id:<value> name:<value>´. This lines are handled by the new readln implementation. First I thought about to using eval to set the variables. But I think the risk is to
high, if there is something bad in the values.

I only tested save and restore of domains.
I did not test  XENDOMAINS_SYSRQ, XENDOMAINS_MIGRATE and XENDOMAINS_SHUTDOWN
for different reasons ( not enough skill, no destination to migrate to, there is nothing changed in this blocks except that state in watchdog has now a value, and my family becomes angry about the up and downs of the server ;-) )

I would be glad if you give it a chance and test it.

Thanks

Question: Is it ok to use local for variable declarations in functions of ? Normally I prefer that.

Andreas

--vvvv xendomains patch -----------------------------
--- xendomains.4.3    2013-07-01 11:48:41.000000000 +0200
+++ xendomains    2013-07-04 23:55:03.000000000 +0200
@@ -26,15 +26,18 @@
 # Description:       Start / stop domains automatically when domain 0
 #                    boots / shuts down.
 ### END INIT INFO
+#AG set -x
+#AG set -v

 . /etc/xen/scripts/hotplugpath.sh

-CMD=${SBINDIR}/xm
+CMD="${SBINDIR}/xm"
 HEADCOMP="LinuxGuestRecord"
+
 $CMD list &> /dev/null
 if test $? -ne 0
 then
-    CMD=${SBINDIR}/xl
+        CMD=${SBINDIR}/xl
     HEADCOMP="Xen saved domain"
 fi

@@ -185,8 +188,35 @@
 # read name from xen config file
 rdname()
 {
-    NM=$($CMD create --quiet --dryrun --defconfig "$1" |
-         sed -n 's/^.*(name \(.*\))$/\1/p')
+    #AG the old implementation works only for sxp formated output
+    #AG NM=$($CMD create --quiet --dryrun --defconfig "$1" |
+    #AG     sed -n 's/^.*(name \(.*\))$/\1/p')
+
+    #AG The new implemnetation works with an pattern matching address range
+    #AG but only if the output of xl is in correct json or sxp format
+    #AG For json the output must start with a line containing only a `{´
+ #AG and ending with a line containing only a `}´. All lines bevor "start" and after "end" + #AG are ignored. For sxp the output must start with a line containing only a `(domain´
+    #AG and ending with a line containing only a `)´
+    #AG
+ #AG /^[{]$/,/^[}]$/ {...} is an pattern address range match it executes the block {...} + #AG for every line between the start pattern `^[{]$´ and the end pattern `^[}]$´ + #AG including the lines with start and end pattern. `[{]´ is the same as `\{´ . I prefer + #AG the first one for sed scripts in shell scripts because it make its clear that it
+    #AG belongs to the sed script and not to the shell script.
+ #AG Here the first addres range /^[{]$/,/^[}]$/ {...} gets aktive if the output is in + #AG JSON format and the second /^[(]domain$/,/^[)]$/ {...} when the output is in sxp fromat. + #AG Thanks to the author of http://www.grymoire.com/Unix/Sed.html#uh-25 for explaining sed
+    #AG so clear.
+    NM=$(
+      ${CMD} create --quiet --dryrun --defconfig "${1}" \
+      |  sed -n -e '
+          /^[{]$/,/^[}]$/ {
+              s/^.*"name": "\(.*\)",$/\1/p }
+          /^[(]domain$/,/^[)]$/ {
+              s/^.*(name \(.*\))$/\1/p }
+      '
+    )
 }

 rdnames()
@@ -206,22 +236,113 @@
     done
 }

-LIST_GREP='(domain\|(domid\|(name\|^    {$\|"name":\|"domid":'
-parseln()
-{
-    if [[ "$1" =~ '(domain' ]] || [[ "$1" = "{" ]]; then
-        name=;id=
-    elif [[ "$1" =~ '(name' ]]; then
-        name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
-    elif [[ "$1" =~ '(domid' ]]; then
-        id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
-    elif [[ "$1" =~ '"name":' ]]; then
-        name=$(echo $1 | sed -e 's/^.*"name": "\(.*\)",$/\1/')
-    elif [[ "$1" =~ '"domid":' ]]; then
-        id=$(echo $1 | sed -e 's/^.*"domid": \(.*\),$/\1/')
-    fi

-    [ -n "$name" -a -n "$id" ] && return 0 || return 1
+getDomStateByName () {
+    local _name=
+    local _id=
+    local _mem=
+    local _vcpu=
+    local _state=
+    local _time=
+    local _dummy=
+    while read _name _id _mem _vcpu _state _time _dummy; do
+      [ -n "${_state}" ] && break;
+    done <<EOF
+$( ${CMD} list "${1}" | sed -n -e '/^Name[ ][ ]*ID[ ][ ]*Mem[ ][ ]*VCPUs[ ][ ]*State/! p' )
+EOF
+    echo "${_state}"
+}
+
+getDomIdByName () {
+    $CMD list -l "${1}" \
+    | sed -n -e '/^{$/,/^}$/ { s/^.*"domid": "\(-\?[0-9][0-9]*\)",$/\1/p }
+        /^(domain$/,/^)$/ { s/^.*(domid \(-\?[0-9][0-9]*\))$/\1/p }'
+}
+
+#AG LIST_GREP='(domain\|(domid\|(name\|^    {$\|"name":\|"domid":'
+#AG list_domians() is the replacement for the expression ($CMD list -l | grep "$LIST_GREP")
+#AG here the sxp and json parsing is impelmented
+#AG for every domain it produce a line with `id:<value> name:<value>´
+#AG Perhaps it is possible to combine the two sed piped sed script to a single one but at
+#AG the moment I couldn' see the solution.
+list_domains () {
+  #AG ^[     ] contain a space and a ht 0x09
+  $CMD list -l \
+  | sed -n -e '
+      /^    {$/,/^    },$/ {
+        s/^[     ][     ]*"domid": \(-\?[0-9][0-9]*\),$/id="\1" / p
+        s/^[     ][     ]*"name": "\(.*\)",$/name="\1" / p
+        s/^    }\(,\|\)$/BREAK/ p
+      }
+      /^(domain$/,/^)$/ {
+        s/^[     ][     ]*(domid \(-\?[0-9][0-9]*\))$/id="\1" / p
+        s/^[     ][    ]*(name \(.*\))$/name="\1" / p
+        s/^)$/BREAK/ p
+      }
+    ' \
+  | sed -n  -e '
+      /BREAK$/! { H }
+      /BREAK$/ {
+        x
+        s/\n//g
+        p
+        s/.*//
+        x
+      }
+    '
+}
+
+#AG parseln()
+#AG {
+#AG     if [[ "$1" =~ '(domain' ]] || [[ "$1" = "{" ]]; then
+#AG         name=;id=
+#AG     elif [[ "$1" =~ '(name' ]]; then
+#AG         name=$(echo $1 | sed -e 's/^.*(name \(.*\))$/\1/')
+#AG     elif [[ "$1" =~ '(domid' ]]; then
+#AG         id=$(echo $1 | sed -e 's/^.*(domid \(.*\))$/\1/')
+#AG     elif [[ "$1" =~ '"name":' ]]; then
+#AG         name=$(echo $1 | sed -e 's/^.*"name": "\(.*\)",$/\1/')
+#AG     elif [[ "$1" =~ '"domid":' ]]; then
+#AG        id=$(echo $1 | sed -e 's/^.*"domid": \(.*\),$/\1/')
+#AG     fi
+#AG
+#AG     [ -n "$name" -a -n "$id" ] && return 0 || return 1
+#AG }
+parseln () {
+    id=
+    name=
+    state=
+    for _i in ${LN}; do
+        _k="${_i%=*}"
+    case "${_k}" in
+        (name)
+        _v="${_i#${_k}=}"
+        if [ "${_v}" != "${_i}" ]; then
+            _v="${_v//\"/}"
+            name="${_v}"
+        fi
+        ;;
+        (id)
+        _v="${_i#${_k}=}"
+        if [ "${_v}" != "${_i}" ]; then
+            _v="${_v//\"/}"
+            id="${_v}"
+        fi
+        ;;
+    esac
+    done
+    if [ -n "${name}" -a \( -z "${id}" -o "${id}" = "-1" \) ]; then
+    v="$(getDomIdByName ${name})"
+    if [ -n "${v}" ]; then
+        id="${v}"
+    fi
+    fi
+    if [ -n "${name}" -a  -n "${id}" ]; then
+    state="$(getDomStateByName ${name})"
+    return 0
+    else
+    return 1
+    fi
 }

 is_running()
@@ -237,7 +358,10 @@
         RC=0
         ;;
     esac
-    done < <($CMD list -l | grep "$LIST_GREP")
+    done <<EOF
+$( list_domains )
+EOF
+    #AG done < <($CMD list -l | grep "$LIST_GREP")
     return $RC
 }

@@ -319,7 +443,10 @@
     if test "$state" != "-b---d" -a "$state" != "-----d"; then
         return 1;
     fi
-    done < <($CMD list -l | grep "$LIST_GREP")
+    done <<EOF
+$( list_domains )
+EOF
+    #AG done < <($CMD list -l | grep "$LIST_GREP")
     return 0
 }

@@ -368,6 +495,12 @@
     if test $id = 0; then continue; fi
     echo -n " $name"
     if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
+ #AG I am not a fan of using eval on variables with uncheck content.
+          #AG Some body could name a domain like "$(touch /tmp/dummy)"
+ #AG that is possible xl create --dryrun --defconfig ... except such a domain names
+          #AG I did  not try to create i finally
+ #AG I tryed some some combination to do a hack on this expression but I always failed. + #AG I think the `\´ in front of `$´ makes it save but I am not shure if this is always right.
         eval "
         case \"\$name\" in
         ($NAMES)
@@ -450,7 +583,10 @@
         fi
         kill $WDOG_PID >/dev/null 2>&1
     fi
-    done < <($CMD list -l | grep "$LIST_GREP")
+    done <<EOF
+$( list_domains )
+EOF
+    #AG done < <($CMD list -l | grep "$LIST_GREP")

     # NB. this shuts down ALL Xen domains (politely), not just the ones in
     # AUTODIR/*
@@ -487,7 +623,10 @@
         return 0
         ;;
     esac
-    done < <($CMD list -l | grep "$LIST_GREP")
+    done <<EOF
+$( list_domains)
+EOF
+    #AG done < <($CMD list -l | grep "$LIST_GREP")
     return 1
 }

--^^^^ xendomains patch -----------------------------

On 07/01/13 19:09, Ian Murray wrote:



----- Original Message -----
From: Andreas Greve<greve-ml@xxxxxxxxxx>
To: Ian Murray<murrayie@xxxxxxxxxxx>
Cc: greve-ml@xxxxxxxxxx; xen-users<xen-users@xxxxxxxxxxxxx>; 
andreas.greve@xxxxxxxxxx
Sent: Monday, 1 July 2013, 17:44
Subject: Re: [Xen-users] Xen 4.2.2 /etc/init.d/xendomains save and restore
  of domains does not work
I have an idea.

assumptions:

SXP format:
root@srv01:~# xl create --quiet --dryrun --defconfig
/etc/xen/auto/03_gnomedag | head -10
(domain
          (domid -1)
          (create_info)
          (hvm 0)
          (hap<default>)
          (oos<default>)
          (ssidref 0)
          (name gnomedag)
          (uuid<unknown>)
          (cpupool Pool-0)
[...]
)
root@srv01:~#

JSON format:
xl create --quiet --dryrun --defconfig /etc/xen/auto/03_gnomedag | head -10
{
      "domid": null,
      "config": {
          "c_info": {
              "type": "pv",
              "hap": "<default>",
              "oos": "<default>",
              "ssidref": 0,
              "name": "gnomedag",
              "uuid": "d9a9eba0-e7b8-4d16-ad6e-bb4cac05fd14",
[...]
}

Let use sed  pattern address ranges to distinguish between JSON and SXP.


xl create --quiet --dryrun --defconfig /etc/xen/auto/03_gnomedag \
|  sed -n -e '/^[{]$/,/^[}]$/ { s/^.*"name":
"\(.*\)",$/\1/p }
/^[(]domain$/,/^[)]$/ { s/^.*(name \(.*\))$/\1/p }'

/^[{]$/,/^[}]$/  identify JSON
/^[(]domain$/,/^[)]$/  identify SXP

the line break between ...\1/p} and /^[(]domain$... is syntactical
needed by sed.


sed -n -e '/^[{]$/,$ { s/^.*"name":
"\(.*\)",$/\1/p }
/^[(]domain$/,$ { s/^.*(name \(.*\))$/\1/p }'<  json.out

in the example above  ,$ in the address range part  means until  end of file

For the JSON filter perhaps you can use somthing like this
/^[ ]*"c_info": [{]$/,$
as address range because `"c_info": {´ is comes close before
`"name:"
"gnomedag"´ but I
know not enough about xl to estimate if that is always true.

but further I have to look at the stop() function at the block

      if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
         eval
         [...]
      fi

for bad side effects of the now working rdnames() ->  rdname()
You've gone beyond my sed/regex skills so I can't really assist on the above. I 
think the best thing is for you to try to get it into a working patch and I'd 
be happy to test it, then you could submit it to the dev list for inclusion. 
Also beware that there is an bug in xl list -l in sxp format. The domain id 
comes out as -1 for a running domain. I agreed to adapt a commit as a backport 
when we discussed this on dev list.


[...]



_______________________________________________
Xen-users mailing list
Xen-users@xxxxxxxxxxxxx
http://lists.xen.org/xen-users


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.