Search in sources :

Example 11 with RbdImage

use of com.ceph.rbd.RbdImage in project cloudstack by apache.

the class LibvirtBackupSnapshotCommandWrapper method execute.

@Override
public Answer execute(final BackupSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
    final Long dcId = command.getDataCenterId();
    final Long accountId = command.getAccountId();
    final Long volumeId = command.getVolumeId();
    final String secondaryStoragePoolUrl = command.getSecondaryStorageUrl();
    final String snapshotName = command.getSnapshotName();
    String snapshotDestPath = null;
    String snapshotRelPath = null;
    final String vmName = command.getVmName();
    KVMStoragePool secondaryStoragePool = null;
    final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
    try {
        final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
        final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
        secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
        final String ssPmountPath = secondaryStoragePool.getLocalPath();
        snapshotRelPath = File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
        snapshotDestPath = ssPmountPath + File.separator + "snapshots" + File.separator + dcId + File.separator + accountId + File.separator + volumeId;
        final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
        final KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(command.getVolumePath());
        final String manageSnapshotPath = libvirtComputingResource.manageSnapshotPath();
        final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
        /**
         * RBD snapshots can't be copied using qemu-img, so we have to use
         * the Java bindings for librbd here.
         *
         * These bindings will read the snapshot and write the contents to
         * the secondary storage directly
         *
         * It will stop doing so if the amount of time spend is longer then
         * cmds.timeout
         */
        if (primaryPool.getType() == StoragePoolType.RBD) {
            try {
                final Rados r = new Rados(primaryPool.getAuthUserName());
                r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
                r.confSet("key", primaryPool.getAuthSecret());
                r.confSet("client_mount_timeout", "30");
                r.connect();
                s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
                final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
                final Rbd rbd = new Rbd(io);
                final RbdImage image = rbd.open(snapshotDisk.getName(), snapshotName);
                final File fh = new File(snapshotDestPath);
                try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fh))) {
                    final int chunkSize = 4194304;
                    long offset = 0;
                    s_logger.debug("Backuping up RBD snapshot " + snapshotName + " to  " + snapshotDestPath);
                    while (true) {
                        final byte[] buf = new byte[chunkSize];
                        final int bytes = image.read(offset, buf, chunkSize);
                        if (bytes <= 0) {
                            break;
                        }
                        bos.write(buf, 0, bytes);
                        offset += bytes;
                    }
                    s_logger.debug("Completed backing up RBD snapshot " + snapshotName + " to  " + snapshotDestPath + ". Bytes written: " + toHumanReadableSize(offset));
                } catch (final IOException ex) {
                    s_logger.error("BackupSnapshotAnswer:Exception:" + ex.getMessage());
                }
                r.ioCtxDestroy(io);
            } catch (final RadosException e) {
                s_logger.error("A RADOS operation failed. The error was: " + e.getMessage());
                return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
            } catch (final RbdException e) {
                s_logger.error("A RBD operation on " + snapshotDisk.getName() + " failed. The error was: " + e.getMessage());
                return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
            }
        } else {
            final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
            scriptCommand.add("-b", snapshotDisk.getPath());
            scriptCommand.add("-n", snapshotName);
            scriptCommand.add("-p", snapshotDestPath);
            scriptCommand.add("-t", snapshotName);
            final String result = scriptCommand.execute();
            if (result != null) {
                s_logger.debug("Failed to backup snaptshot: " + result);
                return new BackupSnapshotAnswer(command, false, result, null, true);
            }
        }
        /* Delete the snapshot on primary */
        DomainState state = null;
        Domain vm = null;
        if (vmName != null) {
            try {
                vm = libvirtComputingResource.getDomain(conn, command.getVmName());
                state = vm.getInfo().state;
            } catch (final LibvirtException e) {
                s_logger.trace("Ignoring libvirt error.", e);
            }
        }
        final KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPool().getUuid());
        if (state == DomainState.VIR_DOMAIN_RUNNING && !primaryStorage.isExternalSnapshot()) {
            final MessageFormat snapshotXML = new MessageFormat("   <domainsnapshot>" + "       <name>{0}</name>" + "          <domain>" + "            <uuid>{1}</uuid>" + "        </domain>" + "    </domainsnapshot>");
            final String vmUuid = vm.getUUIDString();
            final Object[] args = new Object[] { snapshotName, vmUuid };
            final String snapshot = snapshotXML.format(args);
            s_logger.debug(snapshot);
            final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
            if (snap != null) {
                snap.delete(0);
            } else {
                throw new CloudRuntimeException("Unable to find vm snapshot with name -" + snapshotName);
            }
            /*
                 * libvirt on RHEL6 doesn't handle resume event emitted from
                 * qemu
                 */
            vm = libvirtComputingResource.getDomain(conn, command.getVmName());
            state = vm.getInfo().state;
            if (state == DomainState.VIR_DOMAIN_PAUSED) {
                vm.resume();
            }
        } else {
            final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
            scriptCommand.add("-d", snapshotDisk.getPath());
            scriptCommand.add("-n", snapshotName);
            final String result = scriptCommand.execute();
            if (result != null) {
                s_logger.debug("Failed to backup snapshot: " + result);
                return new BackupSnapshotAnswer(command, false, "Failed to backup snapshot: " + result, null, true);
            }
        }
    } catch (final LibvirtException e) {
        return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
    } catch (final CloudRuntimeException e) {
        return new BackupSnapshotAnswer(command, false, e.toString(), null, true);
    } finally {
        if (secondaryStoragePool != null) {
            storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(), secondaryStoragePool.getUuid());
        }
    }
    return new BackupSnapshotAnswer(command, true, null, snapshotRelPath + File.separator + snapshotName, true);
}
Also used : LibvirtException(org.libvirt.LibvirtException) RadosException(com.ceph.rados.exceptions.RadosException) KVMStoragePool(com.cloud.hypervisor.kvm.storage.KVMStoragePool) Rbd(com.ceph.rbd.Rbd) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) BufferedOutputStream(java.io.BufferedOutputStream) Script(com.cloud.utils.script.Script) KVMStoragePoolManager(com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager) MessageFormat(java.text.MessageFormat) KVMPhysicalDisk(com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk) Connect(org.libvirt.Connect) Rados(com.ceph.rados.Rados) DomainSnapshot(org.libvirt.DomainSnapshot) IOException(java.io.IOException) DomainState(org.libvirt.DomainInfo.DomainState) FileOutputStream(java.io.FileOutputStream) RbdImage(com.ceph.rbd.RbdImage) IoCTX(com.ceph.rados.IoCTX) BackupSnapshotAnswer(com.cloud.agent.api.BackupSnapshotAnswer) Domain(org.libvirt.Domain) File(java.io.File) RbdException(com.ceph.rbd.RbdException)

