CLOUDSTACK-4278: Fix resizing RBD volumes Although libvirt supports resizing RBD volumes (and other formats) the Java bindings (libvirt-java) don't.
Right now we use the Java bindings for librbd to handle the resizing for us, but in the future this should be done by libvirt rather then these Java bindings. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/97cad491 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/97cad491 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/97cad491 Branch: refs/heads/4.2 Commit: 97cad491acb529b1ae2e272ab44cc58053d844f7 Parents: e40043f Author: Wido den Hollander <[email protected]> Authored: Wed Aug 14 16:13:30 2013 +0200 Committer: Wido den Hollander <[email protected]> Committed: Wed Aug 14 16:17:37 2013 +0200 ---------------------------------------------------------------------- .../kvm/resource/LibvirtComputingResource.java | 81 ++++++++++++++------ .../kvm/storage/LibvirtStorageAdaptor.java | 11 ++- pom.xml | 2 +- 3 files changed, 65 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/97cad491/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 5aab7bd..d2534d1 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1567,35 +1567,66 @@ ServerResource { String path = vol.getPath(); String type = getResizeScriptType(pool, vol); - if (type == null) { - return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" - + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); - } else if (type.equals("QCOW2") && shrinkOk) { - return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); - } - - s_logger.debug("got to the stage where we execute the volume resize, params:" - + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); - final Script resizecmd = new Script(_resizeVolumePath, - _cmdsTimeout, s_logger); - resizecmd.add("-s",String.valueOf(newSize)); - resizecmd.add("-c",String.valueOf(currentSize)); - resizecmd.add("-p",path); - resizecmd.add("-t",type); - resizecmd.add("-r",String.valueOf(shrinkOk)); - resizecmd.add("-v",vmInstanceName); - String result = resizecmd.execute(); + /** + * RBD volumes can't be resized via a Bash script or via libvirt + * + * libvirt-java doesn't implemented resizing volumes, so we have to do this manually + * + * Future fix would be to hand this over to libvirt + */ + if (pool.getType() == StoragePoolType.RBD) { + try { + Rados r = new Rados(pool.getAuthUserName()); + r.confSet("mon_host", pool.getSourceHost() + ":" + pool.getSourcePort()); + r.confSet("key", pool.getAuthSecret()); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); - if (result == null) { + IoCTX io = r.ioCtxCreate(pool.getSourceDir()); + Rbd rbd = new Rbd(io); + RbdImage image = rbd.open(vol.getName()); - /* fetch new size as seen from libvirt, don't want to assume anything */ - pool = _storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); - long finalSize = pool.getPhysicalDisk(volid).getVirtualSize(); - s_logger.debug("after resize, size reports as " + finalSize + ", requested " + newSize); - return new ResizeVolumeAnswer(cmd, true, "success", finalSize); + s_logger.debug("Resizing RBD volume " + vol.getName() + " to " + newSize + " bytes"); + image.resize(newSize); + rbd.close(image); + + r.ioCtxDestroy(io); + s_logger.debug("Succesfully resized RBD volume " + vol.getName() + " to " + newSize + " bytes"); + } catch (RadosException e) { + return new ResizeVolumeAnswer(cmd, false, e.toString()); + } catch (RbdException e) { + return new ResizeVolumeAnswer(cmd, false, e.toString()); + } + } else { + if (type == null) { + return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); + } else if (type.equals("QCOW2") && shrinkOk) { + return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); + } + + s_logger.debug("got to the stage where we execute the volume resize, params:" + + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); + final Script resizecmd = new Script(_resizeVolumePath, + _cmdsTimeout, s_logger); + resizecmd.add("-s",String.valueOf(newSize)); + resizecmd.add("-c",String.valueOf(currentSize)); + resizecmd.add("-p",path); + resizecmd.add("-t",type); + resizecmd.add("-r",String.valueOf(shrinkOk)); + resizecmd.add("-v",vmInstanceName); + String result = resizecmd.execute(); + + if (result != null) { + return new ResizeVolumeAnswer(cmd, false, result); + } } - return new ResizeVolumeAnswer(cmd, false, result); + /* fetch new size as seen from libvirt, don't want to assume anything */ + pool = _storagePoolMgr.getStoragePool(spool.getType(), spool.getUuid()); + long finalSize = pool.getPhysicalDisk(volid).getVirtualSize(); + s_logger.debug("after resize, size reports as " + finalSize + ", requested " + newSize); + return new ResizeVolumeAnswer(cmd, true, "success", finalSize); } catch (CloudRuntimeException e) { String error = "failed to resize volume: " + e; s_logger.debug(error); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/97cad491/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index f93eb37..d487e3c 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -414,7 +414,14 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { disk = new KVMPhysicalDisk(vol.getPath(), vol.getName(), pool); disk.setSize(vol.getInfo().allocation); disk.setVirtualSize(vol.getInfo().capacity); - if (voldef.getFormat() == null) { + + /** + * libvirt returns format = 'unknow', so we have to force + * the format to RAW for RBD storage volumes + */ + if (pool.getType() == StoragePoolType.RBD) { + disk.setFormat(PhysicalDiskFormat.RAW); + } else if (voldef.getFormat() == null) { File diskDir = new File(disk.getPath()); if (diskDir.exists() && diskDir.isDirectory()) { disk.setFormat(PhysicalDiskFormat.DIR); @@ -423,8 +430,6 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } else { disk.setFormat(pool.getDefaultFormat()); } - } else if (pool.getType() == StoragePoolType.RBD) { - disk.setFormat(PhysicalDiskFormat.RAW); } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) { disk.setFormat(PhysicalDiskFormat.QCOW2); } else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.RAW) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/97cad491/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 259e810..e8c4be8 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ <cs.java-ipv6.version>0.10</cs.java-ipv6.version> <cs.replace.properties>build/replace.properties</cs.replace.properties> <cs.libvirt-java.version>0.4.9</cs.libvirt-java.version> - <cs.rados-java.version>0.1.2</cs.rados-java.version> + <cs.rados-java.version>0.1.3</cs.rados-java.version> <cs.target.dir>target</cs.target.dir> <cs.daemon.version>1.0.10</cs.daemon.version> <cs.jna.version>3.0.9</cs.jna.version>
