Search in sources :

Example 6 with QemuImg

use of com.cloud.agent.resource.kvm.storage.utils.QemuImg in project cosmic by MissionCriticalCloud.

the class LibvirtStorageAdaptor method createDiskFromTemplateOnRbd.

private KvmPhysicalDisk createDiskFromTemplateOnRbd(final KvmPhysicalDisk template, final String name, final long size, final KvmStoragePool destPool, final int timeout) {
    /*
         * With RBD you can't run qemu-img convert with an existing RBD image as destination qemu-img will exit with the
         * error that the destination already exists. So for RBD we don't create the image, but let qemu-img do that for us.
         *
         * We then create a KVMPhysicalDisk object that we can return
         */
    final KvmStoragePool srcPool = template.getPool();
    KvmPhysicalDisk disk;
    final PhysicalDiskFormat format = PhysicalDiskFormat.RAW;
    disk = new KvmPhysicalDisk(destPool.getSourceDir() + "/" + name, name, destPool);
    disk.setFormat(format);
    if (size > template.getVirtualSize()) {
        disk.setSize(size);
        disk.setVirtualSize(size);
    } else {
        // leave these as they were if size isn't applicable
        disk.setSize(template.getVirtualSize());
        disk.setVirtualSize(disk.getSize());
    }
    final QemuImg qemu = new QemuImg(timeout);
    final QemuImgFile srcFile;
    final QemuImgFile destFile = new QemuImgFile(KvmPhysicalDisk.rbdStringBuilder(destPool.getSourceHost(), destPool.getSourcePort(), destPool.getAuthUserName(), destPool.getAuthSecret(), disk.getPath()));
    destFile.setFormat(format);
    if (srcPool.getType() != StoragePoolType.RBD) {
        srcFile = new QemuImgFile(template.getPath(), template.getFormat());
        try {
            qemu.convert(srcFile, destFile);
        } catch (final QemuImgException e) {
            this.logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage());
        }
    } else {
        try {
            if (srcPool.getSourceHost().equals(destPool.getSourceHost()) && srcPool.getSourceDir().equals(destPool.getSourceDir())) {
                /* We are on the same Ceph cluster, but we require RBD format 2 on the source image */
                this.logger.debug("Trying to perform a RBD clone (layering) since we are operating in the same storage pool");
                final Rados r = new Rados(srcPool.getAuthUserName());
                r.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort());
                r.confSet("key", srcPool.getAuthSecret());
                r.confSet("client_mount_timeout", "30");
                r.connect();
                this.logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
                final IoCTX io = r.ioCtxCreate(srcPool.getSourceDir());
                final Rbd rbd = new Rbd(io);
                final RbdImage srcImage = rbd.open(template.getName());
                if (srcImage.isOldFormat()) {
                    /* The source image is RBD format 1, we have to do a regular copy */
                    this.logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + " is RBD format 1. We have to perform a regular copy (" + disk.getVirtualSize() + " bytes)");
                    rbd.create(disk.getName(), disk.getVirtualSize(), this.rbdFeatures, this.rbdOrder);
                    final RbdImage destImage = rbd.open(disk.getName());
                    this.logger.debug("Starting to copy " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
                    rbd.copy(srcImage, destImage);
                    this.logger.debug("Finished copying " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
                    rbd.close(destImage);
                } else {
                    final String rbdTemplateSnapName = "cloudstack-base-snap";
                    this.logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + " is RBD format 2. We will perform a RBD clone using snapshot " + rbdTemplateSnapName);
                    /* The source image is format 2, we can do a RBD snapshot+clone (layering) */
                    this.logger.debug("Checking if RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " exists prior to attempting a clone operation.");
                    final List<RbdSnapInfo> snaps = srcImage.snapList();
                    this.logger.debug("Found " + snaps.size() + " snapshots on RBD image " + srcPool.getSourceDir() + "/" + template.getName());
                    boolean snapFound = false;
                    for (final RbdSnapInfo snap : snaps) {
                        if (rbdTemplateSnapName.equals(snap.name)) {
                            this.logger.debug("RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " already exists.");
                            snapFound = true;
                            break;
                        }
                    }
                    if (!snapFound) {
                        this.logger.debug("Creating RBD snapshot " + rbdTemplateSnapName + " on image " + name);
                        srcImage.snapCreate(rbdTemplateSnapName);
                        this.logger.debug("Protecting RBD snapshot " + rbdTemplateSnapName + " on image " + name);
                        srcImage.snapProtect(rbdTemplateSnapName);
                    }
                    rbd.clone(template.getName(), rbdTemplateSnapName, io, disk.getName(), this.rbdFeatures, this.rbdOrder);
                    this.logger.debug("Succesfully cloned " + template.getName() + "@" + rbdTemplateSnapName + " to " + disk.getName());
                    /* We also need to resize the image if the VM was deployed with a larger root disk size */
                    if (disk.getVirtualSize() > template.getVirtualSize()) {
                        final RbdImage diskImage = rbd.open(disk.getName());
                        diskImage.resize(disk.getVirtualSize());
                        rbd.close(diskImage);
                        this.logger.debug("Resized " + disk.getName() + " to " + disk.getVirtualSize());
                    }
                }
                rbd.close(srcImage);
                r.ioCtxDestroy(io);
            } else {
                /* The source pool or host is not the same Ceph cluster, we do a simple copy with Qemu-Img */
                this.logger.debug("Both the source and destination are RBD, but not the same Ceph cluster. Performing a copy");
                final Rados rSrc = new Rados(srcPool.getAuthUserName());
                rSrc.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort());
                rSrc.confSet("key", srcPool.getAuthSecret());
                rSrc.confSet("client_mount_timeout", "30");
                rSrc.connect();
                this.logger.debug("Succesfully connected to source Ceph cluster at " + rSrc.confGet("mon_host"));
                final Rados rDest = new Rados(destPool.getAuthUserName());
                rDest.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort());
                rDest.confSet("key", destPool.getAuthSecret());
                rDest.confSet("client_mount_timeout", "30");
                rDest.connect();
                this.logger.debug("Succesfully connected to source Ceph cluster at " + rDest.confGet("mon_host"));
                final IoCTX sourceIo = rSrc.ioCtxCreate(srcPool.getSourceDir());
                final Rbd sourceRbd = new Rbd(sourceIo);
                final IoCTX destinationIo = rDest.ioCtxCreate(destPool.getSourceDir());
                final Rbd destinationRbd = new Rbd(destinationIo);
                this.logger.debug("Creating " + disk.getName() + " on the destination cluster " + rDest.confGet("mon_host") + " in pool " + destPool.getSourceDir());
                destinationRbd.create(disk.getName(), disk.getVirtualSize(), this.rbdFeatures, this.rbdOrder);
                final RbdImage srcImage = sourceRbd.open(template.getName());
                final RbdImage destImage = destinationRbd.open(disk.getName());
                this.logger.debug("Copying " + template.getName() + " from Ceph cluster " + rSrc.confGet("mon_host") + " to " + disk.getName() + " on cluster " + rDest.confGet("mon_host"));
                sourceRbd.copy(srcImage, destImage);
                sourceRbd.close(srcImage);
                destinationRbd.close(destImage);
                rSrc.ioCtxDestroy(sourceIo);
                rDest.ioCtxDestroy(destinationIo);
            }
        } catch (final RadosException e) {
            this.logger.error("Failed to perform a RADOS action on the Ceph cluster, the error was: " + e.getMessage());
            disk = null;
        } catch (final RbdException e) {
            this.logger.error("Failed to perform a RBD action on the Ceph cluster, the error was: " + e.getMessage());
            disk = null;
        }
    }
    return disk;
}
Also used : Rados(com.ceph.rados.Rados) RadosException(com.ceph.rados.exceptions.RadosException) PhysicalDiskFormat(com.cloud.model.enumeration.PhysicalDiskFormat) QemuImg(com.cloud.agent.resource.kvm.storage.utils.QemuImg) RbdSnapInfo(com.ceph.rbd.jna.RbdSnapInfo) QemuImgFile(com.cloud.agent.resource.kvm.storage.utils.QemuImgFile) Rbd(com.ceph.rbd.Rbd) QemuImgException(com.cloud.agent.resource.kvm.storage.utils.QemuImgException) RbdImage(com.ceph.rbd.RbdImage) IoCTX(com.ceph.rados.IoCTX) RbdException(com.ceph.rbd.RbdException)

