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/22 01:13:26 UTC

git commit: updated refs/heads/4.2 to 9a27690

Updated Branches:
  refs/heads/4.2 e6384be8e -> 9a2769009


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/9a276900
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/9a276900
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/9a276900

Branch: refs/heads/4.2
Commit: 9a27690093473a3e2f5c33c0e3e67be3af55fbf2
Parents: e6384be
Author: Anthony Xu <an...@citrix.com>
Authored: Mon Oct 21 16:10:07 2013 -0700
Committer: Anthony Xu <an...@citrix.com>
Committed: Mon Oct 21 16:10:07 2013 -0700

----------------------------------------------------------------------
 .../com/cloud/agent/api/ClusterSyncAnswer.java  |  8 +-
 .../cloud/agent/api/StartupRoutingCommand.java  |  8 +-
 core/src/com/cloud/agent/api/StopAnswer.java    | 23 +++--
 .../configuration/dao/ConfigurationDao.java     |  2 +
 .../configuration/dao/ConfigurationDaoImpl.java |  9 +-
 .../com/cloud/storage/dao/VMTemplateDao.java    |  3 +
 .../cloud/storage/dao/VMTemplateDaoImpl.java    | 17 ++++
 .../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        | 90 +++++++++++++-------
 .../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   | 81 ++++++++++++++++++
 .../com/cloud/server/ManagementServerImpl.java  |  6 +-
 .../com/cloud/template/TemplateAdapterBase.java | 16 ++++
 .../com/cloud/template/TemplateManagerImpl.java |  1 +
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  6 +-
 .../com/cloud/vm/VirtualMachineManagerImpl.java | 78 +++++++++++++----
 .../cloud/vpc/dao/MockConfigurationDaoImpl.java | 11 ++-
 26 files changed, 344 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9a276900/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/9a276900/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/9a276900/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/9a276900/engine/schema/src/com/cloud/configuration/dao/ConfigurationDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/configuration/dao/ConfigurationDao.java b/engine/schema/src/com/cloud/configuration/dao/ConfigurationDao.java
index 2b09901..343bbb4 100644
--- a/engine/schema/src/com/cloud/configuration/dao/ConfigurationDao.java
+++ b/engine/schema/src/com/cloud/configuration/dao/ConfigurationDao.java
@@ -54,6 +54,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/9a276900/engine/schema/src/com/cloud/configuration/dao/ConfigurationDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/configuration/dao/ConfigurationDaoImpl.java b/engine/schema/src/com/cloud/configuration/dao/ConfigurationDaoImpl.java
index dadeb78..1f32032 100644
--- a/engine/schema/src/com/cloud/configuration/dao/ConfigurationDaoImpl.java
+++ b/engine/schema/src/com/cloud/configuration/dao/ConfigurationDaoImpl.java
@@ -169,8 +169,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);
@@ -184,7 +189,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/9a276900/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/9a276900/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 7abb58c..de34a73 100755
--- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -411,6 +411,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/9a276900/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 f4e4463..d84096e 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
@@ -509,7 +509,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/9a276900/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 97aa597..b1de827 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
@@ -3275,7 +3275,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/9a276900/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 59ba001..e515783 100755
--- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
+++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
@@ -731,7 +731,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);    
@@ -739,7 +739,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/9a276900/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/9a276900/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/9a276900/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 8ee2b10..4921925 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
@@ -3905,11 +3905,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;
@@ -3917,7 +3917,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);
@@ -3930,7 +3930,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/9a276900/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 f6ffa69..b9adc21 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;
@@ -1350,8 +1350,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;
@@ -2877,8 +2887,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 {
@@ -2908,6 +2918,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 {
@@ -2919,7 +2930,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));
             }
         }
 
@@ -3949,7 +3960,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);
@@ -4006,6 +4017,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>();
@@ -4027,7 +4039,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();
@@ -4059,6 +4071,13 @@ 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 {
@@ -4923,7 +4942,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) {
@@ -7104,7 +7123,6 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                     }
 
                 }
-
                 success = true;
                 details = null;
             } else if (cmd.getCommandSwitch().equals(ManageSnapshotCommand.DESTROY_SNAPSHOT)) {
@@ -7124,7 +7142,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);
     }
 
@@ -8049,12 +8066,12 @@ 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, 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);
         }
@@ -8067,12 +8084,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()) {
@@ -8088,38 +8106,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);
                 }
@@ -8133,42 +8163,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();
@@ -8190,7 +8220,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/9a276900/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/9a276900/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/9a276900/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/9a276900/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 72fe5dd..cefcdd5 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -284,6 +284,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/9a276900/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 73e04f8..b1cc94b 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -120,14 +120,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/9a276900/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 febb6d2..10364ba 100755
--- a/server/src/com/cloud/server/ConfigurationServerImpl.java
+++ b/server/src/com/cloud/server/ConfigurationServerImpl.java
@@ -300,6 +300,9 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio
         // Update the cloud identifier
         updateCloudIdentifier();
 
+        // 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();
         // Set init to true
@@ -309,6 +312,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/9a276900/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 00c534b..f4545dd 100755
--- a/server/src/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/com/cloud/server/ManagementServerImpl.java
@@ -3478,7 +3478,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;
     }
