You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by an...@apache.org on 2013/10/23 02:55:10 UTC

git commit: updated refs/heads/master to e33ae74

Updated Branches:
  refs/heads/master aca6c420b -> e33ae7406


CLOUDSTACK-4649:
    xs 6.1/6.2 introduce the new virtual platform, so there are two virtual platforms, windows PV driver version must match virtual platforms,
this patch tracks PV driver versions in vm details and template details.

Anthony


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

Branch: refs/heads/master
Commit: e33ae74067d5d7ff165098028c0bd6897f14bbd2
Parents: aca6c42
Author: Anthony Xu <an...@citrix.com>
Authored: Mon Oct 21 16:10:07 2013 -0700
Committer: Anthony Xu <an...@citrix.com>
Committed: Tue Oct 22 17:54:51 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/agent/api/ClusterSyncAnswer.java  |   8 +-
 .../cloud/agent/api/StartupRoutingCommand.java  |   8 +-
 core/src/com/cloud/agent/api/StopAnswer.java    |  23 ++--
 .../com/cloud/vm/VirtualMachineManagerImpl.java |  79 +++++++++++---
 .../com/cloud/storage/dao/VMTemplateDao.java    |   3 +
 .../cloud/storage/dao/VMTemplateDaoImpl.java    |  17 +++
 .../framework/config/dao/ConfigurationDao.java  |   2 +
 .../config/dao/ConfigurationDaoImpl.java        |   9 +-
 .../networkservice/BareMetalResourceBase.java   |   2 +-
 .../kvm/resource/LibvirtComputingResource.java  |   2 +-
 .../cloud/ovm/hypervisor/OvmResourceBase.java   |   4 +-
 .../cloud/agent/manager/MockVmManagerImpl.java  |   2 +-
 .../cloud/resource/AgentRoutingResource.java    |   2 +-
 .../vmware/resource/VmwareResource.java         |   8 +-
 .../xen/resource/CitrixResourceBase.java        | 109 +++++++++++++------
 .../xen/resource/XenServer610Resource.java      |  22 ++++
 .../xen/resource/XenServerPoolVms.java          |  39 ++++---
 .../vm/hypervisor/xenserver/setupxenserver.sh   |   2 +-
 server/src/com/cloud/configuration/Config.java  |   2 +
 .../cloud/hypervisor/HypervisorGuruBase.java    |   6 +-
 .../cloud/server/ConfigurationServerImpl.java   |  80 ++++++++++++++
 .../com/cloud/server/ManagementServerImpl.java  |   6 +-
 .../com/cloud/template/TemplateAdapterBase.java |  17 +++
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  14 ++-
 .../cloud/vpc/dao/MockConfigurationDaoImpl.java |  11 +-
 25 files changed, 368 insertions(+), 109 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/core/src/com/cloud/agent/api/ClusterSyncAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/ClusterSyncAnswer.java b/core/src/com/cloud/agent/api/ClusterSyncAnswer.java
index 99fee2a..e5ea1f1 100644
--- a/core/src/com/cloud/agent/api/ClusterSyncAnswer.java
+++ b/core/src/com/cloud/agent/api/ClusterSyncAnswer.java
@@ -18,12 +18,12 @@ package com.cloud.agent.api;
 
 import java.util.HashMap;
 