Example 7 with QemuImg

use of com.cloud.agent.resource.kvm.storage.utils.QemuImg in project cosmic by MissionCriticalCloud.

the class LibvirtStorageAdaptor method getPhysicalDisk.

@Override
public KvmPhysicalDisk getPhysicalDisk(final String volumeUuid, final KvmStoragePool pool) {
    final LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
    try {
        final StorageVol vol = getVolume(libvirtPool.getPool(), volumeUuid);
        final KvmPhysicalDisk disk;
        final LibvirtStorageVolumeDef voldef = getStorageVolumeDef(vol);
        disk = new KvmPhysicalDisk(vol.getPath(), vol.getName(), pool);
        disk.setSize(vol.getInfo().allocation);
        disk.setVirtualSize(vol.getInfo().capacity);
        if (pool.getType() == StoragePoolType.RBD) {
            disk.setFormat(PhysicalDiskFormat.RAW);
        } else if (pool.getType() == StoragePoolType.NetworkFilesystem) {
            final QemuImg qemuImg = new QemuImg(60000);
            final Map<String, String> info = qemuImg.info(new QemuImgFile(disk.getPath()));
            disk.setFormat(PhysicalDiskFormat.valueOf(info.get("file_format").toUpperCase()));
        } else if (voldef.getFormat() == null) {
            disk.setFormat(pool.getDefaultFormat());
        } else if (voldef.getFormat() == LibvirtStorageVolumeDef.VolumeFormat.QCOW2) {
            disk.setFormat(PhysicalDiskFormat.QCOW2);
        } else if (voldef.getFormat() == LibvirtStorageVolumeDef.VolumeFormat.RAW) {
            disk.setFormat(PhysicalDiskFormat.RAW);
        }
        return disk;
    } catch (final LibvirtException | QemuImgException e) {
        this.logger.debug("Failed to get physical disk:", e);
        throw new CloudRuntimeException(e.toString());
    }
}
Also used : StorageVol(org.libvirt.StorageVol) LibvirtStorageVolumeDef(com.cloud.agent.resource.kvm.xml.LibvirtStorageVolumeDef) LibvirtException(org.libvirt.LibvirtException) QemuImgFile(com.cloud.agent.resource.kvm.storage.utils.QemuImgFile) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) QemuImgException(com.cloud.agent.resource.kvm.storage.utils.QemuImgException) HashMap(java.util.HashMap) Map(java.util.Map) QemuImg(com.cloud.agent.resource.kvm.storage.utils.QemuImg)

