Search in sources :

Example 1 with RbdSnapInfo

use of com.ceph.rbd.jna.RbdSnapInfo in project cloudstack by apache.

the class LibvirtStorageAdaptor method createDiskFromTemplateOnRBD.

private KVMPhysicalDisk createDiskFromTemplateOnRBD(KVMPhysicalDisk template, String name, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, KVMStoragePool destPool, 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
         */
    KVMStoragePool srcPool = template.getPool();
    KVMPhysicalDisk disk = null;
    String newUuid = name;
    format = PhysicalDiskFormat.RAW;
    disk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + newUuid, newUuid, 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());
    }
    QemuImg qemu = new QemuImg(timeout);
    QemuImgFile srcFile;
    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 (QemuImgException e) {
            s_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 */
                s_logger.debug("Trying to perform a RBD clone (layering) since we are operating in the same storage pool");
                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();
                s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
                IoCTX io = r.ioCtxCreate(srcPool.getSourceDir());
                Rbd rbd = new Rbd(io);
                RbdImage srcImage = rbd.open(template.getName());
                if (srcImage.isOldFormat()) {
                    /* The source image is RBD format 1, we have to do a regular copy */
                    s_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(), rbdFeatures, rbdOrder);
                    RbdImage destImage = rbd.open(disk.getName());
                    s_logger.debug("Starting to copy " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
                    rbd.copy(srcImage, destImage);
                    s_logger.debug("Finished copying " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
                    rbd.close(destImage);
                } else {
                    s_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) */
                    s_logger.debug("Checking if RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " exists prior to attempting a clone operation.");
                    List<RbdSnapInfo> snaps = srcImage.snapList();
                    s_logger.debug("Found " + snaps.size() + " snapshots on RBD image " + srcPool.getSourceDir() + "/" + template.getName());
                    boolean snapFound = false;
                    for (RbdSnapInfo snap : snaps) {
                        if (rbdTemplateSnapName.equals(snap.name)) {
                            s_logger.debug("RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " already exists.");
                            snapFound = true;
                            break;
                        }
                    }
                    if (!snapFound) {
                        s_logger.debug("Creating RBD snapshot " + rbdTemplateSnapName + " on image " + name);
                        srcImage.snapCreate(rbdTemplateSnapName);
                        s_logger.debug("Protecting RBD snapshot " + rbdTemplateSnapName + " on image " + name);
                        srcImage.snapProtect(rbdTemplateSnapName);
                    }
                    rbd.clone(template.getName(), rbdTemplateSnapName, io, disk.getName(), rbdFeatures, rbdOrder);
                    s_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()) {
                        RbdImage diskImage = rbd.open(disk.getName());
                        diskImage.resize(disk.getVirtualSize());
                        rbd.close(diskImage);
                        s_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 */
                s_logger.debug("Both the source and destination are RBD, but not the same Ceph cluster. Performing a copy");
                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();
                s_logger.debug("Succesfully connected to source Ceph cluster at " + rSrc.confGet("mon_host"));
                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();
                s_logger.debug("Succesfully connected to source Ceph cluster at " + rDest.confGet("mon_host"));
                IoCTX sIO = rSrc.ioCtxCreate(srcPool.getSourceDir());
                Rbd sRbd = new Rbd(sIO);
                IoCTX dIO = rDest.ioCtxCreate(destPool.getSourceDir());
                Rbd dRbd = new Rbd(dIO);
                s_logger.debug("Creating " + disk.getName() + " on the destination cluster " + rDest.confGet("mon_host") + " in pool " + destPool.getSourceDir());
                dRbd.create(disk.getName(), disk.getVirtualSize(), rbdFeatures, rbdOrder);
                RbdImage srcImage = sRbd.open(template.getName());
                RbdImage destImage = dRbd.open(disk.getName());
                s_logger.debug("Copying " + template.getName() + " from Ceph cluster " + rSrc.confGet("mon_host") + " to " + disk.getName() + " on cluster " + rDest.confGet("mon_host"));
                sRbd.copy(srcImage, destImage);
                sRbd.close(srcImage);
                dRbd.close(destImage);
                rSrc.ioCtxDestroy(sIO);
                rDest.ioCtxDestroy(dIO);
            }
        } catch (RadosException e) {
            s_logger.error("Failed to perform a RADOS action on the Ceph cluster, the error was: " + e.getMessage());
            disk = null;
        } catch (RbdException e) {
            s_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) QemuImg(org.apache.cloudstack.utils.qemu.QemuImg) RbdSnapInfo(com.ceph.rbd.jna.RbdSnapInfo) QemuImgFile(org.apache.cloudstack.utils.qemu.QemuImgFile) Rbd(com.ceph.rbd.Rbd) QemuImgException(org.apache.cloudstack.utils.qemu.QemuImgException) RbdImage(com.ceph.rbd.RbdImage) IoCTX(com.ceph.rados.IoCTX) RbdException(com.ceph.rbd.RbdException)

Example 2 with RbdSnapInfo

use of com.ceph.rbd.jna.RbdSnapInfo in project cloudstack by apache.

the class LibvirtStorageAdaptor method deletePhysicalDisk.

@Override
public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool, Storage.ImageFormat format) {
    s_logger.info("Attempting to remove volume " + uuid + " from pool " + pool.getUuid());
    /**
         * RBD volume can have snapshots and while they exist libvirt
         * can't remove the RBD volume
         *
         * We have to remove those snapshots first
         */
    if (pool.getType() == StoragePoolType.RBD) {
        try {
            s_logger.info("Unprotecting and Removing RBD snapshots of image " + pool.getSourceDir() + "/" + uuid + " prior to removing the image");
            Rados r = new Rados(pool.getAuthUserName());
            r.confSet("mon_host", pool.getSourceHost() + ":" + pool.getSourcePort());
            r.confSet("key", pool.getAuthSecret());
            r.confSet("client_mount_timeout", "30");
            r.connect();
            s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
            IoCTX io = r.ioCtxCreate(pool.getSourceDir());
            Rbd rbd = new Rbd(io);
            RbdImage image = rbd.open(uuid);
            s_logger.debug("Fetching list of snapshots of RBD image " + pool.getSourceDir() + "/" + uuid);
            List<RbdSnapInfo> snaps = image.snapList();
            try {
                for (RbdSnapInfo snap : snaps) {
                    if (image.snapIsProtected(snap.name)) {
                        s_logger.debug("Unprotecting snapshot " + pool.getSourceDir() + "/" + uuid + "@" + snap.name);
                        image.snapUnprotect(snap.name);
                    } else {
                        s_logger.debug("Snapshot " + pool.getSourceDir() + "/" + uuid + "@" + snap.name + " is not protected.");
                    }
                    s_logger.debug("Removing snapshot " + pool.getSourceDir() + "/" + uuid + "@" + snap.name);
                    image.snapRemove(snap.name);
                }
                s_logger.info("Succesfully unprotected and removed any remaining snapshots (" + snaps.size() + ") of " + pool.getSourceDir() + "/" + uuid + " Continuing to remove the RBD image");
            } catch (RbdException e) {
                s_logger.error("Failed to remove snapshot with exception: " + e.toString() + ", RBD error: " + ErrorCode.getErrorMessage(e.getReturnValue()));
                throw new CloudRuntimeException(e.toString() + " - " + ErrorCode.getErrorMessage(e.getReturnValue()));
            } finally {
                s_logger.debug("Closing image and destroying context");
                rbd.close(image);
                r.ioCtxDestroy(io);
            }
        } catch (RadosException e) {
            s_logger.error("Failed to remove snapshot with exception: " + e.toString() + ", RBD error: " + ErrorCode.getErrorMessage(e.getReturnValue()));
            throw new CloudRuntimeException(e.toString() + " - " + ErrorCode.getErrorMessage(e.getReturnValue()));
        } catch (RbdException e) {
            s_logger.error("Failed to remove snapshot with exception: " + e.toString() + ", RBD error: " + ErrorCode.getErrorMessage(e.getReturnValue()));
            throw new CloudRuntimeException(e.toString() + " - " + ErrorCode.getErrorMessage(e.getReturnValue()));
        }
    }
    LibvirtStoragePool libvirtPool = (LibvirtStoragePool) pool;
    try {
        StorageVol vol = getVolume(libvirtPool.getPool(), uuid);
        s_logger.debug("Instructing libvirt to remove volume " + uuid + " from pool " + pool.getUuid());
        if (Storage.ImageFormat.DIR.equals(format)) {
            deleteDirVol(libvirtPool, vol);
        } else {
            deleteVol(libvirtPool, vol);
        }
        vol.free();
        return true;
    } catch (LibvirtException e) {
        throw new CloudRuntimeException(e.toString());
    }
}
Also used : RbdSnapInfo(com.ceph.rbd.jna.RbdSnapInfo) StorageVol(org.libvirt.StorageVol) LibvirtException(org.libvirt.LibvirtException) Rbd(com.ceph.rbd.Rbd) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) Rados(com.ceph.rados.Rados) RbdImage(com.ceph.rbd.RbdImage) IoCTX(com.ceph.rados.IoCTX) RadosException(com.ceph.rados.exceptions.RadosException) RbdException(com.ceph.rbd.RbdException)

Aggregations

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 RbdSnapInfo (com.ceph.rbd.jna.RbdSnapInfo)2 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)1 QemuImg (org.apache.cloudstack.utils.qemu.QemuImg)1 QemuImgException (org.apache.cloudstack.utils.qemu.QemuImgException)1 QemuImgFile (org.apache.cloudstack.utils.qemu.QemuImgFile)1 LibvirtException (org.libvirt.LibvirtException)1 StorageVol (org.libvirt.StorageVol)1