From 033d05fa2076b5cf72f3942b4e8a9a1ff685842f Mon Sep 17 00:00:00 2001 From: Devdeep Singh Date: Wed, 10 Jul 2013 17:36:06 +0530 Subject: [PATCH] CLOUDSTACK-3443: Timeoffset on windows guest not persisted between VM stop and start on XenServer. The problem was because in cloudstack when a vm is stopped it gets destroyed on the host. For a windows vm the timeoffset (which can be set by changing the timezone from within the vm) is stored in the platform:timeoffset attribute of vm record. The information is lost when the vm is destroted. Made change to read and persist the platform:timeoffset vm attribute when an instance is stopped. The value is persisted in the user_vm_details table. When the vm is started again the attribute is set for the vm instance that gets created. --- core/src/com/cloud/agent/api/StopAnswer.java | 13 ++++++++++++- .../hypervisor/xen/resource/CitrixResourceBase.java | 12 +++++++++++- .../xen/resource/XenServer56FP1Resource.java | 7 +++++++ .../src/com/cloud/vm/VirtualMachineManagerImpl.java | 10 ++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/core/src/com/cloud/agent/api/StopAnswer.java b/core/src/com/cloud/agent/api/StopAnswer.java index 1111fed1375..0af23853da5 100755 --- a/core/src/com/cloud/agent/api/StopAnswer.java +++ b/core/src/com/cloud/agent/api/StopAnswer.java @@ -18,19 +18,27 @@ package com.cloud.agent.api; public class StopAnswer extends RebootAnswer { Integer vncPort; + Integer timeOffset; protected StopAnswer() { } + public StopAnswer(StopCommand cmd, String details, Integer vncPort, Integer timeOffset, boolean success) { + super(cmd, details, success); + this.vncPort = vncPort; + this.timeOffset = timeOffset; + } + public StopAnswer(StopCommand cmd, String details, Integer vncPort, boolean success) { super(cmd, details, success); this.vncPort = vncPort; + 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) { @@ -42,4 +50,7 @@ public class StopAnswer extends RebootAnswer { return vncPort; } + public Integer getTimeOffset() { + return timeOffset; + } } 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 1f4b4342f5c..d6d05232289 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 @@ -4112,6 +4112,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe try { if (vm.getPowerState(conn) == VmPowerState.HALTED) { + Map platform = vm.getPlatform(conn); + Integer timeoffset = null; + try { + if (platform.containsKey("timeoffset")) { + timeoffset = Integer.valueOf(platform.get("timeoffset")); + } + } catch (NumberFormatException e) { + s_logger.error("Error while reading the platform:timeoffset field of the instance", e); + } + Set vifs = vm.getVIFs(conn); List networks = new ArrayList(); for (VIF vif : vifs) { @@ -4132,7 +4142,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // network might be destroyed by other host } } - return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, true); + return new StopAnswer(cmd, "Stop VM " + vmName + " Succeed", 0, timeoffset, true); } } catch (XenAPIException e) { String msg = "VM destroy failed in Stop " + vmName + " Command due to " + e.toString(); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index 407f069b909..2cc592debe7 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -193,6 +193,13 @@ public class XenServer56FP1Resource extends XenServer56Resource { vmr.VCPUsMax = 32L; } + String timeoffset = details.get("timeoffset"); + if (timeoffset != null) { + Map platform = vmr.platform; + platform.put("timeoffset", timeoffset); + vmr.platform = platform; + } + vmr.VCPUsAtStartup = (long) vmSpec.getCpus(); vmr.consoles.clear(); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 30ee2d70d6c..cddd32e5770 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1184,6 +1184,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac stopped = answer.getResult(); if (!stopped) { throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails()); + } else { + Integer timeoffset = answer.getTimeOffset(); + if (timeoffset != null) { + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + _userVmDao.loadDetails(userVm); + userVm.setDetail("timeoffset", timeoffset.toString()); + _userVmDao.saveDetails(userVm); + } + } } vmGuru.finalizeStop(profile, answer);