Example 12 with RbdImage

use of com.ceph.rbd.RbdImage in project cloudstack by apache.

the class LibvirtManageSnapshotCommandWrapper method execute.

@Override
public Answer execute(final ManageSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
    final String snapshotName = command.getSnapshotName();
    final String snapshotPath = command.getSnapshotPath();
    final String vmName = command.getVmName();
    try {
        final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
        final Connect conn = libvirtUtilitiesHelper.getConnectionByVmName(vmName);
        DomainState state = null;
        Domain vm = null;
        if (vmName != null) {
            try {
                vm = libvirtComputingResource.getDomain(conn, command.getVmName());
                state = vm.getInfo().state;
            } catch (final LibvirtException e) {
                s_logger.trace("Ignoring libvirt error.", e);
            }
        }
        final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
        final StorageFilerTO pool = command.getPool();
        final KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(pool.getType(), pool.getUuid());
        final KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(command.getVolumePath());
        if (state == DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
            final MessageFormat snapshotXML = new MessageFormat("   <domainsnapshot>" + "       <name>{0}</name>" + "          <domain>" + "            <uuid>{1}</uuid>" + "        </domain>" + "    </domainsnapshot>");
            final String vmUuid = vm.getUUIDString();
            final Object[] args = new Object[] { snapshotName, vmUuid };
            final String snapshot = snapshotXML.format(args);
            s_logger.debug(snapshot);
            if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
                vm.snapshotCreateXML(snapshot);
            } else {
                final DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
                snap.delete(0);
            }
            /*
                 * libvirt on RHEL6 doesn't handle resume event emitted from
                 * qemu
                 */
            vm = libvirtComputingResource.getDomain(conn, command.getVmName());
            state = vm.getInfo().state;
            if (state == DomainState.VIR_DOMAIN_PAUSED) {
                vm.resume();
            }
        } else {
            /**
             * For RBD we can't use libvirt to do our snapshotting or any Bash scripts.
             * libvirt also wants to store the memory contents of the Virtual Machine,
             * but that's not possible with RBD since there is no way to store the memory
             * contents in RBD.
             *
             * So we rely on the Java bindings for RBD to create our snapshot
             *
             * This snapshot might not be 100% consistent due to writes still being in the
             * memory of the Virtual Machine, but if the VM runs a kernel which supports
             * barriers properly (>2.6.32) this won't be any different then pulling the power
             * cord out of a running machine.
             */
            if (primaryPool.getType() == StoragePoolType.RBD) {
                try {
                    final Rados r = new Rados(primaryPool.getAuthUserName());
                    r.confSet("mon_host", primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
                    r.confSet("key", primaryPool.getAuthSecret());
                    r.confSet("client_mount_timeout", "30");
                    r.connect();
                    s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
                    final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
                    final Rbd rbd = new Rbd(io);
                    final RbdImage image = rbd.open(disk.getName());
                    if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
                        s_logger.debug("Attempting to create RBD snapshot " + disk.getName() + "@" + snapshotName);
                        image.snapCreate(snapshotName);
                    } else {
                        s_logger.debug("Attempting to remove RBD snapshot " + disk.getName() + "@" + snapshotName);
                        image.snapRemove(snapshotName);
                    }
                    rbd.close(image);
                    r.ioCtxDestroy(io);
                } catch (final Exception e) {
                    s_logger.error("A RBD snapshot operation on " + disk.getName() + " failed. The error was: " + e.getMessage());
                }
            } else {
                /* VM is not running, create a snapshot by ourself */
                final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
                final String manageSnapshotPath = libvirtComputingResource.manageSnapshotPath();
                final Script scriptCommand = new Script(manageSnapshotPath, cmdsTimeout, s_logger);
                if (command.getCommandSwitch().equalsIgnoreCase(ManageSnapshotCommand.CREATE_SNAPSHOT)) {
                    scriptCommand.add("-c", disk.getPath());
                } else {
                    scriptCommand.add("-d", snapshotPath);
                }
                scriptCommand.add("-n", snapshotName);
                final String result = scriptCommand.execute();
                if (result != null) {
                    s_logger.debug("Failed to manage snapshot: " + result);
                    return new ManageSnapshotAnswer(command, false, "Failed to manage snapshot: " + result);
                }
            }
        }
        return new ManageSnapshotAnswer(command, command.getSnapshotId(), disk.getPath() + File.separator + snapshotName, true, null);
    } catch (final LibvirtException e) {
        s_logger.debug("Failed to manage snapshot: " + e.toString());
        return new ManageSnapshotAnswer(command, false, "Failed to manage snapshot: " + e.toString());
    }
}
Also used : Script(com.cloud.utils.script.Script) KVMStoragePoolManager(com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager) LibvirtException(org.libvirt.LibvirtException) MessageFormat(java.text.MessageFormat) KVMPhysicalDisk(com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk) Connect(org.libvirt.Connect) DomainSnapshot(org.libvirt.DomainSnapshot) Rados(com.ceph.rados.Rados) ManageSnapshotAnswer(com.cloud.agent.api.ManageSnapshotAnswer) StorageFilerTO(com.cloud.agent.api.to.StorageFilerTO) LibvirtException(org.libvirt.LibvirtException) KVMStoragePool(com.cloud.hypervisor.kvm.storage.KVMStoragePool) DomainState(org.libvirt.DomainInfo.DomainState) Rbd(com.ceph.rbd.Rbd) RbdImage(com.ceph.rbd.RbdImage) IoCTX(com.ceph.rados.IoCTX) Domain(org.libvirt.Domain)

