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

[Xen-API] [PATCH 3 of 4] CA-33707: Refactor the xenops shutdown functions to (i) make them robust to being called in parallel with (eg) domain destroy; and (ii) to make it possible to call 'shutdown' more than once



# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1260486289 0
# Node ID ca92f46da128588874c6c660aef6409adae119dd
# Parent  90cd62326033db94c84c9c8f607f27335e3c76c4
CA-33707: Refactor the xenops shutdown functions to (i) make them robust to 
being called in parallel with (eg) domain destroy; and (ii) to make it possible 
to call 'shutdown' more than once.

One side-effect is that if a guest misses the initial signal to shutdown then 
we can try a few more times before giving up.

Signed-off-by: David Scott <dave.scott@xxxxxxxxxxxxx>

diff -r 90cd62326033 -r ca92f46da128 ocaml/xenops/domain.ml
--- a/ocaml/xenops/domain.ml    Thu Dec 10 23:04:48 2009 +0000
+++ b/ocaml/xenops/domain.ml    Thu Dec 10 23:04:49 2009 +0000
@@ -201,41 +201,47 @@
 (** Return the path in xenstore watched by the PV shutdown driver *)
 let control_shutdown ~xs domid = xs.Xs.getdomainpath domid ^ 
"/control/shutdown"
 
+(** Raised if a domain has vanished *)
+exception Domain_does_not_exist
+
 (** Request a shutdown, return without waiting for acknowledgement *)
 let shutdown ~xs domid req =
        debug "Requesting shutdown of domain %d" domid;
        let reason = string_of_shutdown_reason req in
-       xs.Xs.write (control_shutdown ~xs domid) reason
+       let path = control_shutdown ~xs domid in
+       let domainpath = xs.Xs.getdomainpath domid in
+       Xs.transaction xs
+               (fun t ->
+                        (* Fail if the directory has been deleted *)
+                        let domain_exists = try ignore (t.Xst.read 
domainpath); true with Xb.Noent -> false in
+                        if not domain_exists then raise Domain_does_not_exist;
+                        (* Delete the node if it already exists. NB: the guest 
may well still shutdown for the
+                               previous reason... we only want to give it a 
kick again just in case. *)
+                        (try t.Xst.rm path with _ -> ());
+                        t.Xst.write path reason
+               )
 
-(** PV domains will acknowledge the request by deleting the node from the
-    store, block until this happens. *)
-let shutdown_wait_for_ack ?timeout ~xs domid req =
+(** If domain is PV, signal it to shutdown. If the PV domain fails to respond 
then throw a Watch.Timeout exception.
+       All other exceptions imply the domain has disappeared. *)
+let shutdown_wait_for_ack ?(timeout=60.) ~xc ~xs domid req =
+  let di = Xc.domain_getinfo xc domid in
+
+  if di.Xc.hvm_guest then begin
+       if Xc.hvm_check_pvdriver xc domid
+       then debug "HVM guest with PV drivers: not expecting any 
acknowledgement"
+       else Xc.domain_shutdown xc domid (shutdown_to_xc_shutdown req)
+  end else begin
        debug "Waiting for PV domain %d to acknowledge shutdown request" domid;
        let path = control_shutdown ~xs domid in
-       try
-         Watch.wait_for ~xs ?timeout (Watch.value_to_become path "");
-         debug "Domain acknowledged shutdown request";
-         true
-       with Watch.Timeout _ ->
-         debug "Timed-out waiting for domain to acknowledge shutdown request";
-         false
-
-
-let shutdown_ack ?(timeout=60.) ~xc ~xs domid req =
-       (* For both PV and HVM, write the control/shutdown node *)
-       shutdown ~xs domid req;
-       (* PV domains will acknowledge the request (if not then something
-          very bad is wrong) *)
-       if not((Xc.domain_getinfo xc domid).Xc.hvm_guest)
-       then shutdown_wait_for_ack ~timeout ~xs domid req
-       else begin
-         (* If HVM domain has no PV drivers, we shut it down here *)
-         if not(Xc.hvm_check_pvdriver xc domid)
-         then Xc.domain_shutdown xc domid (shutdown_to_xc_shutdown req);
-         (* If HVM domain has PV drivers, it shuts itself down but it
-            doesn't remove the control/shutdown node. *)
-         true
-       end
+       (* If already shutdown then we continue *)
+       if not di.Xc.shutdown
+       then match Watch.wait_for ~xs ~timeout (Watch.any_of [ `Ack, 
Watch.value_to_become path "";
+                                                                               
                          `Gone, Watch.key_to_disappear path ]) with
+       | `Ack, _ ->
+                 debug "Domain acknowledged shutdown request"
+       | `Gone, _ ->
+                 debug "Domain disappeared"
+  end
 
 let sysrq ~xs domid key =
        let path = xs.Xs.getdomainpath domid ^ "/control/sysrq" in
diff -r 90cd62326033 -r ca92f46da128 ocaml/xenops/domain.mli
--- a/ocaml/xenops/domain.mli   Thu Dec 10 23:04:48 2009 +0000
+++ b/ocaml/xenops/domain.mli   Thu Dec 10 23:04:49 2009 +0000
@@ -77,6 +77,9 @@
 
 (** Immediately force shutdown the domain with reason 'shutdown_reason' *)
 val hard_shutdown: xc:Xc.handle -> domid -> shutdown_reason -> unit
+
+(** Thrown if the domain has disappeared *)
+exception Domain_does_not_exist
 
 (** Tell the domain to shutdown with reason 'shutdown_reason'. Don't wait for 
an ack *)
 val shutdown: xs:Xs.xsh -> domid -> shutdown_reason -> unit
2 files changed, 37 insertions(+), 28 deletions(-)
ocaml/xenops/domain.ml  |   62 +++++++++++++++++++++++++----------------------
ocaml/xenops/domain.mli |    3 ++


Attachment: xen-api.hg-4.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

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