Search in sources :

Example 6 with QemuImgFile

use of org.apache.cloudstack.utils.qemu.QemuImgFile in project cloudstack by apache.

the class KVMStorageProcessor method backupSnapshot.

@Override
public Answer backupSnapshot(final CopyCommand cmd) {
    final DataTO srcData = cmd.getSrcTO();
    final DataTO destData = cmd.getDestTO();
    final SnapshotObjectTO snapshot = (SnapshotObjectTO) srcData;
    final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshot.getDataStore();
    final SnapshotObjectTO destSnapshot = (SnapshotObjectTO) destData;
    final DataStoreTO imageStore = destData.getDataStore();
    if (!(imageStore instanceof NfsTO)) {
        return backupSnapshotForObjectStore(cmd);
    }
    final NfsTO nfsImageStore = (NfsTO) imageStore;
    final String secondaryStoragePoolUrl = nfsImageStore.getUrl();
    // NOTE: snapshot name is encoded in snapshot path
    final int index = snapshot.getPath().lastIndexOf("/");
    // -1 means the snapshot is created from existing vm snapshot
    final boolean isCreatedFromVmSnapshot = (index == -1) ? true : false;
    final String snapshotName = snapshot.getPath().substring(index + 1);
    String descName = snapshotName;
    final String volumePath = snapshot.getVolume().getPath();
    String snapshotDestPath = null;
    String snapshotRelPath = null;
    final String vmName = snapshot.getVmName();
    KVMStoragePool secondaryStoragePool = null;
    Connect conn = null;
    KVMPhysicalDisk snapshotDisk = null;
    KVMStoragePool primaryPool = null;
    try {
        conn = LibvirtConnection.getConnectionByVmName(vmName);
        secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
        final String ssPmountPath = secondaryStoragePool.getLocalPath();
        snapshotRelPath = destSnapshot.getPath();
        snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath;
        snapshotDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volumePath);
        primaryPool = snapshotDisk.getPool();
        long size = 0;
        /**
             * Since Ceph version Dumpling (0.67.X) librbd / Qemu supports converting RBD
             * snapshots to RAW/QCOW2 files directly.
             *
             * This reduces the amount of time and storage it takes to back up a snapshot dramatically
             */
        if (primaryPool.getType() == StoragePoolType.RBD) {
            final String rbdSnapshot = snapshotDisk.getPath() + "@" + snapshotName;
            final String snapshotFile = snapshotDestPath + "/" + snapshotName;
            try {
                s_logger.debug("Attempting to backup RBD snapshot " + rbdSnapshot);
                final File snapDir = new File(snapshotDestPath);
                s_logger.debug("Attempting to create " + snapDir.getAbsolutePath() + " recursively for snapshot storage");
                FileUtils.forceMkdir(snapDir);
                final QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primaryPool.getSourceHost(), primaryPool.getSourcePort(), primaryPool.getAuthUserName(), primaryPool.getAuthSecret(), rbdSnapshot));
                srcFile.setFormat(snapshotDisk.getFormat());
                final QemuImgFile destFile = new QemuImgFile(snapshotFile);
                destFile.setFormat(PhysicalDiskFormat.QCOW2);
                s_logger.debug("Backing up RBD snapshot " + rbdSnapshot + " to " + snapshotFile);
                final QemuImg q = new QemuImg(cmd.getWaitInMillSeconds());
                q.convert(srcFile, destFile);
                final File snapFile = new File(snapshotFile);
                if (snapFile.exists()) {
                    size = snapFile.length();
                }
                s_logger.debug("Finished backing up RBD snapshot " + rbdSnapshot + " to " + snapshotFile + " Snapshot size: " + size);
            } catch (final FileNotFoundException e) {
                s_logger.error("Failed to open " + snapshotDestPath + ". The error was: " + e.getMessage());
                return new CopyCmdAnswer(e.toString());
            } catch (final IOException e) {
                s_logger.error("Failed to create " + snapshotDestPath + ". The error was: " + e.getMessage());
                return new CopyCmdAnswer(e.toString());
            } catch (final QemuImgException e) {
                s_logger.error("Failed to backup the RBD snapshot from " + rbdSnapshot + " to " + snapshotFile + " the error was: " + e.getMessage());
                return new CopyCmdAnswer(e.toString());
            }
        } else {
            final Script command = new Script(_manageSnapshotPath, cmd.getWaitInMillSeconds(), s_logger);
            command.add("-b", snapshotDisk.getPath());
            command.add("-n", snapshotName);
            command.add("-p", snapshotDestPath);
            if (isCreatedFromVmSnapshot) {
                descName = UUID.randomUUID().toString();
            }
            command.add("-t", descName);
            final String result = command.execute();
            if (result != null) {
                s_logger.debug("Failed to backup snaptshot: " + result);
                return new CopyCmdAnswer(result);
            }
            final File snapFile = new File(snapshotDestPath + "/" + descName);
            if (snapFile.exists()) {
                size = snapFile.length();
            }
        }
        final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
        newSnapshot.setPath(snapshotRelPath + File.separator + descName);
        newSnapshot.setPhysicalSize(size);
        return new CopyCmdAnswer(newSnapshot);
    } catch (final LibvirtException e) {
        s_logger.debug("Failed to backup snapshot: ", e);
        return new CopyCmdAnswer(e.toString());
    } catch (final CloudRuntimeException e) {
        s_logger.debug("Failed to backup snapshot: ", e);
        return new CopyCmdAnswer(e.toString());
    } finally {
        if (isCreatedFromVmSnapshot) {
            s_logger.debug("Ignoring removal of vm snapshot on primary as this snapshot is created from vm snapshot");
        } else {
            try {
                /* Delete the snapshot on primary */
                DomainInfo.DomainState state = null;
                Domain vm = null;
                if (vmName != null) {
                    try {
                        vm = resource.getDomain(conn, vmName);
                        state = vm.getInfo().state;
                    } catch (final LibvirtException e) {
                        s_logger.trace("Ignoring libvirt error.", e);
                    }
                }
                final KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
                if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) {
                    final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
                    snap.delete(0);
                    /*
                         * libvirt on RHEL6 doesn't handle resume event emitted from
                         * qemu
                         */
                    vm = resource.getDomain(conn, vmName);
                    state = vm.getInfo().state;
                    if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
                        vm.resume();
                    }
                } else {
                    if (primaryPool.getType() != StoragePoolType.RBD) {
                        final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
                        command.add("-d", snapshotDisk.getPath());
                        command.add("-n", snapshotName);
                        final String result = command.execute();
                        if (result != null) {
                            s_logger.debug("Failed to delete snapshot on primary: " + result);
                        // return new CopyCmdAnswer("Failed to backup snapshot: " + result);
                        }
                    }
                }
            } catch (final Exception ex) {
                s_logger.debug("Failed to delete snapshots on primary", ex);
            }
        }
        try {
            if (secondaryStoragePool != null) {
                secondaryStoragePool.delete();
            }
        } catch (final Exception ex) {
            s_logger.debug("Failed to delete secondary storage", ex);
        }
    }
}
Also used : SnapshotObjectTO(org.apache.cloudstack.storage.to.SnapshotObjectTO) LibvirtException(org.libvirt.LibvirtException) FileNotFoundException(java.io.FileNotFoundException) DataTO(com.cloud.agent.api.to.DataTO) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) QemuImgException(org.apache.cloudstack.utils.qemu.QemuImgException) DomainInfo(org.libvirt.DomainInfo) Script(com.cloud.utils.script.Script) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) DataStoreTO(com.cloud.agent.api.to.DataStoreTO) Connect(org.libvirt.Connect) DomainSnapshot(org.libvirt.DomainSnapshot) IOException(java.io.IOException) NfsTO(com.cloud.agent.api.to.NfsTO) URISyntaxException(java.net.URISyntaxException) LibvirtException(org.libvirt.LibvirtException) RbdException(com.ceph.rbd.RbdException) QemuImgException(org.apache.cloudstack.utils.qemu.QemuImgException) FileNotFoundException(java.io.FileNotFoundException) InternalErrorException(com.cloud.exception.InternalErrorException) ConfigurationException(javax.naming.ConfigurationException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) RadosException(com.ceph.rados.exceptions.RadosException) IOException(java.io.IOException) QemuImg(org.apache.cloudstack.utils.qemu.QemuImg) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) QemuImgFile(org.apache.cloudstack.utils.qemu.QemuImgFile) Domain(org.libvirt.Domain) QemuImgFile(org.apache.cloudstack.utils.qemu.QemuImgFile) S3Utils.putFile(com.cloud.utils.storage.S3.S3Utils.putFile) File(java.io.File) CopyCmdAnswer(org.apache.cloudstack.storage.command.CopyCmdAnswer)

