bug 11552:

This bug also happens in XenServer 5.6 FP1, but this issue is hidden by bug 11564.
 There are two issues here

 1.  in XenServer 5.6 FP1/SP2, when a slave host is down ( NIC is unplugged), and before master detect the slave is down( it takes about 10 minutes),
 template.createClone doesn't work sometime, it complains can not contact slave host, looks like XenServer try to start VM on this slave host, we use VM.create instead, we can specify host in VM.create API, so it will not try to connect the slave

 2.  in XenServer 5.6 FP1/SP2,  host tag is introduced into VDI, however in HA case, VM.reset_powerstate and VM.destory doesn't remove this host tag, when CloudStack try to start this VM on other host, XenServer complains this VDI is already used ( or mount as RW). CloudStack will manually remove the host tage in VDI in FenceCommand

status 11552: resolved fixed
This commit is contained in:
anthony 2011-09-28 20:34:50 -07:00
parent 59bb2e0289
commit c74f34eadd
2 changed files with 156 additions and 1 deletions

View File

@ -19,14 +19,33 @@ package com.cloud.hypervisor.xen.resource;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import com.cloud.agent.api.FenceAnswer;
import com.cloud.agent.api.FenceCommand;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.resource.ServerResource;
import com.cloud.storage.Volume;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.xensource.xenapi.Connection;
import com.xensource.xenapi.Console;
import com.xensource.xenapi.Host;
import com.xensource.xenapi.Types;
import com.xensource.xenapi.VBD;
import com.xensource.xenapi.VDI;
import com.xensource.xenapi.VM;
import com.xensource.xenapi.Types.XenAPIException;
@Local(value=ServerResource.class)
public class XenServer56FP1Resource extends XenServer56Resource {
@ -55,4 +74,140 @@ public class XenServer56FP1Resource extends XenServer56Resource {
}
@Override
protected FenceAnswer execute(FenceCommand cmd) {
Connection conn = getConnection();
try {
String result = callHostPluginPremium(conn, "check_heartbeat", "host", cmd.getHostGuid(), "interval",
Integer.toString(_heartbeatInterval * 2));
if (!result.contains("> DEAD <")) {
s_logger.debug("Heart beat is still going so unable to fence");
return new FenceAnswer(cmd, false, "Heartbeat is still going on unable to fence");
}
Set<VM> vms = VM.getByNameLabel(conn, cmd.getVmName());
for (VM vm : vms) {
Set<VDI> vdis = new HashSet<VDI>();
Set<VBD> vbds = vm.getVBDs(conn);
for( VBD vbd : vbds ) {
VDI vdi = vbd.getVDI(conn);
if( !isRefNull(vdi) ) {
vdis.add(vdi);
}
}
vm.powerStateReset(conn);
vm.destroy(conn);
for (VDI vdi : vdis) {
Map<String, String> smConfig = vdi.getSmConfig(conn);
for (String key : smConfig.keySet()) {
if (key.startsWith("host_")) {
vdi.removeFromSmConfig(conn, key);
break;
}
}
}
}
return new FenceAnswer(cmd);
} catch (XmlRpcException e) {
s_logger.warn("Unable to fence", e);
return new FenceAnswer(cmd, false, e.getMessage());
} catch (XenAPIException e) {
s_logger.warn("Unable to fence", e);
return new FenceAnswer(cmd, false, e.getMessage());
}
}
@Override
protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException {
String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD);
Set<VM> templates = VM.getByNameLabel(conn, guestOsTypeName);
assert templates.size() == 1 : "Should only have 1 template but found " + templates.size();
VM template = templates.iterator().next();
VM.Record record = template.getRecord(conn);
record.affinity = host;
record.otherConfig.remove("disks");
record.otherConfig.remove("default_template");
record.isATemplate = false;
record.nameLabel = vmSpec.getName();
record.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY;
record.actionsAfterShutdown = Types.OnNormalExit.DESTROY;
record.memoryDynamicMax = vmSpec.getMinRam();
record.memoryDynamicMin = vmSpec.getMinRam();
record.memoryStaticMax = vmSpec.getMinRam();
record.memoryStaticMin = vmSpec.getMinRam();
record.VCPUsMax = (long) vmSpec.getCpus();
record.VCPUsAtStartup = (long) vmSpec.getCpus();
record.consoles.clear();
VM vm = VM.create(conn, record);
VM.Record vmr = vm.getRecord(conn);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Created VM " + vmr.uuid + " for " + vmSpec.getName());
}
Map<String, String> vcpuParams = new HashMap<String, String>();
Integer speed = vmSpec.getSpeed();
if (speed != null) {
int cpuWeight = _maxWeight; // cpu_weight
int utilization = 0; // max CPU cap, default is unlimited
// weight based allocation
cpuWeight = (int) ((speed * 0.99) / _host.speed * _maxWeight);
if (cpuWeight > _maxWeight) {
cpuWeight = _maxWeight;
}
if (vmSpec.getLimitCpuUse()) {
utilization = (int) ((speed * 0.99) / _host.speed * 100);
}
vcpuParams.put("weight", Integer.toString(cpuWeight));
vcpuParams.put("cap", Integer.toString(utilization));
}
if (vcpuParams.size() > 0) {
vm.setVCPUsParams(conn, vcpuParams);
}
String bootArgs = vmSpec.getBootArgs();
if (bootArgs != null && bootArgs.length() > 0) {
String pvargs = vm.getPVArgs(conn);
pvargs = pvargs + vmSpec.getBootArgs();
if (s_logger.isDebugEnabled()) {
s_logger.debug("PV args are " + pvargs);
}
vm.setPVArgs(conn, pvargs);
}
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
if (vmSpec.getBootloader() == BootloaderType.CD) {
VolumeTO[] disks = vmSpec.getDisks();
for (VolumeTO disk : disks) {
if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
if (!isoGuestOsName.equals(guestOsTypeName)) {
vmSpec.setBootloader(BootloaderType.PyGrub);
}
}
}
}
if (vmSpec.getBootloader() == BootloaderType.CD) {
vm.setPVBootloader(conn, "eliloader");
if (!vm.getOtherConfig(conn).containsKey("install-repository")) {
vm.addToOtherConfig(conn, "install-repository", "cdrom");
}
} else if (vmSpec.getBootloader() == BootloaderType.PyGrub) {
vm.setPVBootloader(conn, "pygrub");
} else {
vm.destroy(conn);
throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader());
}
}
return vm;
}
}

View File

@ -30,7 +30,7 @@ import com.cloud.utils.script.Script;
@Local(value=ServerResource.class)
public class XenServer56SP2Resource extends XenServer56Resource {
public class XenServer56SP2Resource extends XenServer56FP1Resource {
private static final Logger s_logger = Logger.getLogger(XenServer56SP2Resource.class);
public XenServer56SP2Resource() {