use of com.cloud.hypervisor.kvm.resource.LibvirtVmDef.InterfaceDef in project cosmic by MissionCriticalCloud.
the class LibvirtComputingResourceTest method testPvlanSetupCommandDhcpAdd.
@Test
public void testPvlanSetupCommandDhcpAdd() {
final String op = "add";
final URI uri = URI.create("http://localhost");
final String networkTag = "/105";
final String dhcpName = "dhcp";
final String dhcpMac = "00:00:00:00";
final String dhcpIp = "127.0.0.1";
final PvlanSetupCommand command = PvlanSetupCommand.createDhcpSetup(op, uri, networkTag, dhcpName, dhcpMac, dhcpIp);
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class);
final Connect conn = Mockito.mock(Connect.class);
final String guestBridgeName = "br0";
when(libvirtComputingResource.getGuestBridgeName()).thenReturn(guestBridgeName);
final int timeout = 0;
when(libvirtComputingResource.getScriptsTimeout()).thenReturn(timeout);
final String ovsPvlanDhcpHostPath = "/pvlan";
when(libvirtComputingResource.getOvsPvlanDhcpHostPath()).thenReturn(ovsPvlanDhcpHostPath);
when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper);
final List<InterfaceDef> ifaces = new ArrayList<>();
final InterfaceDef nic = Mockito.mock(InterfaceDef.class);
ifaces.add(nic);
try {
when(libvirtUtilitiesHelper.getConnectionByVmName(dhcpName)).thenReturn(conn);
when(libvirtComputingResource.getInterfaces(conn, dhcpName)).thenReturn(ifaces);
} catch (final LibvirtException e) {
fail(e.getMessage());
}
final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance();
assertNotNull(wrapper);
final Answer answer = wrapper.execute(command, libvirtComputingResource);
assertFalse(answer.getResult());
verify(libvirtComputingResource, times(1)).getLibvirtUtilitiesHelper();
try {
verify(libvirtUtilitiesHelper, times(1)).getConnectionByVmName(dhcpName);
} catch (final LibvirtException e) {
fail(e.getMessage());
}
}
use of com.cloud.hypervisor.kvm.resource.LibvirtVmDef.InterfaceDef in project cloudstack by apache.
the class LibvirtComputingResource method prepareNetworkElementCommand.
protected ExecutionResult prepareNetworkElementCommand(final SetSourceNatCommand cmd) {
Connect conn;
final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
final IpAddressTO pubIP = cmd.getIpAddress();
try {
conn = LibvirtConnection.getConnectionByVmName(routerName);
Integer devNum = 0;
final String pubVlan = pubIP.getBroadcastUri();
final List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
for (final InterfaceDef pluggedNic : pluggedNics) {
final String pluggedVlanBr = pluggedNic.getBrName();
final String pluggedVlanId = getBroadcastUriFromBridge(pluggedVlanBr);
if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) && pluggedVlanBr.equalsIgnoreCase(_publicBridgeName)) {
break;
} else if (pluggedVlanBr.equalsIgnoreCase(_linkLocalBridgeName)) {
/*skip over, no physical bridge device exists*/
} else if (pluggedVlanId == null) {
/*this should only be true in the case of link local bridge*/
return new ExecutionResult(false, "unable to find the vlan id for bridge " + pluggedVlanBr + " when attempting to set up" + pubVlan + " on router " + routerName);
} else if (pluggedVlanId.equals(pubVlan)) {
break;
}
devNum++;
}
pubIP.setNicDevId(devNum);
return new ExecutionResult(true, "success");
} catch (final LibvirtException e) {
final String msg = "Ip SNAT failure due to " + e.toString();
s_logger.error(msg, e);
return new ExecutionResult(false, msg);
}
}
use of com.cloud.hypervisor.kvm.resource.LibvirtVmDef.InterfaceDef in project cloudstack by apache.
the class LibvirtDomainXMLParser method parseDomainXML.
public boolean parseDomainXML(String domXML) {
DocumentBuilder builder;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(domXML));
Document doc = builder.parse(is);
Element rootElement = doc.getDocumentElement();
desc = getTagValue("description", rootElement);
Element devices = (Element) rootElement.getElementsByTagName("devices").item(0);
NodeList disks = devices.getElementsByTagName("disk");
for (int i = 0; i < disks.getLength(); i++) {
Element disk = (Element) disks.item(i);
String type = disk.getAttribute("type");
DiskDef def = new DiskDef();
if (type.equalsIgnoreCase("network")) {
String diskFmtType = getAttrValue("driver", "type", disk);
String diskCacheMode = getAttrValue("driver", "cache", disk);
String diskPath = getAttrValue("source", "name", disk);
String protocol = getAttrValue("source", "protocol", disk);
String authUserName = getAttrValue("auth", "username", disk);
String poolUuid = getAttrValue("secret", "uuid", disk);
String host = getAttrValue("host", "name", disk);
int port = 0;
String xmlPort = getAttrValue("host", "port", disk);
if (StringUtils.isNotBlank(xmlPort)) {
port = Integer.parseInt(xmlPort);
}
String diskLabel = getAttrValue("target", "dev", disk);
String bus = getAttrValue("target", "bus", disk);
DiskDef.DiskFmtType fmt = null;
if (diskFmtType != null) {
fmt = DiskDef.DiskFmtType.valueOf(diskFmtType.toUpperCase());
}
def.defNetworkBasedDisk(diskPath, host, port, authUserName, poolUuid, diskLabel, DiskDef.DiskBus.valueOf(bus.toUpperCase()), DiskDef.DiskProtocol.valueOf(protocol.toUpperCase()), fmt);
def.setCacheMode(DiskDef.DiskCacheMode.valueOf(diskCacheMode.toUpperCase()));
} else {
String diskFmtType = getAttrValue("driver", "type", disk);
String diskCacheMode = getAttrValue("driver", "cache", disk);
String diskFile = getAttrValue("source", "file", disk);
String diskDev = getAttrValue("source", "dev", disk);
String diskLabel = getAttrValue("target", "dev", disk);
String bus = getAttrValue("target", "bus", disk);
String device = disk.getAttribute("device");
if (type.equalsIgnoreCase("file")) {
if (device.equalsIgnoreCase("disk")) {
DiskDef.DiskFmtType fmt = null;
if (diskFmtType != null) {
fmt = DiskDef.DiskFmtType.valueOf(diskFmtType.toUpperCase());
}
def.defFileBasedDisk(diskFile, diskLabel, DiskDef.DiskBus.valueOf(bus.toUpperCase()), fmt);
} else if (device.equalsIgnoreCase("cdrom")) {
def.defISODisk(diskFile, i + 1);
}
} else if (type.equalsIgnoreCase("block")) {
def.defBlockBasedDisk(diskDev, diskLabel, DiskDef.DiskBus.valueOf(bus.toUpperCase()));
}
if (StringUtils.isNotBlank(diskCacheMode)) {
def.setCacheMode(DiskDef.DiskCacheMode.valueOf(diskCacheMode.toUpperCase()));
}
}
NodeList iotune = disk.getElementsByTagName("iotune");
if ((iotune != null) && (iotune.getLength() != 0)) {
String bytesReadRateStr = getTagValue("read_bytes_sec", (Element) iotune.item(0));
if (bytesReadRateStr != null) {
Long bytesReadRate = Long.parseLong(bytesReadRateStr);
def.setBytesReadRate(bytesReadRate);
}
String bytesReadRateMaxStr = getTagValue("read_bytes_sec_max", (Element) iotune.item(0));
if (bytesReadRateMaxStr != null) {
Long bytesReadRateMax = Long.parseLong(bytesReadRateMaxStr);
def.setBytesReadRateMax(bytesReadRateMax);
}
String bytesReadRateMaxLengthStr = getTagValue("read_bytes_sec_max_length", (Element) iotune.item(0));
if (bytesReadRateMaxLengthStr != null) {
Long bytesReadRateMaxLength = Long.parseLong(bytesReadRateMaxLengthStr);
def.setBytesReadRateMaxLength(bytesReadRateMaxLength);
}
String bytesWriteRateStr = getTagValue("write_bytes_sec", (Element) iotune.item(0));
if (bytesWriteRateStr != null) {
Long bytesWriteRate = Long.parseLong(bytesWriteRateStr);
def.setBytesWriteRate(bytesWriteRate);
}
String bytesWriteRateMaxStr = getTagValue("write_bytes_sec_max", (Element) iotune.item(0));
if (bytesWriteRateMaxStr != null) {
Long bytesWriteRateMax = Long.parseLong(bytesWriteRateMaxStr);
def.setBytesWriteRateMax(bytesWriteRateMax);
}
String bytesWriteRateMaxLengthStr = getTagValue("write_bytes_sec_max_length", (Element) iotune.item(0));
if (bytesWriteRateMaxLengthStr != null) {
Long bytesWriteRateMaxLength = Long.parseLong(bytesWriteRateMaxLengthStr);
def.setBytesWriteRateMaxLength(bytesWriteRateMaxLength);
}
String iopsReadRateStr = getTagValue("read_iops_sec", (Element) iotune.item(0));
if (iopsReadRateStr != null) {
Long iopsReadRate = Long.parseLong(iopsReadRateStr);
def.setIopsReadRate(iopsReadRate);
}
String iopsReadRateMaxStr = getTagValue("read_iops_sec_max", (Element) iotune.item(0));
if (iopsReadRateMaxStr != null) {
Long iopsReadRateMax = Long.parseLong(iopsReadRateMaxStr);
def.setIopsReadRateMax(iopsReadRateMax);
}
String iopsReadRateMaxLengthStr = getTagValue("read_iops_sec_max_length", (Element) iotune.item(0));
if (iopsReadRateMaxLengthStr != null) {
Long iopsReadRateMaxLength = Long.parseLong(iopsReadRateMaxLengthStr);
def.setIopsReadRateMaxLength(iopsReadRateMaxLength);
}
String iopsWriteRateStr = getTagValue("write_iops_sec", (Element) iotune.item(0));
if (iopsWriteRateStr != null) {
Long iopsWriteRate = Long.parseLong(iopsWriteRateStr);
def.setIopsWriteRate(iopsWriteRate);
}
String iopsWriteRateMaxStr = getTagValue("write_iops_sec_max", (Element) iotune.item(0));
if (iopsWriteRateMaxStr != null) {
Long iopsWriteRateMax = Long.parseLong(iopsWriteRateMaxStr);
def.setIopsWriteRateMax(iopsWriteRateMax);
}
String iopsWriteRateMaxLengthStr = getTagValue("write_iops_sec_max_length", (Element) iotune.item(0));
if (iopsWriteRateMaxLengthStr != null) {
Long iopsWriteRateMaxLength = Long.parseLong(iopsWriteRateMaxLengthStr);
def.setIopsWriteRateMaxLength(iopsWriteRateMaxLength);
}
}
diskDefs.add(def);
}
NodeList nics = devices.getElementsByTagName("interface");
for (int i = 0; i < nics.getLength(); i++) {
Element nic = (Element) nics.item(i);
String type = nic.getAttribute("type");
String mac = getAttrValue("mac", "address", nic);
String dev = getAttrValue("target", "dev", nic);
String model = getAttrValue("model", "type", nic);
String slot = StringUtils.removeStart(getAttrValue("address", "slot", nic), "0x");
InterfaceDef def = new InterfaceDef();
NodeList bandwidth = nic.getElementsByTagName("bandwidth");
Integer networkRateKBps = 0;
if ((bandwidth != null) && (bandwidth.getLength() != 0)) {
Integer inbound = Integer.valueOf(getAttrValue("inbound", "average", (Element) bandwidth.item(0)));
Integer outbound = Integer.valueOf(getAttrValue("outbound", "average", (Element) bandwidth.item(0)));
if (inbound.equals(outbound)) {
networkRateKBps = inbound;
}
}
if (type.equalsIgnoreCase("network")) {
String network = getAttrValue("source", "network", nic);
def.defPrivateNet(network, dev, mac, NicModel.valueOf(model.toUpperCase()), networkRateKBps);
} else if (type.equalsIgnoreCase("bridge")) {
String bridge = getAttrValue("source", "bridge", nic);
def.defBridgeNet(bridge, dev, mac, NicModel.valueOf(model.toUpperCase()), networkRateKBps);
} else if (type.equalsIgnoreCase("ethernet")) {
String scriptPath = getAttrValue("script", "path", nic);
def.defEthernet(dev, mac, NicModel.valueOf(model.toUpperCase()), scriptPath, networkRateKBps);
} else if (type.equals("vhostuser")) {
String sourcePort = getAttrValue("source", "path", nic);
String mode = getAttrValue("source", "mode", nic);
int lastSlashIndex = sourcePort.lastIndexOf("/");
String ovsPath = sourcePort.substring(0, lastSlashIndex);
String port = sourcePort.substring(lastSlashIndex + 1);
def.setDpdkSourcePort(port);
def.setDpdkOvsPath(ovsPath);
def.setInterfaceMode(mode);
}
if (StringUtils.isNotBlank(slot)) {
def.setSlot(Integer.parseInt(slot, 16));
}
interfaces.add(def);
}
NodeList ports = devices.getElementsByTagName("channel");
for (int i = 0; i < ports.getLength(); i++) {
Element channel = (Element) ports.item(i);
String type = channel.getAttribute("type");
String path = getAttrValue("source", "path", channel);
String name = getAttrValue("target", "name", channel);
String state = getAttrValue("target", "state", channel);
ChannelDef def = null;
if (StringUtils.isBlank(state)) {
def = new ChannelDef(name, ChannelDef.ChannelType.valueOf(type.toUpperCase()), new File(path));
} else {
def = new ChannelDef(name, ChannelDef.ChannelType.valueOf(type.toUpperCase()), ChannelDef.ChannelState.valueOf(state.toUpperCase()), new File(path));
}
channels.add(def);
}
Element graphic = (Element) devices.getElementsByTagName("graphics").item(0);
if (graphic != null) {
String port = graphic.getAttribute("port");
if (port != null) {
try {
vncPort = Integer.parseInt(port);
if (vncPort != -1) {
vncPort = vncPort - 5900;
} else {
vncPort = null;
}
} catch (NumberFormatException nfe) {
vncPort = null;
}
}
}
NodeList rngs = devices.getElementsByTagName("rng");
for (int i = 0; i < rngs.getLength(); i++) {
RngDef def = null;
Element rng = (Element) rngs.item(i);
String backendModel = getAttrValue("backend", "model", rng);
String path = getTagValue("backend", rng);
String bytes = getAttrValue("rate", "bytes", rng);
String period = getAttrValue("rate", "period", rng);
if (StringUtils.isEmpty(backendModel)) {
def = new RngDef(path, Integer.parseInt(bytes), Integer.parseInt(period));
} else {
def = new RngDef(path, RngBackendModel.valueOf(backendModel.toUpperCase()), Integer.parseInt(bytes), Integer.parseInt(period));
}
rngDefs.add(def);
}
NodeList watchDogs = devices.getElementsByTagName("watchdog");
for (int i = 0; i < watchDogs.getLength(); i++) {
WatchDogDef def = null;
Element watchDog = (Element) watchDogs.item(i);
String action = watchDog.getAttribute("action");
String model = watchDog.getAttribute("model");
if (StringUtils.isEmpty(model)) {
continue;
}
if (StringUtils.isEmpty(action)) {
def = new WatchDogDef(WatchDogModel.valueOf(model.toUpperCase()));
} else {
def = new WatchDogDef(WatchDogAction.valueOf(action.toUpperCase()), WatchDogModel.valueOf(model.toUpperCase()));
}
watchDogDefs.add(def);
}
return true;
} catch (ParserConfigurationException e) {
s_logger.debug(e.toString());
} catch (SAXException e) {
s_logger.debug(e.toString());
} catch (IOException e) {
s_logger.debug(e.toString());
}
return false;
}
use of com.cloud.hypervisor.kvm.resource.LibvirtVmDef.InterfaceDef in project cloudstack by apache.
the class LibvirtComputingResource method getVmStat.
public VmStatsEntry getVmStat(final Connect conn, final String vmName) throws LibvirtException {
Domain dm = null;
try {
dm = getDomain(conn, vmName);
if (dm == null) {
return null;
}
DomainInfo info = dm.getInfo();
final VmStatsEntry stats = new VmStatsEntry();
stats.setNumCPUs(info.nrVirtCpu);
stats.setEntityType("vm");
stats.setMemoryKBs(info.maxMem);
stats.setTargetMemoryKBs(info.memory);
stats.setIntFreeMemoryKBs(getMemoryFreeInKBs(dm));
/* get cpu utilization */
VmStats oldStats = null;
final Calendar now = Calendar.getInstance();
oldStats = _vmStats.get(vmName);
long elapsedTime = 0;
if (oldStats != null) {
elapsedTime = now.getTimeInMillis() - oldStats._timestamp.getTimeInMillis();
double utilization = (info.cpuTime - oldStats._usedTime) / ((double) elapsedTime * 1000000);
utilization = utilization / info.nrVirtCpu;
if (utilization > 0) {
stats.setCPUUtilization(utilization * 100);
}
}
/* get network stats */
final List<InterfaceDef> vifs = getInterfaces(conn, vmName);
long rx = 0;
long tx = 0;
for (final InterfaceDef vif : vifs) {
final DomainInterfaceStats ifStats = dm.interfaceStats(vif.getDevName());
rx += ifStats.rx_bytes;
tx += ifStats.tx_bytes;
}
if (oldStats != null) {
final double deltarx = rx - oldStats._rx;
if (deltarx > 0) {
stats.setNetworkReadKBs(deltarx / 1024);
}
final double deltatx = tx - oldStats._tx;
if (deltatx > 0) {
stats.setNetworkWriteKBs(deltatx / 1024);
}
}
/* get disk stats */
final List<DiskDef> disks = getDisks(conn, vmName);
long io_rd = 0;
long io_wr = 0;
long bytes_rd = 0;
long bytes_wr = 0;
for (final DiskDef disk : disks) {
if (disk.getDeviceType() == DeviceType.CDROM || disk.getDeviceType() == DeviceType.FLOPPY) {
continue;
}
final DomainBlockStats blockStats = dm.blockStats(disk.getDiskLabel());
io_rd += blockStats.rd_req;
io_wr += blockStats.wr_req;
bytes_rd += blockStats.rd_bytes;
bytes_wr += blockStats.wr_bytes;
}
if (oldStats != null) {
final long deltaiord = io_rd - oldStats._ioRead;
if (deltaiord > 0) {
stats.setDiskReadIOs(deltaiord);
}
final long deltaiowr = io_wr - oldStats._ioWrote;
if (deltaiowr > 0) {
stats.setDiskWriteIOs(deltaiowr);
}
final double deltabytesrd = bytes_rd - oldStats._bytesRead;
if (deltabytesrd > 0) {
stats.setDiskReadKBs(deltabytesrd / 1024);
}
final double deltabyteswr = bytes_wr - oldStats._bytesWrote;
if (deltabyteswr > 0) {
stats.setDiskWriteKBs(deltabyteswr / 1024);
}
}
/* save to Hashmap */
final VmStats newStat = new VmStats();
newStat._usedTime = info.cpuTime;
newStat._rx = rx;
newStat._tx = tx;
newStat._ioRead = io_rd;
newStat._ioWrote = io_wr;
newStat._bytesRead = bytes_rd;
newStat._bytesWrote = bytes_wr;
newStat._timestamp = now;
_vmStats.put(vmName, newStat);
return stats;
} finally {
if (dm != null) {
dm.free();
}
}
}
use of com.cloud.hypervisor.kvm.resource.LibvirtVmDef.InterfaceDef in project cloudstack by apache.
the class LibvirtMigrateCommandWrapper method execute.
@Override
public Answer execute(final MigrateCommand command, final LibvirtComputingResource libvirtComputingResource) {
final String vmName = command.getVmName();
final Map<String, Boolean> vlanToPersistenceMap = command.getVlanToPersistenceMap();
final String destinationUri = createMigrationURI(command.getDestinationIp(), libvirtComputingResource);
final List<MigrateDiskInfo> migrateDiskInfoList = command.getMigrateDiskInfoList();
String result = null;
List<InterfaceDef> ifaces = null;
List<DiskDef> disks;
Domain dm = null;
Connect dconn = null;
Domain destDomain = null;
Connect conn = null;
String xmlDesc = null;
List<Ternary<String, Boolean, String>> vmsnapshots = null;
try {
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
ifaces = libvirtComputingResource.getInterfaces(conn, vmName);
disks = libvirtComputingResource.getDisks(conn, vmName);
VirtualMachineTO to = command.getVirtualMachine();
dm = conn.domainLookupByName(vmName);
/*
We replace the private IP address with the address of the destination host.
This is because the VNC listens on the private IP address of the hypervisor,
but that address is of course different on the target host.
MigrateCommand.getDestinationIp() returns the private IP address of the target
hypervisor. So it's safe to use.
The Domain.migrate method from libvirt supports passing a different XML
description for the instance to be used on the target host.
This is supported by libvirt-java from version 0.50.0
CVE-2015-3252: Get XML with sensitive information suitable for migration by using
VIR_DOMAIN_XML_MIGRATABLE flag (value = 8)
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainXMLFlags
Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0.
*/
// 1000000 equals v1.0.0
final int xmlFlag = conn.getLibVirVersion() >= 1000000 ? 8 : 1;
final String target = command.getDestinationIp();
xmlDesc = dm.getXMLDesc(xmlFlag);
xmlDesc = replaceIpForVNCInDescFile(xmlDesc, target);
String oldIsoVolumePath = getOldVolumePath(disks, vmName);
String newIsoVolumePath = getNewVolumePathIfDatastoreHasChanged(libvirtComputingResource, conn, to);
if (newIsoVolumePath != null && !newIsoVolumePath.equals(oldIsoVolumePath)) {
s_logger.debug("Editing mount path");
xmlDesc = replaceDiskSourceFile(xmlDesc, newIsoVolumePath, vmName);
}
// delete the metadata of vm snapshots before migration
vmsnapshots = libvirtComputingResource.cleanVMSnapshotMetadata(dm);
// Verify Format of backing file
for (DiskDef disk : disks) {
if (disk.getDeviceType() == DiskDef.DeviceType.DISK && disk.getDiskFormatType() == DiskDef.DiskFmtType.QCOW2) {
libvirtComputingResource.setBackingFileFormat(disk.getDiskPath());
}
}
Map<String, MigrateCommand.MigrateDiskInfo> mapMigrateStorage = command.getMigrateStorage();
// migrateStorage is declared as final because the replaceStorage method may mutate mapMigrateStorage, but
// migrateStorage's value should always only be associated with the initial state of mapMigrateStorage.
final boolean migrateStorage = MapUtils.isNotEmpty(mapMigrateStorage);
final boolean migrateStorageManaged = command.isMigrateStorageManaged();
if (migrateStorage) {
xmlDesc = replaceStorage(xmlDesc, mapMigrateStorage, migrateStorageManaged);
}
Map<String, DpdkTO> dpdkPortsMapping = command.getDpdkInterfaceMapping();
if (MapUtils.isNotEmpty(dpdkPortsMapping)) {
xmlDesc = replaceDpdkInterfaces(xmlDesc, dpdkPortsMapping);
}
dconn = libvirtUtilitiesHelper.retrieveQemuConnection(destinationUri);
if (to.getType() == VirtualMachine.Type.User) {
libvirtComputingResource.detachAndAttachConfigDriveISO(conn, vmName);
}
// run migration in thread so we can monitor it
s_logger.info("Live migration of instance " + vmName + " initiated to destination host: " + dconn.getURI());
final ExecutorService executor = Executors.newFixedThreadPool(1);
boolean migrateNonSharedInc = command.isMigrateNonSharedInc() && !migrateStorageManaged;
final Callable<Domain> worker = new MigrateKVMAsync(libvirtComputingResource, dm, dconn, xmlDesc, migrateStorage, migrateNonSharedInc, command.isAutoConvergence(), vmName, command.getDestinationIp());
final Future<Domain> migrateThread = executor.submit(worker);
executor.shutdown();
long sleeptime = 0;
while (!executor.isTerminated()) {
Thread.sleep(100);
sleeptime += 100;
if (sleeptime == 1000) {
// wait 1s before attempting to set downtime on migration, since I don't know of a VIR_DOMAIN_MIGRATING state
final int migrateDowntime = libvirtComputingResource.getMigrateDowntime();
if (migrateDowntime > 0) {
try {
final int setDowntime = dm.migrateSetMaxDowntime(migrateDowntime);
if (setDowntime == 0) {
s_logger.debug("Set max downtime for migration of " + vmName + " to " + String.valueOf(migrateDowntime) + "ms");
}
} catch (final LibvirtException e) {
s_logger.debug("Failed to set max downtime for migration, perhaps migration completed? Error: " + e.getMessage());
}
}
}
if (sleeptime % 1000 == 0) {
s_logger.info("Waiting for migration of " + vmName + " to complete, waited " + sleeptime + "ms");
}
// abort the vm migration if the job is executed more than vm.migrate.wait
final int migrateWait = libvirtComputingResource.getMigrateWait();
if (migrateWait > 0 && sleeptime > migrateWait * 1000) {
DomainState state = null;
try {
state = dm.getInfo().state;
} catch (final LibvirtException e) {
s_logger.info("Couldn't get VM domain state after " + sleeptime + "ms: " + e.getMessage());
}
if (state != null && state == DomainState.VIR_DOMAIN_RUNNING) {
try {
DomainJobInfo job = dm.getJobInfo();
s_logger.info("Aborting " + vmName + " domain job: " + job);
dm.abortJob();
result = String.format("Migration of VM %s was cancelled by cloudstack due to time out after %d seconds", vmName, migrateWait);
s_logger.debug(result);
break;
} catch (final LibvirtException e) {
s_logger.info("Failed to abort the vm migration job of vm " + vmName + " : " + e.getMessage());
}
}
}
// pause vm if we meet the vm.migrate.pauseafter threshold and not already paused
final int migratePauseAfter = libvirtComputingResource.getMigratePauseAfter();
if (migratePauseAfter > 0 && sleeptime > migratePauseAfter) {
DomainState state = null;
try {
state = dm.getInfo().state;
} catch (final LibvirtException e) {
s_logger.info("Couldn't get VM domain state after " + sleeptime + "ms: " + e.getMessage());
}
if (state != null && state == DomainState.VIR_DOMAIN_RUNNING) {
try {
s_logger.info("Pausing VM " + vmName + " due to property vm.migrate.pauseafter setting to " + migratePauseAfter + "ms to complete migration");
dm.suspend();
} catch (final LibvirtException e) {
// pause could be racy if it attempts to pause right when vm is finished, simply warn
s_logger.info("Failed to pause vm " + vmName + " : " + e.getMessage());
}
}
}
}
s_logger.info("Migration thread for " + vmName + " is done");
destDomain = migrateThread.get(AgentPropertiesFileHandler.getPropertyValue(AgentProperties.VM_MIGRATE_DOMAIN_RETRIEVE_TIMEOUT), TimeUnit.SECONDS);
if (destDomain != null) {
deleteOrDisconnectDisksOnSourcePool(libvirtComputingResource, migrateDiskInfoList, disks);
}
} catch (final LibvirtException e) {
s_logger.debug("Can't migrate domain: " + e.getMessage());
result = e.getMessage();
if (result.startsWith("unable to connect to server") && result.endsWith("refused")) {
result = String.format("Migration was refused connection to destination: %s. Please check libvirt configuration compatibility and firewall rules on the source and destination hosts.", destinationUri);
}
} catch (final InterruptedException | ExecutionException | TimeoutException | IOException | ParserConfigurationException | SAXException | TransformerException | URISyntaxException e) {
s_logger.debug(String.format("%s : %s", e.getClass().getSimpleName(), e.getMessage()));
if (result == null) {
result = "Exception during migrate: " + e.getMessage();
}
} finally {
try {
if (dm != null && result != null) {
// restore vm snapshots in case of failed migration
if (vmsnapshots != null) {
libvirtComputingResource.restoreVMSnapshotMetadata(dm, vmName, vmsnapshots);
}
}
if (dm != null) {
if (dm.isPersistent() == 1) {
dm.undefine();
}
dm.free();
}
if (dconn != null) {
dconn.close();
}
if (destDomain != null) {
destDomain.free();
}
} catch (final LibvirtException e) {
s_logger.trace("Ignoring libvirt error.", e);
}
}
if (result != null) {
} else {
libvirtComputingResource.destroyNetworkRulesForVM(conn, vmName);
for (final InterfaceDef iface : ifaces) {
String vlanId = libvirtComputingResource.getVlanIdFromBridgeName(iface.getBrName());
// We don't know which "traffic type" is associated with
// each interface at this point, so inform all vif drivers
final List<VifDriver> allVifDrivers = libvirtComputingResource.getAllVifDrivers();
for (final VifDriver vifDriver : allVifDrivers) {
vifDriver.unplug(iface, libvirtComputingResource.shouldDeleteBridge(vlanToPersistenceMap, vlanId));
}
}
}
return new MigrateAnswer(command, result == null, result, null);
}
Aggregations