Search in sources :

Example 11 with LibvirtDiskDef

use of com.cloud.agent.resource.kvm.xml.LibvirtDiskDef in project cosmic by MissionCriticalCloud.

the class LibvirtStopCommandWrapper method execute.

@Override
public Answer execute(final StopCommand command, final LibvirtComputingResource libvirtComputingResource) {
    final String vmName = command.getVmName();
    final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
    if (command.checkBeforeCleanup()) {
        try {
            final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
            final Domain vm = conn.domainLookupByName(command.getVmName());
            if (vm != null && vm.getInfo().state == DomainState.VIR_DOMAIN_RUNNING) {
                return new StopAnswer(command, "vm is still running on host", false);
            }
        } catch (final Exception e) {
            s_logger.debug("Failed to get vm status in case of checkboforecleanup is true", e);
        }
    }
    try {
        final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
        final List<LibvirtDiskDef> disks = libvirtComputingResource.getDisks(conn, vmName);
        final List<LibvirtVmDef.InterfaceDef> ifaces = libvirtComputingResource.getInterfaces(conn, vmName);
        final String result = libvirtComputingResource.stopVm(conn, vmName, command.isForceStop());
        if (result == null) {
            for (final LibvirtDiskDef disk : disks) {
                libvirtComputingResource.cleanupDisk(disk);
            }
            for (final LibvirtVmDef.InterfaceDef iface : ifaces) {
                // each interface at this point, so inform all vif drivers
                for (final VifDriver vifDriver : libvirtComputingResource.getAllVifDrivers()) {
                    vifDriver.unplug(iface);
                }
            }
        }
        return new StopAnswer(command, result, true);
    } catch (final LibvirtException e) {
        return new StopAnswer(command, e.getMessage(), false);
    }
}
Also used : LibvirtVmDef(com.cloud.agent.resource.kvm.xml.LibvirtVmDef) LibvirtException(org.libvirt.LibvirtException) Connect(org.libvirt.Connect) LibvirtException(org.libvirt.LibvirtException) VifDriver(com.cloud.agent.resource.kvm.vif.VifDriver) LibvirtDiskDef(com.cloud.agent.resource.kvm.xml.LibvirtDiskDef) Domain(org.libvirt.Domain) StopAnswer(com.cloud.legacymodel.communication.answer.StopAnswer)

Example 12 with LibvirtDiskDef

use of com.cloud.agent.resource.kvm.xml.LibvirtDiskDef in project cosmic by MissionCriticalCloud.

the class LibvirtMigrateVolumeCommandWrapper method execute.