@@ -3488,7 +3488,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;
     }
@@ -3498,7 +3498,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/9a276900/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 73f159a..6a1a6a0 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;
 
@@ -44,6 +45,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 +216,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");
         UserContext.current().setEventDetails("Id: " +id+ " name: " + name);
         return new TemplateProfile(id, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9a276900/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index f511da2..dff0b3f 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -1121,6 +1121,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
     public VirtualMachineTemplate getTemplate(long templateId) {
         VMTemplateVO template = _tmpltDao.findById(templateId);
         if (template != null && template.getRemoved() == null) {
+            _tmpltDao.loadDetails(template);
             return template;
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9a276900/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 41ad50c..2a4d4bd 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -2853,7 +2853,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
         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")){
@@ -2864,6 +2863,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
             }
        }
 
+        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/9a276900/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 31a45e6..da1fa77 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -946,6 +946,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
                             StopCommand cmd = new StopCommand(vm, _mgmtServer.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);
@@ -1050,7 +1060,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         VMInstanceVO vm = profile.getVirtualMachine();
         StopCommand stop = new StopCommand(vm, _mgmtServer.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;
@@ -1238,6 +1257,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());
@@ -2131,7 +2160,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
 
 
-    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()) {
@@ -2167,7 +2196,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     }
 
 
-    public void fullSync(final long clusterId, Map<String, Pair<String, State>> newStates) {
+    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>());
@@ -2301,7 +2330,7 @@ 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;
@@ -2309,26 +2338,29 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         Collection<VirtualMachineGuru<? extends VMInstanceVO>> vmGurus = _vmGurus.values();
         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;
             for (VirtualMachineGuru<? extends VMInstanceVO> vmGuru : vmGurus) {
                 String name = entry.getKey();
                 VMInstanceVO vm = vmGuru.findByName(name);
                 if (vm != null) {
-                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(), entry.getValue().first()));
+                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().second(),
+                    		entry.getValue().first(), entry.getValue().third()));
                     is_alien_vm = false;
                     break;
                 }
                 Long id = vmGuru.convertToId(name);
                 if (id != null) {
-                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), entry.getValue().first()));
+                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null, entry.getValue().second(), 
+                    		entry.getValue().first(), entry.getValue().third()));
                     is_alien_vm = false;
                     break;
                 }
             }
             // alien VMs
             if (is_alien_vm){
-                map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(), entry.getValue().first()));
+                map.put(alien_vm_count--, new AgentVmInfo(entry.getKey(), null, null, entry.getValue().second(),
+                		entry.getValue().first(), entry.getValue().third()));
                 s_logger.warn("Found an alien VM " + entry.getKey());
             }
         }
@@ -2348,12 +2380,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                 String name = entry.getKey();
                 VMInstanceVO vm = vmGuru.findByName(name);
                 if (vm != null) {
-                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().getState(), entry.getValue().getHost() ));
+                    map.put(vm.getId(), new AgentVmInfo(entry.getKey(), vmGuru, vm, entry.getValue().getState(),
+                    		entry.getValue().getHost()));
                     break;
                 }
                 Long id = vmGuru.convertToId(name);
                 if (id != null) {
-                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(), entry.getValue().getHost() ));
+                    map.put(id, new AgentVmInfo(entry.getKey(), vmGuru, null,entry.getValue().getState(),
+                    		entry.getValue().getHost()));
                     break;
                 }
             }
@@ -2715,7 +2749,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
 
         if (agent.getHypervisorType() == HypervisorType.XenServer) { // only for Xen
             StartupRoutingCommand startup = (StartupRoutingCommand) cmd;
-            HashMap<String, Pair<String, State>> allStates = startup.getClusterVMStateChanges();
+            HashMap<String, Ternary<String, State, String>> allStates = startup.getClusterVMStateChanges();
             if (allStates != null){
                 fullSync(clusterId, allStates);
             }
@@ -2796,25 +2830,37 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
         public String name;
         public State state;
         public String hostUuid;
-        public VMInstanceVO vm;
+        public String hvtoolsversion;
+
+		public VMInstanceVO vm;
         public VirtualMachineGuru<VMInstanceVO> guru;
 
         @SuppressWarnings("unchecked")
-        public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state, String host) {
+        public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state, String host, String hvtoolsversion) {
             this.name = name;
             this.state = state;
             this.vm = vm;
             this.guru = (VirtualMachineGuru<VMInstanceVO>) guru;
-            hostUuid = host;
+            this.hostUuid = host;
+            this.hvtoolsversion= hvtoolsversion;
+            
         }
-
+        
+        public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state, String host) {
+        	this(name, guru, vm, state, host, null);           
+        }
+        
         public AgentVmInfo(String name, VirtualMachineGuru<? extends VMInstanceVO> guru, VMInstanceVO vm, State state) {
-            this(name, guru, vm, state, null);
+            this(name, guru, 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/9a276900/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 4322c32..244b9fe 100644
--- a/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
+++ b/server/test/com/cloud/vpc/dao/MockConfigurationDaoImpl.java
@@ -75,11 +75,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()
      */