# HG changeset patch # User David Scott # Date 1271079881 -3600 # Node ID c2ba03f407d05b94ea883eb5dee68be9f24a72bc # Parent 6182bc7d23af84bb7e5138c698dc2efda20c35dc CA-40134: when looking up a domid, always look up the domain by uuid rather than relying on the value in the master's database (which could be out of sync). In particular if the master is suddenly powercycled then recent domid updates might be lost. This results in VMs which are impossible to shutdown. Looking up the domain by uuid should be strictly better than using the master's version: both are moving targets (eg over migrate) and so we already rely on the per-VM lock to protect (most) accesses. The only problem is the code is slightly inefficient: it still has to contact the master to look up the VM's uuid and then has to list all domains on the host to build up a table of uuid -> domid. This can be improved later. Signed-off-by: David Scott diff -r 6182bc7d23af -r c2ba03f407d0 ocaml/xapi/helpers.ml --- a/ocaml/xapi/helpers.ml Fri Apr 09 10:56:14 2010 +0100 +++ b/ocaml/xapi/helpers.ml Mon Apr 12 14:44:41 2010 +0100 @@ -384,8 +384,16 @@ then raise Device_has_no_VIF else List.assoc devid table +(** Return the domid on the *local host* associated with a specific VM. + Note that if this is called without the VM lock then the result is undefined: the + domid might immediately change after the call returns. Caller beware! *) let domid_of_vm ~__context ~self = - Int64.to_int (Db.VM.get_domid ~__context ~self) + let uuid = Uuid.uuid_of_string (Db.VM.get_uuid ~__context ~self) in + let all = Xc.with_intf (fun xc -> Xc.domain_getinfolist xc 0) in + let uuid_to_domid = List.map (fun di -> Uuid.uuid_of_int_array di.Xc.handle, di.Xc.domid) all in + if List.mem_assoc uuid uuid_to_domid + then List.assoc uuid uuid_to_domid + else -1 (* for backwards compat with old behaviour *) let get_guest_installer_network ~__context = let nets = Db.Network.get_all ~__context in