Search in sources :

Example 6 with QemuImgFile

use of com.cloud.agent.resource.kvm.storage.utils.QemuImgFile 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 QemuImgFile

use of com.cloud.agent.resource.kvm.storage.utils.QemuImgFile 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 QemuImgFile

use of com.cloud.agent.resource.kvm.storage.utils.QemuImgFile 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