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;
}
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());
}
}
Aggregations