Example 13 with RbdImage

use of com.ceph.rbd.RbdImage in project cloudstack by apache.

the class KVMStorageProcessor method createSnapshot.

@Override
public Answer createSnapshot(final CreateObjectCommand cmd) {
    final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) cmd.getData();
    final PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) snapshotTO.getDataStore();
    final VolumeObjectTO volume = snapshotTO.getVolume();
    final String snapshotName = UUID.randomUUID().toString();
    final String vmName = volume.getVmName();
    try {
        final Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
        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 primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(), primaryStore.getUuid());
        final KVMPhysicalDisk disk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volume.getPath());
        if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING && !primaryPool.isExternalSnapshot()) {
            final String vmUuid = vm.getUUIDString();
            final Object[] args = new Object[] { snapshotName, vmUuid };
            final String snapshot = SnapshotXML.format(args);
            final long start = System.currentTimeMillis();
            vm.snapshotCreateXML(snapshot);
            final long total = (System.currentTimeMillis() - start) / 1000;
            s_logger.debug("snapshot takes " + total + " seconds to finish");
            /*
                 * 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 {
            /**
             * For RBD we can't use libvirt to do our snapshotting or any Bash scripts.
             * libvirt also wants to store the memory contents of the Virtual Machine,
             * but that's not possible with RBD since there is no way to store the memory
             * contents in RBD.
             *
             * So we rely on the Java bindings for RBD to create our snapshot
             *
             * This snapshot might not be 100% consistent due to writes still being in the
             * memory of the Virtual Machine, but if the VM runs a kernel which supports
             * barriers properly (>2.6.32) this won't be any different then pulling the power
             * cord out of a running machine.
             */
            if (primaryPool.getType() == StoragePoolType.RBD) {
                try {
                    Rados r = radosConnect(primaryPool);
                    final IoCTX io = r.ioCtxCreate(primaryPool.getSourceDir());
                    final Rbd rbd = new Rbd(io);
                    final RbdImage image = rbd.open(disk.getName());
                    s_logger.debug("Attempting to create RBD snapshot " + disk.getName() + "@" + snapshotName);
                    image.snapCreate(snapshotName);
                    rbd.close(image);
                    r.ioCtxDestroy(io);
                } catch (final Exception e) {
                    s_logger.error("A RBD snapshot operation on " + disk.getName() + " failed. The error was: " + e.getMessage());
                }
            } else {
                /* VM is not running, create a snapshot by ourself */
                final Script command = new Script(_manageSnapshotPath, _cmdsTimeout, s_logger);
                command.add(MANAGE_SNAPSTHOT_CREATE_OPTION, disk.getPath());
                command.add(NAME_OPTION, snapshotName);
                final String result = command.execute();
                if (result != null) {
                    s_logger.debug("Failed to manage snapshot: " + result);
                    return new CreateObjectAnswer("Failed to manage snapshot: " + result);
                }
            }
        }
        final SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
        // NOTE: sort of hack, we'd better just put snapshtoName
        newSnapshot.setPath(disk.getPath() + File.separator + snapshotName);
        return new CreateObjectAnswer(newSnapshot);
    } catch (final LibvirtException e) {
        s_logger.debug("Failed to manage snapshot: ", e);
        return new CreateObjectAnswer("Failed to manage snapshot: " + e.toString());
    }
}
Also used : SnapshotObjectTO(org.apache.cloudstack.storage.to.SnapshotObjectTO) Script(com.cloud.utils.script.Script) LibvirtException(org.libvirt.LibvirtException) Connect(org.libvirt.Connect) Rados(com.ceph.rados.Rados) CreateObjectAnswer(org.apache.cloudstack.storage.command.CreateObjectAnswer) RbdException(com.ceph.rbd.RbdException) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InvalidParameterValueException(com.cloud.exception.InvalidParameterValueException) LibvirtException(org.libvirt.LibvirtException) QemuImgException(org.apache.cloudstack.utils.qemu.QemuImgException) FileNotFoundException(java.io.FileNotFoundException) InternalErrorException(com.cloud.exception.InternalErrorException) ConfigurationException(javax.naming.ConfigurationException) RadosException(com.ceph.rados.exceptions.RadosException) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) Rbd(com.ceph.rbd.Rbd) RbdImage(com.ceph.rbd.RbdImage) VolumeObjectTO(org.apache.cloudstack.storage.to.VolumeObjectTO) IoCTX(com.ceph.rados.IoCTX) DomainInfo(org.libvirt.DomainInfo) Domain(org.libvirt.Domain)