-import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
 import com.cloud.vm.VirtualMachine.State;
 
 public class ClusterSyncAnswer extends Answer {
     private long _clusterId;
-    private HashMap<String, Pair<String, State>> _newStates;
+    private HashMap<String, Ternary<String, State, String>> _newStates;
     private boolean _isExecuted=false;
 
     // this is here because a cron command answer is being sent twice
@@ -38,7 +38,7 @@ public class ClusterSyncAnswer extends Answer {
     }
 
 
-    public ClusterSyncAnswer(long clusterId, HashMap<String, Pair<String, State>> newStates){
+    public ClusterSyncAnswer(long clusterId, HashMap<String, Ternary<String, State, String>> newStates){
         _clusterId = clusterId;
         _newStates = newStates;
         result = true;
@@ -48,7 +48,7 @@ public class ClusterSyncAnswer extends Answer {
         return _clusterId;
     }
 
-    public HashMap<String, Pair<String, State>> getNewStates() {
+    public HashMap<String, Ternary<String, State, String>> getNewStates() {
         return _newStates;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/core/src/com/cloud/agent/api/StartupRoutingCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/com/cloud/agent/api/StartupRoutingCommand.java
index 5961ab0..d52666b 100755
--- a/core/src/com/cloud/agent/api/StartupRoutingCommand.java
+++ b/core/src/com/cloud/agent/api/StartupRoutingCommand.java
@@ -22,7 +22,7 @@ import java.util.Map;
 import com.cloud.host.Host;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.network.Networks.RouterPrivateIpStrategy;
-import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
 import com.cloud.vm.VirtualMachine.State;
 
 public class StartupRoutingCommand extends StartupCommand {
@@ -48,7 +48,7 @@ public class StartupRoutingCommand extends StartupCommand {
     long dom0MinMemory;
     boolean poolSync;
     Map<String, VmState> vms;
-    HashMap<String, Pair<String, State>> _clusterVMStates;
+    HashMap<String, Ternary<String, State, String>> _clusterVMStates;
     String caps;
     String pool;
     HypervisorType hypervisorType;
@@ -129,7 +129,7 @@ getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStr
         }
     }
 
-    public void setClusterVMStateChanges(HashMap<String, Pair<String, State>> allStates){
+    public void setClusterVMStateChanges(HashMap<String, Ternary<String, State, String>> allStates){
     	_clusterVMStates = allStates;
     }
 
@@ -157,7 +157,7 @@ getHostDetails().put(RouterPrivateIpStrategy.class.getCanonicalName(), privIpStr
         return vms;
     }
 
-    public HashMap<String, Pair<String, State>> getClusterVMStateChanges() {
+    public HashMap<String, Ternary<String, State, String>> getClusterVMStateChanges() {
         return _clusterVMStates;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/core/src/com/cloud/agent/api/StopAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/StopAnswer.java b/core/src/com/cloud/agent/api/StopAnswer.java
index 0af2385..614835e 100755
--- a/core/src/com/cloud/agent/api/StopAnswer.java
+++ b/core/src/com/cloud/agent/api/StopAnswer.java
@@ -17,37 +17,34 @@
 package com.cloud.agent.api;
 
 public class StopAnswer extends RebootAnswer {
-    Integer vncPort;
+
+    private String hypervisortoolsversion;
     Integer timeOffset;
 
     protected StopAnswer() {
     }
 
-    public StopAnswer(StopCommand cmd, String details, Integer vncPort, Integer timeOffset, boolean success) {
+    public StopAnswer(StopCommand cmd, String details, String hypervisortoolsversion, Integer timeOffset, boolean success) {
         super(cmd,  details, success);
-        this.vncPort = vncPort;
+        this.hypervisortoolsversion = hypervisortoolsversion;
         this.timeOffset = timeOffset;
     }
 
-    public StopAnswer(StopCommand cmd, String details, Integer vncPort, boolean success) {
+    public StopAnswer(StopCommand cmd, String details, boolean success) {
         super(cmd,  details, success);
-        this.vncPort = vncPort;
+        this.hypervisortoolsversion = null;
         this.timeOffset = null;
     }
 
-    public StopAnswer(StopCommand cmd, String details, boolean success) {
-        super(cmd, details, success);
-        vncPort = null;
-        timeOffset = null;
-    }
 
     public StopAnswer(StopCommand cmd, Exception e) {
         super(cmd, e);
+        this.hypervisortoolsversion = null;
+        this.timeOffset = null;
     }
 
-    @Override
-    public Integer getVncPort() {
-        return vncPort;
+    public String getHypervisorToolsVersion() {
+        return hypervisortoolsversion;
     }
 
     public Integer getTimeOffset() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 8bf419f..81b1cdc 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -884,6 +884,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                             StopCommand cmd = new StopCommand(vm, getExecuteInSequence());
                             StopAnswer answer = (StopAnswer)_agentMgr.easySend(destHostId, cmd);
+                           if ( answer != null ) {
+                                String hypervisortoolsversion = answer.getHypervisorToolsVersion();
+                                if (hypervisortoolsversion != null) {
+                                    UserVmVO userVm = _userVmDao.findById(vm.getId());
+                                    _userVmDao.loadDetails(userVm);
+                                    userVm.setDetail("hypervisortoolsversion",  hypervisortoolsversion);
+                                    _userVmDao.saveDetails(userVm);
+                                }
+                            }
+
                             if (answer == null || !answer.getResult()) {
                                 s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers"));
                                 _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop);
@@ -989,7 +999,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VirtualMachine vm = profile.getVirtualMachine();
         StopCommand stop = new StopCommand(vm, getExecuteInSequence());
         try {
-            Answer answer = _agentMgr.send(vm.getHostId(), stop);
+            StopAnswer answer = (StopAnswer) _agentMgr.send(vm.getHostId(), stop);
+            if ( answer != null ) {
+                String hypervisortoolsversion = answer.getHypervisorToolsVersion();
+                if (hypervisortoolsversion != null) {
+                    UserVmVO userVm = _userVmDao.findById(vm.getId());
+                    _userVmDao.loadDetails(userVm);
+                    userVm.setDetail("hypervisortoolsversion",  hypervisortoolsversion);
+                    _userVmDao.saveDetails(userVm);
+                }
+            }
             if (!answer.getResult()) {
                 s_logger.debug("Unable to stop VM due to " + answer.getDetails());
                 return false;
@@ -1185,6 +1204,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         StopAnswer answer = null;
         try {
             answer = (StopAnswer)_agentMgr.send(vm.getHostId(), stop);
+
+            if ( answer != null ) {
+                String hypervisortoolsversion = answer.getHypervisorToolsVersion();
+                if (hypervisortoolsversion != null) {
+                    UserVmVO userVm = _userVmDao.findById(vm.getId());
+                    _userVmDao.loadDetails(userVm);
+                    userVm.setDetail("hypervisortoolsversion",  hypervisortoolsversion);
+                    _userVmDao.saveDetails(userVm);
+                }
+            }
             stopped = answer.getResult();
             if (!stopped) {
                 throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
@@ -1997,7 +2026,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         return commands;
     }
 
-    public void deltaSync(Map<String, Pair<String, State>> newStates) {
+
+
+    public void deltaSync(Map<String, Ternary<String, State, String>> newStates) {
         Map<Long, AgentVmInfo> states = convertToInfos(newStates);
 
         for (Map.Entry<Long, AgentVmInfo> entry : states.entrySet()) {
@@ -2032,9 +2063,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         }
     }
 
-    public void fullSync(final long clusterId, Map<String, Pair<String, State>> newStates) {
-        if (newStates == null)
-            return;
+    public void fullSync(final long clusterId, Map<String, Ternary<String, State, String>> newStates) {
+        if (newStates==null)
+        	return;
         Map<Long, AgentVmInfo> infos = convertToInfos(newStates);
         Set<VMInstanceVO> set_vms = Collections.synchronizedSet(new HashSet<VMInstanceVO>());
         set_vms.addAll(_vmDao.listByClusterId(clusterId));
@@ -2162,24 +2193,27 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
     }
 
-    protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, Pair<String, State>> newStates) {
+
+    protected Map<Long, AgentVmInfo> convertToInfos(final Map<String, Ternary<String, State, String>> newStates) {
         final HashMap<Long, AgentVmInfo> map = new HashMap<Long, AgentVmInfo>();
         if (newStates == null) {
             return map;
         }
         boolean is_alien_vm = true;
         long alien_vm_count = -1;
-        for (Map.Entry<String, Pair<String, State>> entry : newStates.entrySet()) {
+        for (Map.Entry<String, Ternary<String, State, String>> entry : newStates.entrySet()) {
             is_alien_vm = true;
             String name = entry.getKey();
             VMInstanceVO vm = _vmDao.findVMByInstanceName(name);
             if (vm != null) {
-                map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vm, entry.getValue().second(), entry.getValue().first()));
+                map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vm, entry.getValue().second(),
+                		entry.getValue().first(), entry.getValue().third()));
                 is_alien_vm = false;
             }
             // alien VMs
             if (is_alien_vm) {
-                map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, entry.getValue().second(), entry.getValue().first()));
+                map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, entry.getValue().second(), 
+                		entry.getValue().first(), entry.getValue().third()));
                 s_logger.warn("Found an alien VM " + entry.getKey());
             }
         }
@@ -2544,9 +2578,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         long agentId = agent.getId();
 
         if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
-            StartupRoutingCommand startup = (StartupRoutingCommand)cmd;
-            HashMap<String, Pair<String, State>> allStates = startup.getClusterVMStateChanges();
-            if (allStates != null) {
+            StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
+            HashMap<String, Ternary<String, State, String>> allStates = startup.getClusterVMStateChanges();
+            if (allStates != null){
                 fullSync(clusterId, allStates);
             }
 
@@ -2625,22 +2659,35 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         public String name;
         public State state;
         public String hostUuid;
+        public String hvtoolsversion;
         public VMInstanceVO vm;
 
-        public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) {
+
+        @SuppressWarnings("unchecked")
+        public AgentVmInfo(String name, VMInstanceVO vm, State state, String host, String hvtoolsversion) {
             this.name = name;
             this.state = state;
             this.vm = vm;
-            hostUuid = host;
+            this.hostUuid = host;
+            this.hvtoolsversion= hvtoolsversion;
+            
         }
-
+        
+        public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) {
+        	this(name, vm, state, host, null);           
+        }
+        
         public AgentVmInfo(String name, VMInstanceVO vm, State state) {
-            this(name, vm, state, null);
+            this(name, vm, state, null, null);
         }
 
         public String getHostUuid() {
             return hostUuid;
         }
+        
+        public String getHvtoolsversion() {
+            return hvtoolsversion;
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
index 700ccf5..58dc2ed 100755
--- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
+++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
@@ -76,4 +76,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long> {
 
     List<VMTemplateVO> findTemplatesToSyncToS3();
 
+    void loadDetails(VMTemplateVO tmpl);
+
+    void saveDetails(VMTemplateVO tmpl);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
index a96524c..901ae80 100755
--- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -402,6 +402,23 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
         return routerTmpltName;
     }
 
+
+    @Override
+    public void loadDetails(VMTemplateVO tmpl) {
+        Map<String, String> details = _templateDetailsDao.findDetails(tmpl.getId());
+        tmpl.setDetails(details);
+    }
+
+    @Override
+    public void saveDetails(VMTemplateVO tmpl) {
+        Map<String, String> details = tmpl.getDetails();
+        if (details == null) {
+            return;
+        }
+        _templateDetailsDao.persist(tmpl.getId(), details);
+    }
+
+
     /*
      * @Override public Set<Pair<Long, Long>> searchSwiftTemplates(String name,
      * String keyword, TemplateFilter templateFilter, boolean isIso,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDao.java
----------------------------------------------------------------------
diff --git a/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDao.java b/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDao.java
index 2f4b6e2..58e8a69 100644
--- a/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDao.java
+++ b/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDao.java
@@ -55,6 +55,8 @@ public interface ConfigurationDao extends GenericDao<ConfigurationVO, String> {
     
     public String getValueAndInitIfNotExist(String name, String category, String initValue);
     
+    public String getValueAndInitIfNotExist(String name, String category, String initValue, String desc);
+    
 
     /**
      * returns whether or not this is a premium configuration

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java
----------------------------------------------------------------------
diff --git a/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java b/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java
index e402988..e98cbcc 100644
--- a/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java
+++ b/framework/config/src/org/apache/cloudstack/framework/config/dao/ConfigurationDaoImpl.java
@@ -168,8 +168,13 @@ public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String
     }
 
     @Override
-    @DB
     public String getValueAndInitIfNotExist(String name, String category, String initValue) {
+    	return getValueAndInitIfNotExist(name, category, initValue, ""); 
+    }
+    
+    @Override
+    @DB
+    public String getValueAndInitIfNotExist(String name, String category, String initValue, String desc) {
         String returnValue = initValue;
         try {
             ConfigurationVO config = findByName(name);
@@ -183,7 +188,7 @@ public class ConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, String
                 if (category.equals("Hidden") || category.equals("Secure")) {
                     initValue = DBEncryptionUtil.encrypt(initValue);
                 }
-                ConfigurationVO newConfig = new ConfigurationVO(category, "DEFAULT", "management-server", name, initValue, "");
+                ConfigurationVO newConfig = new ConfigurationVO(category, "DEFAULT", "management-server", name, initValue, desc);
                 persist(newConfig);
             }
             return returnValue;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
index a814530..fa7abd5 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
@@ -517,7 +517,7 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource
 			count++;
 		}
 
-		return success ? new StopAnswer(cmd, "Success", 0, true) : new StopAnswer(cmd, "IPMI power off failed", false);
+		return success ? new StopAnswer(cmd, "Success", true) : new StopAnswer(cmd, "IPMI power off failed", false);
 	}
 
 	protected StartAnswer execute(StartCommand cmd) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 371c4e0..51ba743 100755
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -3257,7 +3257,7 @@ ServerResource {
             }
 
             state = State.Stopped;
-            return new StopAnswer(cmd, result, 0, true);
+            return new StopAnswer(cmd, result, true);
         } catch (LibvirtException e) {
             return new StopAnswer(cmd, e.getMessage(), false);
         } finally {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
index 1eddedc..2d0d67b 100755
--- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
+++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
@@ -732,7 +732,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
                 vm = OvmVm.getDetails(_conn, vmName);
             } catch (XmlRpcException e) {
                 s_logger.debug("Unable to get details of vm: " + vmName + ", treating it as stopped", e);
-                return new StopAnswer(cmd, "success", 0, true);
+                return new StopAnswer(cmd, "success", true);
             }
 
             deleteAllNetworkRulesForVm(vmName);
@@ -740,7 +740,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
             cleanup(vm);
 
             state = State.Stopped;
-            return new StopAnswer(cmd, "success", 0, true);
+            return new StopAnswer(cmd, "success", true);
         } catch (Exception e) {
             s_logger.debug("Stop " + vmName + "failed", e);
             return new StopAnswer(cmd, e.getMessage(), false);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java
index 64df113..e503bc6 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java
@@ -517,7 +517,7 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager {
                 _mockAgentMgr.handleSystemVMStop(vm.getId());
             }
             txn.commit();
-            return new StopAnswer(cmd, null, new Integer(0), true);
+            return new StopAnswer(cmd, null, true);
         } catch (Exception ex) {
             txn.rollback();
             throw new CloudRuntimeException("unable to stop vm " + cmd.getVmName(), ex);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java
index 8a03c4b..9a27d74 100644
--- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java
+++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java
@@ -231,7 +231,7 @@ public class AgentRoutingResource extends AgentStorageResource {
 		        return new StopAnswer(cmd, result.getDetails(), false);
 		    }
 
-			answer = new StopAnswer(cmd, null, 0, true);
+			answer = new StopAnswer(cmd, null, true);
 			Pair<Long, Long> data = _runningVms.get(vmName);
 			if (data != null) {
 				this.usedCpu -= data.first();

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 66b0cc6..77e799d 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -3857,11 +3857,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
                     if (getVmState(vmMo) != State.Stopped) {
                         if (vmMo.safePowerOff(_shutdown_waitMs)) {
                             state = State.Stopped;
-                            return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", 0, true);
+                            return new StopAnswer(cmd, "Stop VM " + cmd.getVmName() + " Succeed", true);
                         } else {
                             String msg = "Have problem in powering off VM " + cmd.getVmName() + ", let the process continue";
                             s_logger.warn(msg);
-                            return new StopAnswer(cmd, msg, 0, true);
+                            return new StopAnswer(cmd, msg, true);
                         }
                     } else {
                         state = State.Stopped;
@@ -3869,7 +3869,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
                     String msg = "VM " + cmd.getVmName() + " is already in stopped state";
                     s_logger.info(msg);
-                    return new StopAnswer(cmd, msg, 0, true);
+                    return new StopAnswer(cmd, msg, true);
                 } finally {
                     synchronized (_vms) {
                         _vms.put(cmd.getVmName(), state);
@@ -3882,7 +3882,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
 
                 String msg = "VM " + cmd.getVmName() + " is no longer in vSphere";
                 s_logger.info(msg);
-                return new StopAnswer(cmd, msg, 0, true);
+                return new StopAnswer(cmd, msg, true);
             }
         } catch (Exception e) {
             if (e instanceof RemoteException) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/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 0ac8b1c..f16a6f5 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
@@ -207,9 +207,9 @@ import com.cloud.storage.template.TemplateProp;
 import com.cloud.template.VirtualMachineTemplate.BootloaderType;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
 import com.cloud.utils.S3Utils;
 import com.cloud.utils.StringUtils;
-import com.cloud.utils.Ternary;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 import com.cloud.vm.DiskProfile;
@@ -1349,8 +1349,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader());
             }
         }
+
+        try {
+            finalizeVmMetaData(vm, conn, vmSpec);
+        } catch ( Exception e) {
+            throw new CloudRuntimeException("Unable to finalize VM MetaData: " + vmSpec);
+        }
         return vm;
     }
+    
+    protected void finalizeVmMetaData(VM vm, Connection conn, VirtualMachineTO vmSpec) throws Exception {
+    }
+
 
     protected String handleVmStartFailure(Connection conn, String vmName, VM vm, String message, Throwable th) {
         String msg = "Unable to start " + vmName + " due to " + message;
@@ -2862,8 +2872,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return state == null ? State.Unknown : state;
     }
 
-    protected HashMap<String, Pair<String, State>> getAllVms(Connection conn) {
-        final HashMap<String, Pair<String, State>> vmStates = new HashMap<String, Pair<String, 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>>();
         Map<VM, VM.Record>  vm_map = null;
         for (int i = 0; i < 2; i++) {
             try {
@@ -2893,6 +2903,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 s_logger.trace("VM " + record.nameLabel + ": powerstate = " + ps + "; vm state=" + state.toString());
             }
             Host host = record.residentOn;
+            String xstoolsversion = getVMXenToolsVersion(record.platform);
             String host_uuid = null;
             if( ! isRefNull(host) ) {
                 try {
@@ -2904,7 +2915,7 @@ 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 Pair<String, State>(host_uuid, state));
+                vmStates.put(record.nameLabel, new Ternary<String, State, String>(host_uuid, state, xstoolsversion));
             }
         }
 
@@ -3915,7 +3926,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                     s_logger.info("VM does not exist on XenServer" + _host.uuid);
                     s_vms.remove(_cluster, _name, vmName);
                 }
-                return new StopAnswer(cmd, "VM does not exist", 0 , true);
+                return new StopAnswer(cmd, "VM does not exist", true);
             }
             for (VM vm : vms) {
                 VM.Record vmr = vm.getRecord(conn);
@@ -3972,6 +3983,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                             } catch (NumberFormatException e) {
                                 s_logger.error("Error while reading the platform:timeoffset field of the instance", e);
                             }
+                            String xentoolsversion = getVMXenToolsVersion(platform);
 
                             Set<VIF> vifs = vm.getVIFs(conn);
                             List<Network> networks = new ArrayList<Network>();
@@ -3993,7 +4005,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                                     // network might be destroyed by other host
                                 }
                             }
-                            return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, timeoffset, true);
+                            return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", xentoolsversion, timeoffset, true);
                         }
                     } catch (XenAPIException e) {
                         String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString();
@@ -4025,6 +4037,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return new StopAnswer(cmd, "Stop VM failed", false);
     }
 
+   
+    /*Override by subclass*/
+    protected String getVMXenToolsVersion(Map<String, String> platform) {
+        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 {
@@ -4873,7 +4909,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
             Host.Record hostr = poolr.master.getRecord(conn);
             if (_host.uuid.equals(hostr.uuid)) {
-                HashMap<String, Pair<String, State>> allStates=fullClusterSync(conn);
+                HashMap<String, Ternary<String, State, String>> allStates=fullClusterSync(conn);
                 cmd.setClusterVMStateChanges(allStates);
             }
         } catch (Throwable e) {
@@ -7055,7 +7091,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                     }
 
                 }
-
                 success = true;
                 details = null;
             } else if (cmd.getCommandSwitch().equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
@@ -7075,7 +7110,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             details += ", reason: " + e.toString();
             s_logger.warn(details, e);
         }
-
         return new ManageSnapshotAnswer(cmd, snapshotId, snapshotUUID, success, details);
     }
 
@@ -7999,13 +8033,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         } catch (Throwable e) {
             s_logger.warn("Check for master failed, failing the Cluster sync command");
             return  new Answer(cmd);
-        }
-        HashMap<String, Pair<String, State>> newStates = deltaClusterSync(conn);
+        } 
+        HashMap<String, Ternary<String, State, String>> newStates = deltaClusterSync(conn);
         return new ClusterSyncAnswer(cmd.getClusterId(), newStates);
     }
 
 
-    protected HashMap<String, Pair<String, State>> fullClusterSync(Connection conn) {
+    protected HashMap<String, Ternary<String, State, String>> fullClusterSync(Connection conn) {
         synchronized (_cluster.intern()) {
             s_vms.clear(_cluster);
         }
@@ -8018,12 +8052,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 String vm_name = record.nameLabel;
                 VmPowerState ps = record.powerState;
                 final State state = convertToState(ps);
+                String xstoolsversion = getVMXenToolsVersion(record.platform);
                 Host host = record.residentOn;
                 String host_uuid = null;
                 if( ! isRefNull(host) ) {
                     host_uuid = host.getUuid(conn);
                     synchronized (_cluster.intern()) {
-                        s_vms.put(_cluster, host_uuid, vm_name, state);
+                        s_vms.put(_cluster, host_uuid, vm_name, state, xstoolsversion);
                     }
                 }
                 if (s_logger.isTraceEnabled()) {
@@ -8039,38 +8074,50 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     }
 
 
-    protected HashMap<String, Pair<String, State>> deltaClusterSync(Connection conn) {
-        final HashMap<String, Pair<String, State>> changes = new HashMap<String, Pair<String, State>>();
+    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>>();
 
 
         synchronized (_cluster.intern()) {
-            HashMap<String, Pair<String, State>> newStates = getAllVms(conn);
+            HashMap<String, Ternary<String, 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, Pair<String, State>>  oldStates = new HashMap<String, Pair<String, State>>(s_vms.size(_cluster));
+            HashMap<String, Ternary<String, State, String>>  oldStates = new HashMap<String, Ternary<String, State, String>>(s_vms.size(_cluster));
             oldStates.putAll(s_vms.getClusterVmState(_cluster));
 
-            for (final Map.Entry<String, Pair<String, State>> entry : newStates.entrySet()) {
+            for (final Map.Entry<String, Ternary<String, State, String>> entry : newStates.entrySet()) {
                 final String vm = entry.getKey();
-
+                String xstoolsversion = entry.getValue().third();
                 State newState = entry.getValue().second();
                 String host_uuid = entry.getValue().first();
-                final Pair<String, State> oldState = oldStates.remove(vm);
+                final Ternary<String, 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){
+                        s_logger.warn("Detecting a change in xstoolsversion for " + vm);
+                        changes.put(vm, new Ternary<String, 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);
+                        continue;
+                    }
+                }
                 //check if host is changed
                 if (host_uuid != null && oldState != null){
                     if (!host_uuid.equals(oldState.first()) && newState != State.Stopped && newState != State.Stopping){
                         s_logger.warn("Detecting a change in host for " + vm);
-                        changes.put(vm, new Pair<String, State>(host_uuid, newState));
+                        changes.put(vm, new Ternary<String, 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);
+                        s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                         continue;
                     }
                 }
 
+
                 if (newState == State.Stopped  && oldState != null && oldState.second() != State.Stopping && oldState.second() != State.Stopped) {
                     newState = getRealPowerState(conn, vm);
                 }
@@ -8084,42 +8131,42 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                     continue;
                 }
                 if (oldState == null) {
-                    s_vms.put(_cluster, host_uuid, vm, newState);
+                    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 Pair<String, State>(host_uuid, newState));
+                    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");
-                        s_vms.put(_cluster, host_uuid, vm, newState);
+                        s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                     } else if (newState == 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) {
                         s_logger.debug("Detected that an migrating VM is now running: " + vm);
-                        s_vms.put(_cluster, host_uuid, vm, newState);
+                        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");
-                        s_vms.put(_cluster, host_uuid, vm, newState);
+                        s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                     } else if (newState == 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);
+                    s_vms.put(_cluster, host_uuid, vm, newState, xstoolsversion);
                     if (newState == State.Stopped) {
                         /*
                          * if (s_vmsKilled.remove(vm)) { s_logger.debug("VM " + vm + " has been killed for storage. ");
                          * newState = State.Error; }
                          */
                     }
-                    changes.put(vm, new Pair<String, State>(host_uuid, newState));
+                    changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
                 }
             }
 
-            for (final Map.Entry<String, Pair<String, State>> entry : oldStates.entrySet()) {
+            for (final Map.Entry<String, Ternary<String, State, String>> entry : oldStates.entrySet()) {
                 final String vm = entry.getKey();
                 final State oldState = entry.getValue().second();
                 String host_uuid = entry.getValue().first();
@@ -8141,7 +8188,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 } else {
                     State newState = State.Stopped;
                     s_logger.warn("The VM is now missing marking it as Stopped " + vm);
-                    changes.put(vm, new Pair<String, State>(host_uuid, newState));
+                    changes.put(vm, new Ternary<String, State, String>(host_uuid, newState, null));
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java
index c3c0307..2603922 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java
@@ -452,5 +452,27 @@ public class XenServer610Resource extends XenServer56FP1Resource {
     @Override
     protected void plugDom0Vif(Connection conn, VIF dom0Vif) throws XmlRpcException, XenAPIException {
         // do nothing. In xenserver 6.1 and beyond this step isn't needed.
+    }    
+  
+    @Override
+    protected String getVMXenToolsVersion(Map<String, String> platform) {
+        if (platform.containsKey("device_id")) {
+            return "xenserver61";
+        }
+        return "xenserver56";
     }
+    
+    @Override
+    protected void finalizeVmMetaData(VM vm, Connection conn, VirtualMachineTO vmSpec) throws Exception {
+        Map<String, String> details = vmSpec.getDetails();
+        if ( details!= null ) {
+            String xentoolsversion = details.get("hypervisortoolsversion");
+            if ( xentoolsversion == null || !xentoolsversion.equalsIgnoreCase("xenserver61") ) {
+                 Map<String, String> platform = vm.getPlatform(conn);
+                 platform.remove("device_id");
+                 vm.setPlatform(conn, platform);
+             }
+         }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/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 33f2bf9..f22fb28 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
@@ -20,20 +20,20 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.log4j.Logger;
 import java.util.concurrent.ConcurrentHashMap;
-import com.cloud.utils.Pair;
+import com.cloud.utils.Ternary;
 import com.cloud.vm.VirtualMachine.State;
 
  
 public class XenServerPoolVms {
     private static final Logger s_logger = Logger.getLogger(XenServerPoolVms.class);
-    private final Map<String/* clusterId */, HashMap<String/* vm name */, Pair<String/* host uuid */, State/* vm state */>>> _cluster_vms =
-         new ConcurrentHashMap<String, HashMap<String, Pair<String, State>>>();
+    private final Map<String/* clusterId */, HashMap<String/* vm name */, Ternary<String/* host uuid */, State/* vm state */, String/* PV driver version*/>>> _cluster_vms =
+         new ConcurrentHashMap<String, HashMap<String, Ternary<String, State, String>>>();
 
 
-    public HashMap<String, Pair<String, State>> getClusterVmState(String clusterId){
-        HashMap<String, Pair<String, State>> _vms= _cluster_vms.get(clusterId);
+    public HashMap<String, Ternary<String, State, String>> getClusterVmState(String clusterId){
+        HashMap<String, Ternary<String, State, String>> _vms= _cluster_vms.get(clusterId);
         if (_vms==null) {
-            HashMap<String, Pair<String, State>> vmStates =  new HashMap<String, Pair<String, State>>();
+            HashMap<String, Ternary<String, State, String>> vmStates =  new HashMap<String, Ternary<String, State, String>>();
             _cluster_vms.put(clusterId, vmStates);
             return vmStates;
         }
@@ -41,40 +41,47 @@ public class XenServerPoolVms {
     }
     
     public void clear(String clusterId){
-        HashMap<String, Pair<String, State>> _vms= getClusterVmState(clusterId);
+        HashMap<String, Ternary<String, State, String>> _vms= getClusterVmState(clusterId);
         _vms.clear();
     }
     
     public State getState(String clusterId, String name){
-        HashMap<String, Pair<String, State>> vms = getClusterVmState(clusterId);
-        Pair<String, State> pv = vms.get(name);
+        HashMap<String, Ternary<String, State, String>> vms = getClusterVmState(clusterId);
+        Ternary<String, State, String> pv = vms.get(name);
         return pv == null ? State.Stopped : pv.second(); // if a VM is absent on the cluster, it is effectively in stopped state.
     }
+    
+
+    public void put(String clusterId, String hostUuid, String name, State state, String xstoolsversion){
+        HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);
+        vms.put(name, new Ternary<String, State, String>(hostUuid, state, xstoolsversion));
+    }
+    
 
     public void put(String clusterId, String hostUuid, String name, State state){
-        HashMap<String, Pair<String, State>> vms= getClusterVmState(clusterId);
-        vms.put(name, new Pair<String, State>(hostUuid, state));
+        HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);
+        vms.put(name, new Ternary<String, State, String>(hostUuid, state, null));
     }
     
     public void remove(String clusterId, String hostUuid, String name){
-        HashMap<String, Pair<String, State>> vms= getClusterVmState(clusterId);
+        HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);
         vms.remove(name);
     }
     
-    public void putAll(String clusterId, HashMap<String, Pair<String, State>> new_vms){
-        HashMap<String, Pair<String, State>> vms= getClusterVmState(clusterId);
+    public void putAll(String clusterId, HashMap<String, Ternary<String, State, String>> new_vms){
+        HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);
         vms.putAll(new_vms);
     }
     
     public int size(String clusterId){
-        HashMap<String, Pair<String, State>> vms= getClusterVmState(clusterId);
+        HashMap<String, Ternary<String, State, String>> vms= getClusterVmState(clusterId);
         return vms.size();
     }
     
     @Override
     public String toString(){
         StringBuilder sbuf = new StringBuilder("PoolVms=");
-        for (HashMap<String/* vm name */, Pair<String/* host uuid */, State/* vm state */>>  clusterVM: _cluster_vms.values()){
+        for (HashMap<String/* vm name */, Ternary<String/* host uuid */, State/* vm state */, String>>  clusterVM: _cluster_vms.values()){
             for (String vmname: clusterVM.keySet()){
                 sbuf.append(vmname).append("-").append(clusterVM.get(vmname).second()).append(",");
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/scripts/vm/hypervisor/xenserver/setupxenserver.sh
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/setupxenserver.sh b/scripts/vm/hypervisor/xenserver/setupxenserver.sh
index e4b6f3e..311f273 100755
--- a/scripts/vm/hypervisor/xenserver/setupxenserver.sh
+++ b/scripts/vm/hypervisor/xenserver/setupxenserver.sh
@@ -49,7 +49,7 @@ sed -i 's/0\.0\.0\.0/127\.0\.0\.1/' /opt/xensource/libexec/qemu-dm-wrapper 2>&1
 sed -i /NOZEROCONF/d /etc/sysconfig/network
 echo "NOZEROCONF=yes" >> /etc/sysconfig/network
 
-[ -f /etc/cron.hourly/logrotate ] || mv /etc/cron.daily/logrotate /etc/cron.hourly 2>&1
+mv -n /etc/cron.daily/logrotate /etc/cron.hourly 2>&1
 
 # more aio thread
 echo 1048576 >/proc/sys/fs/aio-max-nr

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 857fdeb..3fdc343 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -246,6 +246,8 @@ public enum Config {
     XenHeartBeatInterval("Advanced", ManagementServer.class, Integer.class, "xen.heartbeat.interval", "60", "heartbeat to use when implementing XenServer Self Fencing", null),
     XenGuestNetwork("Hidden", ManagementServer.class, String.class, "xen.guest.network.device", null, "Specify for guest network name label", null),
     XenMaxNics("Advanced", AgentManager.class, Integer.class, "xen.nics.max", "7", "Maximum allowed nics for Vms created on Xen", null),
+    XenPVdriverVersion("Advanced", ManagementServer.class, String.class, "xen.pvdriver.version", "xenserver61", "default Xen PV driver version for registered template, valid value:xenserver56,xenserver61 ", "xenserver56,xenserver61"),
+
     // VMware
     VmwareUseNexusVSwitch("Network", ManagementServer.class, Boolean.class, "vmware.use.nexus.vswitch", "false", "Enable/Disable Cisco Nexus 1000v vSwitch in VMware environment", null),
     VmwareUseDVSwitch("Network", ManagementServer.class, Boolean.class, "vmware.use.dvswitch", "false", "Enable/Disable Nexus/Vmware dvSwitch in VMware environment", null),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 2ee6364..32c7693 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -113,14 +113,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
             to.setArch("x86_64");
         }
 
-        long templateId = vm.getTemplateId();
-        Map<String, String> details = _templateDetailsDao.findDetails(templateId);
-        assert(details != null);
         Map<String, String> detailsInVm = vm.getDetails();
         if(detailsInVm != null) {
-            details.putAll(detailsInVm);
+            to.setDetails(detailsInVm);
         }
-        to.setDetails(details);
         // Workaround to make sure the TO has the UUID we need for Niciri integration
         VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
         // check if XStools/VMWare tools are present in the VM and dynamic scaling feature is enabled (per zone/global)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/server/ConfigurationServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java
index 4c5c8a1..af1847a 100755
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -292,6 +292,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
         updateCloudIdentifier();
 
         _configDepotAdmin.populateConfigurations();
+        // setup XenServer default PV driver version
+        initiateXenServerPVDriverVersion();
 
         // We should not update seed data UUID column here since this will be invoked in upgrade case as well.
         //updateUuids();
@@ -302,6 +304,84 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
         _configDao.invalidateCache();
     }
 
+
+    private void templateDetailsInitIfNotExist(long id, String name, String value) {
+        Transaction txn = Transaction.currentTxn();
+        PreparedStatement stmt = null;
+        PreparedStatement stmtInsert = null;
+        boolean insert = false;
+        try {
+            txn.start();
+            stmt = txn.prepareAutoCloseStatement("SELECT id FROM vm_template_details WHERE template_id=? and name=?");
+            stmt.setLong(1, id);
+            stmt.setString(2, name);
+            ResultSet rs = stmt.executeQuery();
+            if(rs == null || !rs.next()) {
+                insert = true;
+            }
+            stmt.close();
+
+            if ( insert ) {
+                stmtInsert = txn.prepareAutoCloseStatement(
+                "INSERT INTO vm_template_details(template_id, name, value) VALUES(?, ?, ?)");
+                stmtInsert.setLong(1, id);
+                stmtInsert.setString(2, name);
+                stmtInsert.setString(3, value);
+                if(stmtInsert.executeUpdate() < 1) {
+                    throw new CloudRuntimeException("Unable to init template " + id + " datails: " + name);
+                }
+            }
+            txn.commit();
+        } catch (Exception e) {
+            s_logger.warn("Unable to init template " + id + " datails: " + name, e);
+            throw new CloudRuntimeException("Unable to init template " + id + " datails: " + name);
+        }
+    }
+
+    private void initiateXenServerPVDriverVersion() {
+        String pvdriverversion = Config.XenPVdriverVersion.getDefaultValue();
+        Transaction txn = Transaction.currentTxn();
+        PreparedStatement pstmt = null;
+        ResultSet rs1 = null;
+        ResultSet rs2 = null;
+        try {
+            String oldValue = _configDao.getValue(Config.XenPVdriverVersion.key());
+            if ( oldValue == null ) {
+                String sql = "select resource from host where hypervisor_type='XenServer' and removed is null and status not in ('Error', 'Removed') group by resource" ;
+                pstmt = txn.prepareAutoCloseStatement(sql);
+                rs1 = pstmt.executeQuery();
+                while (rs1.next()) {
+                    String resouce = rs1.getString(1); //resource column
+                    if ( resouce == null ) continue;
+                    if ( resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56Resource")
+                        ||  resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56FP1Resource")
+                        ||  resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer56SP2Resource")
+                        ||  resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer600Resource")
+                        ||  resouce.equalsIgnoreCase("com.cloud.hypervisor.xen.resource.XenServer602Resource") ) {
+                        pvdriverversion = "xenserver56";
+                        break;
+                    }
+                }
+                _configDao.getValueAndInitIfNotExist(Config.XenPVdriverVersion.key(),
+                    Config.XenPVdriverVersion.getCategory(), pvdriverversion, Config.XenPVdriverVersion.getDescription());
+                sql = "select id from vm_template where hypervisor_type='XenServer'  and format!='ISO' and removed is null";
+                pstmt = txn.prepareAutoCloseStatement(sql);
+                rs2 = pstmt.executeQuery();
+                List<Long> tmpl_ids = new ArrayList<Long>();
+                while (rs2.next()) {
+                    tmpl_ids.add(rs2.getLong(1));
+                }
+                for( Long tmpl_id : tmpl_ids) {
+                    templateDetailsInitIfNotExist(tmpl_id, "hypervisortoolsversion", pvdriverversion);
+                }
+            }
+        } catch (Exception e) {
+            s_logger.debug("initiateXenServerPVDriverVersion failed due to " + e.toString());
+            // ignore
+        }
+    }
+
+
     /*
     private void updateUuids() {
         _identityDao.initializeDefaultUuid("disk_offering");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/server/ManagementServerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java
index 699f469..4637da6 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -3440,7 +3440,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         // give us the same key
         if (_hashKey == null) {
             _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(),
-                    getBase64EncodedRandomKey(128));
+                    getBase64EncodedRandomKey(128), Config.HashKey.getDescription());
         }
         return _hashKey;
     }
@@ -3450,7 +3450,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         if (_encryptionKey == null) {
             _encryptionKey = _configDao.getValueAndInitIfNotExist(Config.EncryptionKey.key(),
                     Config.EncryptionKey.getCategory(),
-                    getBase64EncodedRandomKey(128));
+                    getBase64EncodedRandomKey(128), Config.EncryptionKey.getDescription());
         }
         return _encryptionKey;
     }
@@ -3460,7 +3460,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
         if (_encryptionIV == null) {
             _encryptionIV = _configDao.getValueAndInitIfNotExist(Config.EncryptionIV.key(),
                     Config.EncryptionIV.getCategory(),
-                    getBase64EncodedRandomKey(128));
+                    getBase64EncodedRandomKey(128),  Config.EncryptionIV.getDescription());
         }
         return _encryptionIV;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/template/TemplateAdapterBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java
index a0d4c77..6194e6e 100755
--- a/server/src/com/cloud/template/TemplateAdapterBase.java
+++ b/server/src/com/cloud/template/TemplateAdapterBase.java
@@ -18,6 +18,7 @@ package com.cloud.template;
 
 import java.util.List;
 import java.util.Map;
+import java.util.HashMap;
 
 import javax.inject.Inject;
 
@@ -36,6 +37,7 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
 import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
 
 import com.cloud.api.ApiDBUtils;
+import com.cloud.configuration.Config;
 import com.cloud.configuration.Resource.ResourceType;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.dao.DataCenterDao;
@@ -45,6 +47,7 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.org.Grouping;
 import com.cloud.projects.ProjectManager;
@@ -214,6 +217,20 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
             }
         }
 
+        if (hypervisorType.equals(Hypervisor.HypervisorType.XenServer) ) {
+            if(  details == null || !details.containsKey("hypervisortoolsversion")
+                    || details.get("hypervisortoolsversion") == null
+                    || ((String)details.get("hypervisortoolsversion")).equalsIgnoreCase("none") ) {
+                String hpvs = _configDao.getValue(Config.XenPVdriverVersion.key());
+                if ( hpvs != null) {
+                    if ( details == null ) {
+                        details = new HashMap<String, String>();
+                    }
+                    details.put("hypervisortoolsversion", hpvs);
+                }
+            }
+        }
+
         Long id = _tmpltDao.getNextInSequence(Long.class, "id");
         CallContext.current().setEventDetails("Id: " + id + " name: " + name);
         return new TemplateProfile(id, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, featured, isExtractable, imgfmt, guestOSId, zoneId,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 05663db..2ec033a 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -2458,7 +2458,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
     }
 
     @DB
-    protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId,
+    protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate tmplt, String hostName, String displayName, Account owner, Long diskOfferingId,
         Long diskSize, List<NetworkVO> networkList, List<Long> securityGroupIdList, String group, HTTPMethod httpmethod,
 	    String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map<Long, IpAddresses> requestedIps,
 	    IpAddresses defaultIps, Boolean isDisplayVmEnabled, String keyboard, List<Long> affinityGroupIdList)
@@ -2470,7 +2470,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
             throw new PermissionDeniedException(
                     "The owner of vm to deploy is disabled: " + owner);
         }
-
+        VMTemplateVO template = _templateDao.findById(tmplt.getId());
+        if (template != null) {
+            _templateDao.loadDetails(template);
+        }
+        
         long accountId = owner.getId();
 
         assert !(requestedIps != null && (defaultIps.getIp4Address() != null || defaultIps.getIp6Address() != null)) : "requestedIp list and defaultNetworkIp should never be specified together";
@@ -2807,7 +2811,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
         long guestOSCategoryId = guestOS.getCategoryId();
         GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId);
 
-
         // If hypervisor is vSphere and OS is OS X, set special settings.
         if (hypervisorType.equals(HypervisorType.VMware)) {
             if (guestOS.getDisplayName().toLowerCase().contains("apple mac os")){
@@ -2818,6 +2821,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
             }
        }
 
+        Map<String, String> details = template.getDetails();
+        if ( details != null && !details.isEmpty() ) {
+            vm.details.putAll(details);
+        }
+
         _vmDao.persist(vm);
         _vmDao.saveDetails(vm);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e33ae740/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java b/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
index a0110b5..0802b7a 100644
--- a/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
+++ b/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
@@ -76,11 +76,20 @@ public class MockConfigurationDaoImpl  extends GenericDaoBase<ConfigurationVO, S
      * @see com.cloud.configuration.dao.ConfigurationDao#getValueAndInitIfNotExist(java.lang.String, java.lang.String, java.lang.String)
      */
     @Override
+    public String getValueAndInitIfNotExist(String name, String category, String initValue, String desc) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    
+    /* (non-Javadoc)
+     * @see com.cloud.configuration.dao.ConfigurationDao#getValueAndInitIfNotExist(java.lang.String, java.lang.String, java.lang.String)
+     */
+    @Override
     public String getValueAndInitIfNotExist(String name, String category, String initValue) {
         // TODO Auto-generated method stub
         return null;
     }
-
+    
     /* (non-Javadoc)
      * @see com.cloud.configuration.dao.ConfigurationDao#isPremium()
      */