Example 8 with QemuImg

use of com.cloud.agent.resource.kvm.storage.utils.QemuImg in project cosmic by MissionCriticalCloud.

the class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper method execute.

@Override
public Answer execute(final CreatePrivateTemplateFromVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
    final String secondaryStorageUrl = command.getSecondaryStorageUrl();
    KvmStoragePool secondaryStorage = null;
    KvmStoragePool primary = null;
    final KvmStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
    try {
        final String templateFolder = command.getAccountId() + File.separator + command.getTemplateId() + File.separator;
        final String templateInstallFolder = "/template/tmpl/" + templateFolder;
        secondaryStorage = storagePoolMgr.getStoragePoolByUri(secondaryStorageUrl);
        try {
            primary = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
        } catch (final CloudRuntimeException e) {
            if (e.getMessage().contains("not found")) {
                primary = storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(), command.getPool().getUserInfo(), command.getPool().getType());
            } else {
                return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
            }
        }
        final KvmPhysicalDisk disk = primary.getPhysicalDisk(command.getVolumePath());
        final String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder;
        final StorageLayer storage = libvirtComputingResource.getStorage();
        storage.mkdirs(tmpltPath);
        if (primary.getType() != StoragePoolType.RBD) {
            final String createTmplPath = libvirtComputingResource.createTmplPath();
            final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
            final Script scriptCommand = new Script(createTmplPath, cmdsTimeout, s_logger);
            scriptCommand.add("-f", disk.getPath());
            scriptCommand.add("-t", tmpltPath);
            scriptCommand.add("-n", command.getUniqueName() + ".qcow2");
            final String result = scriptCommand.execute();
            if (result != null) {
                s_logger.debug("failed to create template: " + result);
                return new CreatePrivateTemplateAnswer(command, false, result);
            }
        } else {
            s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + command.getUniqueName());
            final QemuImgFile srcFile = new QemuImgFile(KvmPhysicalDisk.rbdStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(), primary.getAuthSecret(), disk.getPath()));
            srcFile.setFormat(PhysicalDiskFormat.RAW);
            final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + command.getUniqueName() + ".qcow2");
            destFile.setFormat(PhysicalDiskFormat.QCOW2);
            final QemuImg q = new QemuImg(0);
            try {
                q.convert(srcFile, destFile);
            } catch (final QemuImgException e) {
                s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
            }
            final File templateProp = new File(tmpltPath + "/template.properties");
            if (!templateProp.exists()) {
                templateProp.createNewFile();
            }
            String templateContent = "filename=" + command.getUniqueName() + ".qcow2" + System.getProperty("line.separator");
            final DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
            final Date date = new Date();
            templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
            try (final FileOutputStream templFo = new FileOutputStream(templateProp)) {
                templFo.write(templateContent.getBytes("UTF-8"));
                templFo.flush();
            } catch (final IOException ex) {
                s_logger.error("CreatePrivateTemplateAnswer:Exception:" + ex.getMessage());
            }
        }
        final Map<String, Object> params = new HashMap<>();
        params.put(StorageLayer.InstanceConfigKey, storage);
        final Processor qcow2Processor = new QCOW2Processor();
        qcow2Processor.configure("QCOW2 Processor", params);
        final TemplateFormatInfo info = qcow2Processor.process(tmpltPath, null, command.getUniqueName());
        final TemplateLocation loc = new TemplateLocation(storage, tmpltPath);
        loc.create(1, true, command.getUniqueName());
        loc.addFormat(info);
        loc.save();
        return new CreatePrivateTemplateAnswer(command, true, null, templateInstallFolder + command.getUniqueName() + ".qcow2", info.virtualSize, info.size, command.getUniqueName(), ImageFormat.QCOW2);
    } catch (final InternalErrorException e) {
        return new CreatePrivateTemplateAnswer(command, false, e.toString());
    } catch (final IOException e) {
        return new CreatePrivateTemplateAnswer(command, false, e.toString());
    } catch (final ConfigurationException e) {
        return new CreatePrivateTemplateAnswer(command, false, e.toString());
    } catch (final CloudRuntimeException e) {
        return new CreatePrivateTemplateAnswer(command, false, e.toString());
    } finally {
        if (secondaryStorage != null) {
            storagePoolMgr.deleteStoragePool(secondaryStorage.getType(), secondaryStorage.getUuid());
        }
    }
}
Also used : KvmStoragePool(com.cloud.agent.resource.kvm.storage.KvmStoragePool) StorageLayer(com.cloud.utils.storage.StorageLayer) QCOW2Processor(com.cloud.common.storageprocessor.QCOW2Processor) Processor(com.cloud.common.storageprocessor.Processor) HashMap(java.util.HashMap) ConfigurationException(javax.naming.ConfigurationException) CloudRuntimeException(com.cloud.legacymodel.exceptions.CloudRuntimeException) TemplateLocation(com.cloud.common.storageprocessor.TemplateLocation) QemuImgException(com.cloud.agent.resource.kvm.storage.utils.QemuImgException) KvmStoragePoolManager(com.cloud.agent.resource.kvm.storage.KvmStoragePoolManager) KvmPhysicalDisk(com.cloud.agent.resource.kvm.storage.KvmPhysicalDisk) Script(com.cloud.utils.script.Script) IOException(java.io.IOException) InternalErrorException(com.cloud.legacymodel.exceptions.InternalErrorException) Date(java.util.Date) QemuImg(com.cloud.agent.resource.kvm.storage.utils.QemuImg) QCOW2Processor(com.cloud.common.storageprocessor.QCOW2Processor) QemuImgFile(com.cloud.agent.resource.kvm.storage.utils.QemuImgFile) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) FileOutputStream(java.io.FileOutputStream) TemplateFormatInfo(com.cloud.legacymodel.storage.TemplateFormatInfo) CreatePrivateTemplateAnswer(com.cloud.legacymodel.communication.answer.CreatePrivateTemplateAnswer) File(java.io.File) QemuImgFile(com.cloud.agent.resource.kvm.storage.utils.QemuImgFile) SimpleDateFormat(java.text.SimpleDateFormat)

