You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2013/11/14 13:11:28 UTC

[2/3] git commit: updated refs/heads/4.2-workplace to 1148b6f

VM state detection is done


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b3236309
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b3236309
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b3236309

Branch: refs/heads/4.2-workplace
Commit: b323630901e133ba5a08270661e3f3531a549bb2
Parents: ded95cc
Author: Alex Huang <al...@citrix.com>
Authored: Wed Nov 13 06:03:00 2013 -0800
Committer: Alex Huang <al...@citrix.com>
Committed: Thu Nov 14 04:11:25 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/vm/VirtualMachineName.java    |  15 +-
 .../xen/resource/CitrixResourceBase.java        | 383 +++++++++++++------
 .../xen/resource/XenServerPoolVms.java          |  10 +-
 3 files changed, 291 insertions(+), 117 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b3236309/api/src/com/cloud/vm/VirtualMachineName.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/VirtualMachineName.java b/api/src/com/cloud/vm/VirtualMachineName.java
index 1279fd6..dfa70ab 100755
--- a/api/src/com/cloud/vm/VirtualMachineName.java
+++ b/api/src/com/cloud/vm/VirtualMachineName.java
@@ -21,7 +21,7 @@ import java.util.Formatter;
 import com.cloud.dc.Vlan;
 
 /**
- * VM Name. 
+ * VM Name.
  */
 public class VirtualMachineName {
     public static final String SEPARATOR = "-";
@@ -61,6 +61,19 @@ public class VirtualMachineName {
         return instance == null || instance.equals(tokens[3]);
     }
     
+    public static boolean isValidCloudStackVmName(String name, String instance) {
+        String[] parts = name.split(SEPARATOR);
+        if (parts.length <= 1) {
+            return false;
+        }
+
+        if (!parts[parts.length - 1].equals(instance)) {
+            return false;
+        }
+
+        return true;
+    }
+
     public static String getVmName(long vmId, long userId, String instance) {
         StringBuilder vmName = new StringBuilder("i");
         vmName.append(SEPARATOR).append(userId).append(SEPARATOR).append(vmId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b3236309/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index fa1aef3..c2a3e7b 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -66,6 +66,7 @@ import com.trilead.ssh2.SCPClient;
 import com.xensource.xenapi.Bond;
 import com.xensource.xenapi.Connection;
 import com.xensource.xenapi.Console;
+import com.xensource.xenapi.Event;
 import com.xensource.xenapi.Host;
 import com.xensource.xenapi.HostCpu;
 import com.xensource.xenapi.HostMetrics;
@@ -81,8 +82,10 @@ import com.xensource.xenapi.Types;
 import com.xensource.xenapi.Types.BadAsyncResult;
 import com.xensource.xenapi.Types.BadServerResponse;
 import com.xensource.xenapi.Types.ConsoleProtocol;
+import com.xensource.xenapi.Types.EventsLost;
 import com.xensource.xenapi.Types.IpConfigurationMode;
 import com.xensource.xenapi.Types.OperationNotAllowed;
+import com.xensource.xenapi.Types.SessionNotRegistered;
 import com.xensource.xenapi.Types.SrFull;
 import com.xensource.xenapi.Types.VbdType;
 import com.xensource.xenapi.Types.VmBadPowerState;
@@ -300,7 +303,7 @@ import com.cloud.utils.net.NetUtils;
 import com.cloud.utils.ssh.SSHCmdHelper;
 import com.cloud.vm.DiskProfile;
 import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachine.State;
+import com.cloud.vm.VirtualMachineName;
 import com.cloud.vm.snapshot.VMSnapshot;
 
 /**
@@ -362,6 +365,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
     protected StorageSubsystemCommandHandler storageHandler;
     protected int _maxNics = 7;
+    protected VmEventListener _listener = null;
 
     public enum SRType {
         NFS, LVM, ISCSI, ISO, LVMOISCSI, LVMOHBA, EXT, FILE;
@@ -382,14 +386,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    protected static HashMap<Types.VmPowerState, State> s_statesTable;
+    protected static HashMap<Types.VmPowerState, VirtualMachine.State> s_statesTable;
     static {
-        s_statesTable = new HashMap<Types.VmPowerState, State>();
-        s_statesTable.put(Types.VmPowerState.HALTED, State.Stopped);
-        s_statesTable.put(Types.VmPowerState.PAUSED, State.Running);
-        s_statesTable.put(Types.VmPowerState.RUNNING, State.Running);
-        s_statesTable.put(Types.VmPowerState.SUSPENDED, State.Running);
-        s_statesTable.put(Types.VmPowerState.UNRECOGNIZED, State.Unknown);
+        s_statesTable = new HashMap<Types.VmPowerState, VirtualMachine.State>();
+        s_statesTable.put(Types.VmPowerState.HALTED, VirtualMachine.State.Stopped);
+        s_statesTable.put(Types.VmPowerState.PAUSED, VirtualMachine.State.Running);
+        s_statesTable.put(Types.VmPowerState.RUNNING, VirtualMachine.State.Running);
+        s_statesTable.put(Types.VmPowerState.SUSPENDED, VirtualMachine.State.Running);
+        s_statesTable.put(Types.VmPowerState.UNRECOGNIZED, VirtualMachine.State.Unknown);
     }
 
     public XsHost getHost() {
@@ -791,7 +795,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 vm.destroy(conn);
                 vmState = VirtualMachine.State.Stopped;
             } else {
-                s_vms.put(_cluster, _name, vmName, State.Running);
+                s_vms.put(_cluster, _name, vmName, VirtualMachine.State.Running);
                 vmState = VirtualMachine.State.Running;
             }
 
@@ -1652,7 +1656,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         Connection conn = getConnection();
         VirtualMachineTO vmSpec = cmd.getVirtualMachine();
         String vmName = vmSpec.getName();
-        State state = State.Stopped;
+        VirtualMachine.State state = VirtualMachine.State.Stopped;
         VM vm = null;
         try {
             Set<VM> vms = VM.getByNameLabel(conn, vmName);
@@ -1674,7 +1678,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
             }
             synchronized (_cluster.intern()) {
-                s_vms.put(_cluster, _name, vmName, State.Starting);
+                s_vms.put(_cluster, _name, vmName, VirtualMachine.State.Starting);
             }
             s_logger.debug("1. The VM " + vmName + " is in Starting state.");
 
@@ -1763,7 +1767,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
             }
 
-            state = State.Running;
+            state = VirtualMachine.State.Running;
             return new StartAnswer(cmd);
         } catch (Exception e) {
             s_logger.warn("Catch Exception: " + e.getClass().toString() + " due to " + e.toString(), e);
@@ -1771,7 +1775,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             return new StartAnswer(cmd, msg);
         } finally {
             synchronized (_cluster.intern()) {
-                if (state != State.Stopped) {
+                if (state != VirtualMachine.State.Stopped) {
                     s_vms.put(_cluster, _name, vmName, state);
                     s_logger.debug("2. The VM " + vmName + " is in " + state + " state.");
                 } else {
@@ -2928,13 +2932,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    protected State convertToState(Types.VmPowerState ps) {
-        final State state = s_statesTable.get(ps);
-        return state == null ? State.Unknown : state;
+    protected VirtualMachine.State convertToState(Types.VmPowerState ps) {
+        final VirtualMachine.State state = s_statesTable.get(ps);
+        return state == null ? VirtualMachine.State.Unknown : state;
     }
 
-    protected HashMap<String, Ternary<String, State, String>> getAllVms(Connection conn) {
-        final HashMap<String, Ternary<String, State, String>> vmStates = new HashMap<String, Ternary<String, State, String>>();
+    protected HashMap<String, Ternary<String, VirtualMachine.State, String>> getAllVms(Connection conn) {
+        final HashMap<String, Ternary<String, VirtualMachine.State, String>> vmStates = new HashMap<String, Ternary<String, VirtualMachine.State, String>>();
         Map<VM, VM.Record>  vm_map = null;
         for (int i = 0; i < 2; i++) {
             try {
@@ -2959,7 +2963,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             }
 
             VmPowerState ps = record.powerState;
-            final State state = convertToState(ps);
+            final VirtualMachine.State state = convertToState(ps);
             if (s_logger.isTraceEnabled()) {
                 s_logger.trace("VM " + record.nameLabel + ": powerstate = " + ps + "; vm state=" + state.toString());
             }
@@ -2976,14 +2980,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 } catch (XmlRpcException e) {
                     s_logger.error("Failed to get host uuid for host " + host.toWireString(), e);
                 }
-                vmStates.put(record.nameLabel, new Ternary<String, State, String>(host_uuid, state, xstoolsversion));
+                vmStates.put(record.nameLabel, new Ternary<String, VirtualMachine.State, String>(host_uuid, state, xstoolsversion));
             }
         }
 
         return vmStates;
     }
 
-    protected State getVmState(Connection conn, final String vmName) {
+    protected VirtualMachine.State getVmState(Connection conn, final String vmName) {
         int retry = 3;
         while (retry-- > 0) {
             try {
@@ -3020,17 +3024,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             }
         }
 
-        return State.Stopped;
+        return VirtualMachine.State.Stopped;
     }
 
     protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
         Connection conn = getConnection();
         final String vmName = cmd.getVmName();
-        final State state = getVmState(conn, vmName);
+        final VirtualMachine.State state = getVmState(conn, vmName);
         Integer vncPort = null;
-        if (state == State.Running) {
+        if (state == VirtualMachine.State.Running) {
             synchronized (_cluster.intern()) {
-                s_vms.put(_cluster, _name, vmName, State.Running);
+                s_vms.put(_cluster, _name, vmName, VirtualMachine.State.Running);
             }
             s_logger.debug("3. The VM " + vmName + " is in Running state");
         }
@@ -3054,7 +3058,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 getNetwork(conn, nic);
             }
             synchronized (_cluster.intern()) {
-                s_vms.put(_cluster, _name, vm.getName(), State.Migrating);
+                s_vms.put(_cluster, _name, vm.getName(), VirtualMachine.State.Migrating);
             }
             s_logger.debug("4. The VM " +  vm.getName() + " is in Migrating state");
 
@@ -3065,27 +3069,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    private String copy_vhd_to_secondarystorage(Connection conn, String mountpoint, String vdiuuid, String sruuid, int wait) {
-        String results = callHostPluginAsync(conn, "vmopspremium", "copy_vhd_to_secondarystorage",
-                wait, "mountpoint", mountpoint, "vdiuuid", vdiuuid, "sruuid", sruuid);
-        String errMsg = null;
-        if (results == null || results.isEmpty()) {
-            errMsg = "copy_vhd_to_secondarystorage return null";
-        } else {
-            String[] tmp = results.split("#");
-            String status = tmp[0];
-            if (status.equals("0")) {
-                return tmp[1];
-            } else {
-                errMsg = tmp[1];
-            }
-        }
-        String source = vdiuuid + ".vhd";
-        killCopyProcess(conn, source);
-        s_logger.warn(errMsg);
-        throw new CloudRuntimeException(errMsg);
-    }
-
     String upgradeSnapshot(Connection conn, String templatePath, String snapshotPath) {
         String results = callHostPluginAsync(conn, "vmopspremium", "upgrade_snapshot",
                 2 * 60 * 60, "templatePath", templatePath, "snapshotPath", snapshotPath);
@@ -3316,12 +3299,12 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     protected MigrateAnswer execute(final MigrateCommand cmd) {
         Connection conn = getConnection();
         final String vmName = cmd.getVmName();
-        State state = null;
+        VirtualMachine.State state = null;
 
         state = s_vms.getState(_cluster, vmName);
 
         synchronized (_cluster.intern()) {
-            s_vms.put(_cluster, _name, vmName, State.Stopping);
+            s_vms.put(_cluster, _name, vmName, VirtualMachine.State.Stopping);
         }
         s_logger.debug("5. The VM " + vmName + " is in Stopping state");
         try {
@@ -3353,7 +3336,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
                 migrateVM(conn, dsthost, vm, vmName);
                 vm.setAffinity(conn, dsthost);
-                state = State.Stopping;
+                state = VirtualMachine.State.Stopping;
             }
             return new MigrateAnswer(cmd, true, "migration succeeded", null);
         } catch (Exception e) {
@@ -3369,9 +3352,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
     }
 
-    protected State getRealPowerState(Connection conn, String label) {
+    protected VirtualMachine.State getRealPowerState(Connection conn, String label) {
         int i = 0;
-        s_logger.trace("Checking on the HALTED State");
+        s_logger.trace("Checking on the HALTED VirtualMachine.State");
         for (; i < 20; i++) {
             try {
                 Set<VM> vms = VM.getByNameLabel(conn, label);
@@ -3398,7 +3381,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             } catch (InterruptedException e) {
             }
         }
-        return State.Stopped;
+        return VirtualMachine.State.Stopped;
     }
 
     protected Pair<VM, VM.Record> getControlDomain(Connection conn) throws XenAPIException, XmlRpcException {
@@ -3482,7 +3465,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     public RebootAnswer execute(RebootCommand cmd) {
         Connection conn = getConnection();
         synchronized (_cluster.intern()) {
-            s_vms.put(_cluster, _name, cmd.getVmName(), State.Starting);
+            s_vms.put(_cluster, _name, cmd.getVmName(), VirtualMachine.State.Starting);
         }
         s_logger.debug("7. The VM " + cmd.getVmName() + " is in Starting state");
         try {
@@ -3508,7 +3491,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             return new RebootAnswer(cmd, "reboot succeeded", true);
         } finally {
             synchronized (_cluster.intern()) {
-                s_vms.put(_cluster, _name, cmd.getVmName(), State.Running);
+                s_vms.put(_cluster, _name, cmd.getVmName(), VirtualMachine.State.Running);
             }
             s_logger.debug("8. The VM " + cmd.getVmName() + " is in Running state");
         }
@@ -4035,10 +4018,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                     return new StopAnswer(cmd, msg, false);
                 }
 
-                State state = s_vms.getState(_cluster, vmName);
+                VirtualMachine.State state = s_vms.getState(_cluster, vmName);
 
                 synchronized (_cluster.intern()) {
-                    s_vms.put(_cluster, _name, vmName, State.Stopping);
+                    s_vms.put(_cluster, _name, vmName, VirtualMachine.State.Stopping);
                 }
                 s_logger.debug("9. The VM " + vmName + " is in Stopping state");
 
@@ -4083,7 +4066,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                                 networks.add(vif.getNetwork(conn));
                             }
                             vm.destroy(conn);
-                            state = State.Stopped;
+                            state = VirtualMachine.State.Stopped;
                             SR sr = getISOSRbyVmName(conn, cmd.getVmName());
                             removeSR(conn, sr);
                             // Disable any VLAN networks that aren't used
@@ -4135,24 +4118,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return "xenserver56";
     }
 
-    
-    private List<VDI> getVdis(Connection conn, VM vm) {
-        List<VDI> vdis = new ArrayList<VDI>();
-        try {
-            Set<VBD> vbds =vm.getVBDs(conn);
-            for( VBD vbd : vbds ) {
-                vdis.add(vbd.getVDI(conn));
-            }
-        } catch (XenAPIException e) {
-            String msg = "getVdis can not get VPD due to " + e.toString();
-            s_logger.warn(msg, e);
-        } catch (XmlRpcException e) {
-            String msg = "getVdis can not get VPD due to " + e.getMessage();
-            s_logger.warn(msg, e);
-        }
-        return vdis;
-    }
-
     protected String connect(Connection conn, final String vmName, final String ipAddress, final int port) {
         for (int i = 0; i <= _retry; i++) {
             try {
@@ -5000,8 +4965,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
             Host.Record hostr = poolr.master.getRecord(conn);
             if (_host.uuid.equals(hostr.uuid)) {
-                HashMap<String, Ternary<String, State, String>> allStates=fullClusterSync(conn);
+                HashMap<String, Ternary<String, VirtualMachine.State, String>> allStates=fullClusterSync(conn);
                 cmd.setClusterVMStateChanges(allStates);
+                _listener = new VmEventListener();
+                _listener.start();
             }
         } catch (Throwable e) {
             s_logger.warn("Check for master failed, failing the FULL Cluster sync command");
@@ -8109,12 +8076,31 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             s_logger.warn("Check for master failed, failing the Cluster sync command");
             return  new Answer(cmd);
         }
-        HashMap<String, Ternary<String, State, String>> newStates = deltaClusterSync(conn);
+        HashMap<String, Ternary<String, VirtualMachine.State, String>> newStates = deltaClusterSync(conn);
         return new ClusterSyncAnswer(cmd.getClusterId(), newStates);
     }
 
+    protected boolean isMaster() {
+        Connection conn = getConnection();
+        //check if this is master
+        Pool pool;
+        try {
+            pool = Pool.getByUuid(conn, _host.pool);
+            Pool.Record poolr = pool.getRecord(conn);
+
+            Host.Record hostr = poolr.master.getRecord(conn);
+            return _host.uuid.equals(hostr.uuid);
+        } catch (BadServerResponse e) {
+            throw new CloudRuntimeException("Unable to determine if this is the master: " + _host.ip, e);
+        } catch (XenAPIException e) {
+            throw new CloudRuntimeException("Unable to determine if this is the master: " + _host.ip, e);
+        } catch (XmlRpcException e) {
+            throw new CloudRuntimeException("Unable to determine if this is the master: " + _host.ip, e);
+        }
+    }
+
 
-    protected HashMap<String, Ternary<String, State, String>> fullClusterSync(Connection conn) {
+    protected HashMap<String, Ternary<String, VirtualMachine.State, String>> fullClusterSync(Connection conn) {
         synchronized (_cluster.intern()) {
             s_vms.clear(_cluster);
         }
@@ -8126,7 +8112,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
                 String vm_name = record.nameLabel;
                 VmPowerState ps = record.powerState;
-                final State state = convertToState(ps);
+                final VirtualMachine.State state = convertToState(ps);
                 String xstoolsversion = getVMXenToolsVersion(record.platform);
                 Host host = record.residentOn;
                 String host_uuid = null;
@@ -8149,31 +8135,31 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     }
 
 
-    protected HashMap<String, Ternary<String, State, String>> deltaClusterSync(Connection conn) {
-        final HashMap<String, Ternary<String, State, String>> changes = new HashMap<String, Ternary<String, State, String>>();
+    protected HashMap<String, Ternary<String, VirtualMachine.State, String>> deltaClusterSync(Connection conn) {
+        final HashMap<String, Ternary<String, VirtualMachine.State, String>> changes = new HashMap<String, Ternary<String, VirtualMachine.State, String>>();
 
 
         synchronized (_cluster.intern()) {
-            HashMap<String, Ternary<String, State, String>> newStates = getAllVms(conn);
+            HashMap<String, Ternary<String, VirtualMachine.State, String>> newStates = getAllVms(conn);
             if (newStates == null) {
                 s_logger.warn("Unable to get the vm states so no state sync at this point.");
                 return null;
             }
-            HashMap<String, Ternary<String, State, String>>  oldStates = new HashMap<String, Ternary<String, State, String>>(s_vms.size(_cluster));
+            HashMap<String, Ternary<String, VirtualMachine.State, String>>  oldStates = new HashMap<String, Ternary<String, VirtualMachine.State, String>>(s_vms.size(_cluster));
             oldStates.putAll(s_vms.getClusterVmState(_cluster));
 
-            for (final Map.Entry<String, Ternary<String, State, String>> entry : newStates.entrySet()) {
+            for (final Map.Entry<String, Ternary<String, VirtualMachine.State, String>> entry : newStates.entrySet()) {
                 final String vm = entry.getKey();
                 String xstoolsversion = entry.getValue().third();
-                State newState = entry.getValue().second();
+                VirtualMachine.State newState = entry.getValue().second();
                 String host_uuid = entry.getValue().first();
-                final Ternary<String, State, String> oldState = oldStates.remove(vm);
+                final Ternary<String, VirtualMachine.State, String> oldState = oldStates.remove(vm);
                 
                 // check if xstoolsversion changed
                 if (xstoolsversion != null && oldState != null){
-                    if (xstoolsversion != oldState.third() && newState != State.Stopped && newState != State.Stopping){
+                    if (xstoolsversion != oldState.third() && newState != VirtualMachine.State.Stopped && newState != VirtualMachine.State.Stopping){
                         s_logger.warn("Detecting a change in xstoolsversion for " + vm);
-                        changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, xstoolsversion));
+                        changes.put(vm, new Ternary<String, VirtualMachine.State, String>(host_uuid, newState, xstoolsversion));
 
                         s_logger.debug("11. The VM " + vm + " is in " + newState + " state");
                         s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
@@ -8182,9 +8168,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
                 //check if host is changed
                 if (host_uuid != null && oldState != null){
-                    if (!host_uuid.equals(oldState.first()) && newState != State.Stopped && newState != State.Stopping){
+                    if (!host_uuid.equals(oldState.first()) && newState != VirtualMachine.State.Stopped && newState != VirtualMachine.State.Stopping){
                         s_logger.warn("Detecting a change in host for " + vm);
-                        changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
+                        changes.put(vm, new Ternary<String, VirtualMachine.State, String>(host_uuid, newState, null));
 
                         s_logger.debug("11. The VM " + vm + " is in " + newState + " state");
                         s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
@@ -8193,7 +8179,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 }
 
 
-                if (newState == State.Stopped  && oldState != null && oldState.second() != State.Stopping && oldState.second() != State.Stopped) {
+                if (newState == VirtualMachine.State.Stopped  && oldState != null && oldState.second() != VirtualMachine.State.Stopping && oldState.second() != VirtualMachine.State.Stopped) {
                     newState = getRealPowerState(conn, vm);
                 }
 
@@ -8208,62 +8194,62 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 if (oldState == null) {
                     s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                     s_logger.warn("Detecting a new state but couldn't find a old state so adding it to the changes: " + vm);
-                    changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
-                } else if (oldState.second() == State.Starting) {
-                    if (newState == State.Running) {
-                        s_logger.debug("12. The VM " + vm + " is in " + State.Running + " state");
+                    changes.put(vm, new Ternary<String, VirtualMachine.State, String>(host_uuid, newState, null));
+                } else if (oldState.second() == VirtualMachine.State.Starting) {
+                    if (newState == VirtualMachine.State.Running) {
+                        s_logger.debug("12. The VM " + vm + " is in " + VirtualMachine.State.Running + " state");
                         s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
-                    } else if (newState == State.Stopped) {
+                    } else if (newState == VirtualMachine.State.Stopped) {
                         s_logger.warn("Ignoring vm " + vm + " because of a lag in starting the vm.");
                     }
-                } else if (oldState.second() == State.Migrating) {
-                    if (newState == State.Running) {
+                } else if (oldState.second() == VirtualMachine.State.Migrating) {
+                    if (newState == VirtualMachine.State.Running) {
                         s_logger.debug("Detected that an migrating VM is now running: " + vm);
                         s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                     }
-                } else if (oldState.second() == State.Stopping) {
-                    if (newState == State.Stopped) {
-                        s_logger.debug("13. The VM " + vm + " is in " + State.Stopped + " state");
+                } else if (oldState.second() == VirtualMachine.State.Stopping) {
+                    if (newState == VirtualMachine.State.Stopped) {
+                        s_logger.debug("13. The VM " + vm + " is in " + VirtualMachine.State.Stopped + " state");
                         s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
-                    } else if (newState == State.Running) {
+                    } else if (newState == VirtualMachine.State.Running) {
                         s_logger.warn("Ignoring vm " + vm + " because of a lag in stopping the vm. ");
                     }
                 } else if (oldState.second() != newState) {
                     s_logger.debug("14. The VM " + vm + " is in " + newState + " state was " + oldState.second());
                     s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
-                    if (newState == State.Stopped) {
+                    if (newState == VirtualMachine.State.Stopped) {
                         /*
                          * if (s_vmsKilled.remove(vm)) { s_logger.debug("VM " + vm + " has been killed for storage. ");
-                         * newState = State.Error; }
+                         * newState = VirtualMachine.State.Error; }
                          */
                     }
-                    changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
+                    changes.put(vm, new Ternary<String, VirtualMachine.State, String>(host_uuid, newState, null));
                 }
             }
 
