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
This commit is contained in:
Anthony Xu 2013-10-21 16:10:07 -07:00
parent aca6c420b4
commit e33ae74067
25 changed files with 368 additions and 109 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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() {

View File

@ -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

View File

@ -76,4 +76,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long> {
List<VMTemplateVO> findTemplatesToSyncToS3();
void loadDetails(VMTemplateVO tmpl);
void saveDetails(VMTemplateVO tmpl);
}

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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) {

View File

@ -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));
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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(",");
}

View File

@ -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

View File

@ -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),

View File

@ -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)

View File

@ -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");

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -72,6 +72,15 @@ public class MockConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, S
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, 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)
*/
@ -80,7 +89,7 @@ public class MockConfigurationDaoImpl extends GenericDaoBase<ConfigurationVO, S
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see com.cloud.configuration.dao.ConfigurationDao#isPremium()
*/