Aggregations

QemuImg (com.cloud.agent.resource.kvm.storage.utils.QemuImg)8 QemuImgException (com.cloud.agent.resource.kvm.storage.utils.QemuImgException)8 QemuImgFile (com.cloud.agent.resource.kvm.storage.utils.QemuImgFile)8 CloudRuntimeException (com.cloud.legacymodel.exceptions.CloudRuntimeException)7 HashMap (java.util.HashMap)5 File (java.io.File)4 InternalErrorException (com.cloud.legacymodel.exceptions.InternalErrorException)3 Script (com.cloud.utils.script.Script)3 IOException (java.io.IOException)3 ConfigurationException (javax.naming.ConfigurationException)3 LibvirtException (org.libvirt.LibvirtException)3 IoCTX (com.ceph.rados.IoCTX)2 Rados (com.ceph.rados.Rados)2 RadosException (com.ceph.rados.exceptions.RadosException)2 Rbd (com.ceph.rbd.Rbd)2 RbdException (com.ceph.rbd.RbdException)2 RbdImage (com.ceph.rbd.RbdImage)2 Processor (com.cloud.common.storageprocessor.Processor)2 QCOW2Processor (com.cloud.common.storageprocessor.QCOW2Processor)2 TemplateLocation (com.cloud.common.storageprocessor.TemplateLocation)2