@Override
public Answer execute(final MigrateVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
    String result = null;
    final String vmName = command.getAttachedVmName();
    LibvirtDiskDef disk = null;
    final List<LibvirtDiskDef> disks;
    boolean isMigrationSuccessfull = false;
    Domain dm = null;
    Connect conn = null;
    String currentVolumePath = null;
    final String newVolumePath;
    final CountDownLatch completeSignal = new CountDownLatch(1);
    final BlockJobListener blockJobListener = new BlockJobListener() {

        @Override
        public void onBlockJobCompleted(final Domain domain, final String disk, final int type) throws LibvirtException {
            onBlockJobReady(domain, disk, type);
        }

        @Override
        public void onBlockJobFailed(final Domain domain, final String disk, final int type) throws LibvirtException {
            throw new LibvirtException("BlockJobFailed");
        }

        @Override
        public void onBlockJobCanceled(final Domain domain, final String disk, final int type) throws LibvirtException {
            throw new LibvirtException("BlockJobCanceled");
        }

        @Override
        public void onBlockJobReady(final Domain domain, final String disk, final int type) throws LibvirtException {
            domain.blockJobAbort(disk, DomainBlockJobAbortFlags.VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT);
            completeSignal.countDown();
        }
    };
    try {
        final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
        conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
        disks = libvirtComputingResource.getDisks(conn, vmName);
        dm = conn.domainLookupByName(vmName);
        newVolumePath = "/mnt/" + command.getPool().getUuid() + "/" + command.getVolumePath();
        for (final LibvirtDiskDef diskDef : disks) {
            if (diskDef.getDiskPath().contains(command.getVolumePath())) {
                disk = diskDef;
                break;
            }
        }
        logger.debug("Registering block job listener with libvirt for domain " + dm.getName());
        dm.addBlockJobListener(blockJobListener);
        if (disk != null) {
            currentVolumePath = disk.getDiskPath();
            int blockCopySpeed = libvirtComputingResource.getVmBlockCopySpeed();
            disk.setDiskPath(newVolumePath);
            DomainBlockCopyParameters domainBlockCopyParameters = new DomainBlockCopyParameters();
            domainBlockCopyParameters.setDomainBlockCopyBandwidth(blockCopySpeed);
            String scale = new String(domainBlockCopyParameters.isDomainBlockCopyBytes() ? " Bytes/s" : " MiB/s");
            logger.debug("Starting block copy for domain " + dm.getName() + " from " + currentVolumePath + " to " + newVolumePath + " @ " + blockCopySpeed + scale);
            dm.blockCopy(currentVolumePath, disk.toString(), domainBlockCopyParameters.getTypedParameters(), 0);
        } else {
            throw new LibvirtException("Couldn't find disk: " + command.getVolumePath() + " on vm: " + dm.getName());
        }
        logger.debug("Waiting for block copy for domain " + dm.getName() + " from " + currentVolumePath + " to " + newVolumePath + " to finish");
        completeSignal.await();
        logger.debug("Refreshing storage pool " + command.getPool().getUuid());
        final StoragePool storagePool = conn.storagePoolLookupByUUIDString(command.getPool().getUuid());
        storagePool.refresh(0);
        isMigrationSuccessfull = true;
    } catch (final LibvirtException | InterruptedException e) {
        logger.debug("Can't migrate disk: " + e.getMessage());
        result = e.getMessage();
    } finally {
        try {
            if (dm != null) {
                dm.free();
            }
            // Stop block job listener
            if (conn != null) {
                conn.removeBlockJobListener(blockJobListener);
            }
        } catch (final LibvirtException e) {
            logger.debug("Ignoring libvirt error.", e);
        }
    }
    try {
        if (isMigrationSuccessfull && conn != null) {
            logger.debug("Cleaning up old disk " + currentVolumePath);
            final StorageVol storageVol = conn.storageVolLookupByPath(currentVolumePath);
            storageVol.delete(0);
        }
    } catch (final LibvirtException e) {
        logger.error("Cleaning up old disk " + currentVolumePath + " failed!", e);
    }
    return new MigrateVolumeAnswer(command, result == null, result, command.getVolumePath());
}
Also used : LibvirtException(org.libvirt.LibvirtException) StoragePool(org.libvirt.StoragePool) StorageVol(org.libvirt.StorageVol) Connect(org.libvirt.Connect) CountDownLatch(java.util.concurrent.CountDownLatch) DomainBlockCopyParameters(org.libvirt.parameters.DomainBlockCopyParameters) LibvirtDiskDef(com.cloud.agent.resource.kvm.xml.LibvirtDiskDef) MigrateVolumeAnswer(com.cloud.legacymodel.communication.answer.MigrateVolumeAnswer) BlockJobListener(org.libvirt.event.BlockJobListener) Domain(org.libvirt.Domain)

Example 13 with LibvirtDiskDef

use of com.cloud.agent.resource.kvm.xml.LibvirtDiskDef in project cosmic by MissionCriticalCloud.

the class LibvirtMigrateCommandWrapper method execute.