Example 14 with RbdImage

use of com.ceph.rbd.RbdImage 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)

Example 15 with RbdImage

use of com.ceph.rbd.RbdImage in project cloudstack by apache.

the class LibvirtRevertSnapshotCommandWrapper method execute.

@Override
public Answer execute(final RevertSnapshotCommand command, final LibvirtComputingResource libvirtComputingResource) {
    SnapshotObjectTO snapshot = command.getData();
    VolumeObjectTO volume = snapshot.getVolume();
    PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO) volume.getDataStore();
    DataStoreTO snapshotImageStore = snapshot.getDataStore();
    if (!(snapshotImageStore instanceof NfsTO) && primaryStore.getPoolType() != StoragePoolType.RBD) {
        return new Answer(command, false, String.format("Revert snapshot does not support storage pool of type [%s]. Revert snapshot is supported by storage pools of type 'NFS' or 'RBD'", primaryStore.getPoolType()));
    }
    String volumePath = volume.getPath();
    String snapshotPath = null;
    String snapshotRelPath = null;
    KVMStoragePool secondaryStoragePool = null;
    try {
        snapshotRelPath = snapshot.getPath();
        KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
        KVMPhysicalDisk snapshotDisk = storagePoolMgr.getPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), volumePath);
        KVMStoragePool primaryPool = snapshotDisk.getPool();
        if (primaryPool.getType() == StoragePoolType.RBD) {
            Rados rados = new Rados(primaryPool.getAuthUserName());
            rados.confSet(MON_HOST, primaryPool.getSourceHost() + ":" + primaryPool.getSourcePort());
            rados.confSet(KEY, primaryPool.getAuthSecret());
            rados.confSet(CLIENT_MOUNT_TIMEOUT, RADOS_CONNECTION_TIMEOUT);
            rados.connect();
            String[] rbdPoolAndVolumeAndSnapshot = snapshotRelPath.split("/");
            int snapshotIndex = rbdPoolAndVolumeAndSnapshot.length - 1;
            String rbdSnapshotId = rbdPoolAndVolumeAndSnapshot[snapshotIndex];
            IoCTX io = rados.ioCtxCreate(primaryPool.getSourceDir());
            Rbd rbd = new Rbd(io);
            s_logger.debug(String.format("Attempting to rollback RBD snapshot [name:%s], [volumeid:%s], [snapshotid:%s]", snapshot.getName(), volumePath, rbdSnapshotId));
            RbdImage image = rbd.open(volumePath);
            image.snapRollBack(rbdSnapshotId);
            rbd.close(image);
            rados.ioCtxDestroy(io);
        } else {
            NfsTO nfsImageStore = (NfsTO) snapshotImageStore;
            String secondaryStoragePoolUrl = nfsImageStore.getUrl();
            secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(secondaryStoragePoolUrl);
            String ssPmountPath = secondaryStoragePool.getLocalPath();
            snapshotPath = ssPmountPath + File.separator + snapshotRelPath;
            Script cmd = new Script(libvirtComputingResource.manageSnapshotPath(), libvirtComputingResource.getCmdsTimeout(), s_logger);
            cmd.add("-v", snapshotPath);
            cmd.add("-n", snapshotDisk.getName());
            cmd.add("-p", snapshotDisk.getPath());
            String result = cmd.execute();
            if (result != null) {
                s_logger.debug("Failed to revert snaptshot: " + result);
                return new Answer(command, false, result);
            }
        }
        return new Answer(command, true, "RevertSnapshotCommand executes successfully");
    } catch (CloudRuntimeException e) {
        return new Answer(command, false, e.toString());
    } catch (RadosException e) {
        s_logger.error("Failed to connect to Rados pool while trying to revert snapshot. Exception: ", e);
        return new Answer(command, false, e.toString());
    } catch (RbdException e) {
        s_logger.error("Failed to connect to revert snapshot due to RBD exception: ", e);
        return new Answer(command, false, e.toString());
    }
}
Also used : SnapshotObjectTO(org.apache.cloudstack.storage.to.SnapshotObjectTO) Script(com.cloud.utils.script.Script) DataStoreTO(com.cloud.agent.api.to.DataStoreTO) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) KVMStoragePoolManager(com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager) KVMPhysicalDisk(com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk) Rados(com.ceph.rados.Rados) RadosException(com.ceph.rados.exceptions.RadosException) NfsTO(com.cloud.agent.api.to.NfsTO) Answer(com.cloud.agent.api.Answer) KVMStoragePool(com.cloud.hypervisor.kvm.storage.KVMStoragePool) PrimaryDataStoreTO(org.apache.cloudstack.storage.to.PrimaryDataStoreTO) Rbd(com.ceph.rbd.Rbd) CloudRuntimeException(com.cloud.utils.exception.CloudRuntimeException) RbdImage(com.ceph.rbd.RbdImage) VolumeObjectTO(org.apache.cloudstack.storage.to.VolumeObjectTO) IoCTX(com.ceph.rados.IoCTX) RbdException(com.ceph.rbd.RbdException)

Aggregations

IoCTX (com.ceph.rados.IoCTX)15 Rados (com.ceph.rados.Rados)15 Rbd (com.ceph.rbd.Rbd)15 RbdImage (com.ceph.rbd.RbdImage)15 RadosException (com.ceph.rados.exceptions.RadosException)12 RbdException (com.ceph.rbd.RbdException)12 LibvirtException (org.libvirt.LibvirtException)11 CloudRuntimeException (com.cloud.utils.exception.CloudRuntimeException)10 Script (com.cloud.utils.script.Script)7 Connect (org.libvirt.Connect)6 Domain (org.libvirt.Domain)6 RbdSnapInfo (com.ceph.rbd.jna.RbdSnapInfo)5 IOException (java.io.IOException)5 DomainState (org.libvirt.DomainInfo.DomainState)5 MessageFormat (java.text.MessageFormat)4 InternalErrorException (com.cloud.exception.InternalErrorException)3 KVMPhysicalDisk (com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk)3 KVMStoragePool (com.cloud.hypervisor.kvm.storage.KVMStoragePool)3 KVMStoragePoolManager (com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager)3 QemuImgException (com.cloud.utils.qemu.QemuImgException)3