-            for (final Map.Entry<String, Ternary<String, State, String>> entry : oldStates.entrySet()) {
+            for (final Map.Entry<String, Ternary<String, VirtualMachine.State, String>> entry : oldStates.entrySet()) {
                 final String vm = entry.getKey();
-                final State oldState = entry.getValue().second();
+                final VirtualMachine.State oldState = entry.getValue().second();
                 String host_uuid = entry.getValue().first();
 
                 if (s_logger.isTraceEnabled()) {
                     s_logger.trace("VM " + vm + " is now missing from xen so reporting stopped");
                 }
 
-                if (oldState == State.Stopping) {
+                if (oldState == VirtualMachine.State.Stopping) {
                     s_logger.warn("Ignoring VM " + vm + " in transition state stopping.");
                     s_vms.remove(_cluster, host_uuid, vm);
-                } else if (oldState == State.Starting) {
+                } else if (oldState == VirtualMachine.State.Starting) {
                     s_logger.warn("Ignoring VM " + vm + " in transition state starting.");
-                } else if (oldState == State.Stopped) {
+                } else if (oldState == VirtualMachine.State.Stopped) {
                     s_logger.debug("VM missing " + vm + " old state stopped so removing.");
                     s_vms.remove(_cluster, host_uuid, vm);
-                } else if (oldState == State.Migrating) {
+                } else if (oldState == VirtualMachine.State.Migrating) {
                     s_logger.warn("Ignoring VM " + vm + " in migrating state.");
                 } else {
-                    State newState = State.Stopped;
+                    VirtualMachine.State newState = VirtualMachine.State.Stopped;
                     s_logger.warn("The VM is now missing marking it as Stopped " + vm);
-                    changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
+                    changes.put(vm, new Ternary<String, VirtualMachine.State, String>(host_uuid, newState, null));
                 }
             }
         }
@@ -8624,6 +8610,175 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
+    protected class VmEventListener extends Thread {
+        boolean _stop = false;
+        HashMap<String, Ternary<String, VirtualMachine.State, String>> changes = new HashMap<String, Ternary<String, VirtualMachine.State, String>>();
+        
+        @Override
+        public void run() {
+            setName("XS-Listener-" + _host.ip);
+            String token = "";
+            Set<String> classes = new HashSet<String>();
+            classes.add("VM");
+            while (!_stop) {
+                Connection conn = getConnection();
+                Map results;
+                try {
+                    results = Event.properFrom(conn, classes, token, new Double(30));
+                } catch (BadServerResponse e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    continue;
+                } catch (SessionNotRegistered e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    continue;
+                } catch (EventsLost e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    continue;
+                } catch (XenAPIException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    continue;
+                } catch (XmlRpcException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    continue;
+                }
+
+                token = (String)results.get("token");
+                Set<Event.Record> events = (Set<Event.Record>)results.get("events");
+                for (Event.Record event : events) {
+                    try {
+                        if (!(event.snapshot instanceof VM.Record)) {
+                            s_logger.debug("The snapshot is not a VM: " + event);
+                            continue;
+                        }
+                        VM.Record vm = (VM.Record)event.snapshot;
+                        if (!VirtualMachineName.isValidCloudStackVmName(vm.nameLabel, _instance)) {
+                            s_logger.debug("Skipping over VMs that does not form to the CloudStack naming convention: " + vm.nameLabel);
+                            continue;
+                        }
+                        recordChanges(conn, vm, vm.residentOn.getUuid(conn));
+                    } catch (BadServerResponse e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    } catch (XenAPIException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    } catch (XmlRpcException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+
+                }
+            }
+        }
+
+        protected void recordChanges(Connection conn, VM.Record rec, String hostUuid) {
+            synchronized (_cluster.intern()) {
+                String xstoolsversion = null;
+                VirtualMachine.State newState = convertToState(rec.powerState);
+                String vm = rec.nameLabel;
+                Ternary<String, VirtualMachine.State, String> oldState = s_vms.get(_cluster, vm);
+
+                if (oldState == null) {
+                    // If we can't find this VM in the previous states then it must have been stopped.
+                    oldState = new Ternary<String, VirtualMachine.State, String>(null, VirtualMachine.State.Stopped, null);
+                    s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                    changes.put(vm, new Ternary<String, VirtualMachine.State, String>(hostUuid, newState, null));
+                }
+                
+                // check if xstoolsversion changed
+                if (xstoolsversion != null) {
+                    if (xstoolsversion != oldState.third() && newState != VirtualMachine.State.Stopped && newState != VirtualMachine.State.Stopping) {
+                        s_logger.warn("Detecting a change in xstoolsversion for " + vm);
+                        changes.put(vm, new Ternary<String, VirtualMachine.State, String>(hostUuid, newState, xstoolsversion));
+
+                        if (s_logger.isDebugEnabled()) {
+                            s_logger.debug("11. The VM " + vm + " is in " + newState + " state");
+                        }
+                        s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                        return;
+                    }
+                }
+                
+                //check if host is changed
+                if (hostUuid != null) {
+                    if (!hostUuid.equals(oldState.first()) && newState != VirtualMachine.State.Stopped && newState != VirtualMachine.State.Stopping) {
+                        s_logger.warn("Detecting a change in host for " + vm);
+                        changes.put(vm, new Ternary<String, VirtualMachine.State, String>(hostUuid, newState, null));
+
+                        s_logger.debug("11. The VM " + vm + " is in " + newState + " state");
+                        s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                        return;
+                    }
+                }
+
+                if (newState == VirtualMachine.State.Stopped && oldState.second() != VirtualMachine.State.Stopping && oldState.second() != VirtualMachine.State.Stopped) {
+                    newState = getRealPowerState(conn, vm);
+                }
+
+                if (s_logger.isTraceEnabled()) {
+                    s_logger.trace("VM " + vm + ": xen has state " + newState + " and we have state " + (oldState != null ? oldState.toString() : "null"));
+                }
+
+                if (vm.startsWith("migrating")) {
+                    s_logger.warn("Migrating from xen detected.  Skipping");
+                    return;
+                }
+                
+                if (oldState.second() == VirtualMachine.State.Starting) {
+                    if (newState == VirtualMachine.State.Running) {
+                        s_logger.debug("12. The VM " + vm + " is in " + VirtualMachine.State.Running + " state");
+                        s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                    } else if (newState == VirtualMachine.State.Stopped) {
+                        s_logger.warn("Ignoring vm " + vm + " because of a lag in starting the vm.");
+                    }
+                } else if (oldState.second() == VirtualMachine.State.Migrating) {
+                    if (newState == VirtualMachine.State.Running) {
+                        s_logger.debug("Detected that an migrating VM is now running: " + vm);
+                        s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                    }
+                } else if (oldState.second() == VirtualMachine.State.Stopping) {
+                    if (newState == VirtualMachine.State.Stopped) {
+                        s_logger.debug("13. The VM " + vm + " is in " + VirtualMachine.State.Stopped + " state");
+                        s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                    } else if (newState == VirtualMachine.State.Running) {
+                        s_logger.warn("Ignoring vm " + vm + " because of a lag in stopping the vm. ");
+                    }
+                } else if (oldState.second() != newState) {
+                    s_logger.debug("14. The VM " + vm + " is in " + newState + " state was " + oldState.second());
+                    s_vms.put(_cluster, hostUuid, vm, newState, xstoolsversion);
+                    if (newState == VirtualMachine.State.Stopped) {
+                        /*
+                         * if (s_vmsKilled.remove(vm)) { s_logger.debug("VM " + vm + " has been killed for storage. ");
+                         * newState = VirtualMachine.State.Error; }
+                         */
+                    }
+                    changes.put(vm, new Ternary<String, VirtualMachine.State, String>(hostUuid, newState, null));
+                }
+            }
+        }
+
+        public HashMap<String, Ternary<String, VirtualMachine.State, String>> getChanges() {
+            synchronized(_cluster.intern()) {
+                if (changes.size() == 0) {
+                    return null;
+                }
+                HashMap<String, Ternary<String, VirtualMachine.State, String>> diff = changes;
+                changes = new HashMap<String, Ternary<String, VirtualMachine.State, String>>();
+                return diff;
+            }
+        }
+
+        public void signalStop() {
+            _stop = true;
+            interrupt();
+        }
+    }
+
 	@Override
 	public void setName(String name) {
 	}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b3236309/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
index f22fb28..8797e0a 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerPoolVms.java
@@ -11,15 +11,17 @@
 // Unless required by applicable law or agreed to in writing,
 // software distributed under the License is distributed on an
 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the 
+// KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
 package com.cloud.hypervisor.xen.resource;
 
 import java.util.HashMap;
 import java.util.Map;
-import org.apache.log4j.Logger;
 import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.log4j.Logger;
+
 import com.cloud.utils.Ternary;
 import com.cloud.vm.VirtualMachine.State;
 
@@ -51,6 +53,10 @@ public class XenServerPoolVms {
         return pv == null ? State.Stopped : pv.second(); // if a VM is absent on the cluster, it is effectively in stopped state.
     }
     
+    public Ternary<String, State, String> get(String clusterId, String name) {
+        HashMap<String, Ternary<String, State, String>> vms = getClusterVmState(clusterId);
+        return vms.get(name);
+    }
 
     public void put(String clusterId, String hostUuid, String name, State state, String xstoolsversion){
         HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);