@Override
public Answer execute(final MigrateCommand command, final LibvirtComputingResource libvirtComputingResource) {
    final String vmName = command.getVmName();
    String result = null;
    List<LibvirtVmDef.InterfaceDef> ifaces = null;
    final List<LibvirtDiskDef> disks;
    Domain dm = null;
    Connect dconn = null;
    Domain destDomain = null;
    Connect conn = null;
    final String xmlDesc;
    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);
        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 ofcourse 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;
        xmlDesc = dm.getXMLDesc(xmlFlag).replace(libvirtComputingResource.getPrivateIp(), command.getDestinationIp());
        // delete the metadata of vm snapshots before migration
        vmsnapshots = libvirtComputingResource.cleanVMSnapshotMetadata(dm);
        dconn = libvirtUtilitiesHelper.retrieveQemuConnection("qemu+tcp://" + command.getDestinationIp() + "/system");
        // run migration in thread so we can monitor it
        s_logger.info("Live migration of instance " + vmName + " initiated");
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        final Callable<Domain> worker = new MigrateKvmAsync(libvirtComputingResource, dm, dconn, xmlDesc, 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) {
                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");
            }
            // 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(10, TimeUnit.SECONDS);
        if (destDomain != null) {
            for (final LibvirtDiskDef disk : disks) {
                libvirtComputingResource.cleanupDisk(disk);
            }
        }
    } catch (final LibvirtException e) {
        s_logger.debug("Can't migrate domain: " + e.getMessage());
        result = e.getMessage();
    } catch (final InterruptedException e) {
        s_logger.debug("Interrupted while migrating domain: " + e.getMessage());
        result = e.getMessage();
    } catch (final ExecutionException e) {
        s_logger.debug("Failed to execute while migrating domain: " + e.getMessage());
        result = e.getMessage();
    } catch (final TimeoutException e) {
        s_logger.debug("Timed out while migrating domain: " + e.getMessage());
        result = 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) {
        for (final LibvirtVmDef.InterfaceDef iface : ifaces) {
            // 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);
            }
        }
    }
    return new MigrateAnswer(command, result == null, result, null);
}
Also used : LibvirtException(org.libvirt.LibvirtException) MigrateAnswer(com.cloud.legacymodel.communication.answer.MigrateAnswer) LibvirtDiskDef(com.cloud.agent.resource.kvm.xml.LibvirtDiskDef) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException) LibvirtVmDef(com.cloud.agent.resource.kvm.xml.LibvirtVmDef) Ternary(com.cloud.legacymodel.utils.Ternary) Connect(org.libvirt.Connect) VifDriver(com.cloud.agent.resource.kvm.vif.VifDriver) DomainState(org.libvirt.DomainInfo.DomainState) ExecutorService(java.util.concurrent.ExecutorService) Domain(org.libvirt.Domain) MigrateKvmAsync(com.cloud.agent.resource.kvm.async.MigrateKvmAsync)

Aggregations

LibvirtDiskDef (com.cloud.agent.resource.kvm.xml.LibvirtDiskDef)13 Domain (org.libvirt.Domain)8 Connect (org.libvirt.Connect)6 LibvirtException (org.libvirt.LibvirtException)5 InterfaceDef (com.cloud.agent.resource.kvm.xml.LibvirtVmDef.InterfaceDef)4 CloudRuntimeException (com.cloud.legacymodel.exceptions.CloudRuntimeException)3 DiskControllerType (com.cloud.model.enumeration.DiskControllerType)3 ImageFormat (com.cloud.model.enumeration.ImageFormat)3 IOException (java.io.IOException)3 DomainInfo (org.libvirt.DomainInfo)3 KvmPhysicalDisk (com.cloud.agent.resource.kvm.storage.KvmPhysicalDisk)2 KvmStoragePool (com.cloud.agent.resource.kvm.storage.KvmStoragePool)2 VifDriver (com.cloud.agent.resource.kvm.vif.VifDriver)2 LibvirtDomainXmlParser (com.cloud.agent.resource.kvm.xml.LibvirtDomainXmlParser)2 LibvirtVmDef (com.cloud.agent.resource.kvm.xml.LibvirtVmDef)2 Answer (com.cloud.legacymodel.communication.answer.Answer)2 AttachAnswer (com.cloud.legacymodel.communication.answer.AttachAnswer)2 InternalErrorException (com.cloud.legacymodel.exceptions.InternalErrorException)2 ConfigurationException (javax.naming.ConfigurationException)2 DomainBlockStats (org.libvirt.DomainBlockStats)2