Example 7 with QemuImgFile

use of org.apache.cloudstack.utils.qemu.QemuImgFile in project cloudstack by apache.

the class LibvirtStorageAdaptor method createDiskFromTemplate.

/**
     * This function copies a physical disk from Secondary Storage to Primary Storage
     * or from Primary to Primary Storage
     *
     * The first time a template is deployed in Primary Storage it will be copied from
     * Secondary to Primary.
     *
     * If it has been created on Primary Storage, it will be copied on the Primary Storage
     */
@Override
public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, KVMStoragePool destPool, int timeout) {
    s_logger.info("Creating volume " + name + " from template " + template.getName() + " in pool " + destPool.getUuid() + " (" + destPool.getType().toString() + ") with size " + size);
    KVMPhysicalDisk disk = null;
    if (destPool.getType() == StoragePoolType.RBD) {
        disk = createDiskFromTemplateOnRBD(template, name, format, provisioningType, size, destPool, timeout);
    } else {
        try {
            String newUuid = name;
            disk = destPool.createPhysicalDisk(newUuid, format, provisioningType, template.getVirtualSize());
            if (disk == null) {
                throw new CloudRuntimeException("Failed to create disk from template " + template.getName());
            }
            if (template.getFormat() == PhysicalDiskFormat.TAR) {
                // TO BE FIXED to aware provisioningType
                Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath(), timeout);
            } else if (template.getFormat() == PhysicalDiskFormat.DIR) {
                Script.runSimpleBashScript("mkdir -p " + disk.getPath());
                Script.runSimpleBashScript("chmod 755 " + disk.getPath());
                Script.runSimpleBashScript("tar -x -f " + template.getPath() + "/*.tar -C " + disk.getPath(), timeout);
            } else if (format == PhysicalDiskFormat.QCOW2) {
                QemuImg qemu = new QemuImg(timeout);
                QemuImgFile destFile = new QemuImgFile(disk.getPath(), format);
                if (size > template.getVirtualSize()) {
                    destFile.setSize(size);
                } else {
                    destFile.setSize(template.getVirtualSize());
                }
                Map<String, String> options = new HashMap<String, String>();
                options.put("preallocation", QemuImg.PreallocationType.getPreallocationType(provisioningType).toString());
                switch(provisioningType) {
                    case THIN:
                        QemuImgFile backingFile = new QemuImgFile(template.getPath(), template.getFormat());
                        qemu.create(destFile, backingFile, options);
                        break;
                    case SPARSE:
                    case FAT:
                        QemuImgFile srcFile = new QemuImgFile(template.getPath(), template.getFormat());
                        qemu.convert(srcFile, destFile, options);
                        break;
                }
            } else if (format == PhysicalDiskFormat.RAW) {
                QemuImgFile sourceFile = new QemuImgFile(template.getPath(), template.getFormat());
                QemuImgFile destFile = new QemuImgFile(disk.getPath(), PhysicalDiskFormat.RAW);
                if (size > template.getVirtualSize()) {
                    destFile.setSize(size);
                } else {
                    destFile.setSize(template.getVirtualSize());
                }
                QemuImg qemu = new QemuImg(timeout);
                Map<String, String> options = new HashMap<String, String>();
                qemu.convert(sourceFile, destFile, options);
            }
        } catch (QemuImgException e) {
            s_logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage());
        }
    }
    return disk;
}
Also used : QemuImgFile(org.apache.cloudstack.utils.qemu.QemuImgFile) HashMap(java.util.HashMap) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) QemuImgException(org.apache.cloudstack.utils.qemu.QemuImgException) HashMap(java.util.HashMap) Map(java.util.Map) QemuImg(org.apache.cloudstack.utils.qemu.QemuImg)

Aggregations

QemuImg (org.apache.cloudstack.utils.qemu.QemuImg)7 QemuImgException (org.apache.cloudstack.utils.qemu.QemuImgException)7 QemuImgFile (org.apache.cloudstack.utils.qemu.QemuImgFile)7 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)5 RadosException (com.ceph.rados.exceptions.RadosException)4 RbdException (com.ceph.rbd.RbdException)4 File (java.io.File)4 HashMap (java.util.HashMap)4 InternalErrorException (com.cloud.exception.InternalErrorException)3 Script (com.cloud.utils.script.Script)3 IOException (java.io.IOException)3 ConfigurationException (javax.naming.ConfigurationException)3 IoCTX (com.ceph.rados.IoCTX)2 Rados (com.ceph.rados.Rados)2 Rbd (com.ceph.rbd.Rbd)2 RbdImage (com.ceph.rbd.RbdImage)2 DataStoreTO (com.cloud.agent.api.to.DataStoreTO)2 DataTO (com.cloud.agent.api.to.DataTO)2 NfsTO (com.cloud.agent.api.to.NfsTO)2 Processor (com.cloud.storage.template.Processor)2