From: Bill Owen Date: Mon, 18 Nov 2013 22:52:00 +0000 (-0700) Subject: Add support for extend volume in GPFS vol driver X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=0d3e9c32869a77574dee07a0556de87ba7cdb2e5;p=openstack-build%2Fcinder-build.git Add support for extend volume in GPFS vol driver Add support for extend volume support to the GPFS volume driver. Ensure that requested volume size is implemented for each of the volume creation paths. Replace instances where units.GiB could be used but was not. Implements: blueprint gpfs-extend-volume-support Change-Id: I79295205f4147fca109f5cb59497a6e1fbe6d296 --- diff --git a/cinder/tests/test_gpfs.py b/cinder/tests/test_gpfs.py index f6909a17e..3dd7eaf1e 100644 --- a/cinder/tests/test_gpfs.py +++ b/cinder/tests/test_gpfs.py @@ -14,6 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. +import mox as mox_lib import os import tempfile @@ -23,6 +24,7 @@ from cinder import context from cinder import db from cinder import exception from cinder.image import image_utils +from cinder.openstack.common import imageutils from cinder.openstack.common import importutils from cinder.openstack.common import log as logging from cinder.openstack.common import processutils @@ -362,6 +364,43 @@ class GPFSDriverTestCase(test.TestCase): self.assertEqual(stats['volume_backend_name'], 'GPFS') self.assertEqual(stats['storage_protocol'], 'file') + def test_extend_volume(self): + new_vol_size = 15 + mox = mox_lib.Mox() + volume = test_utils.create_volume(self.context, host=CONF.host) + volpath = os.path.join(self.volumes_path, volume['name']) + + qemu_img_info_output = """image: %s + file format: raw + virtual size: %sG (%s bytes) + backing file: %s + """ % (volume['name'], new_vol_size, new_vol_size * units.GiB, volpath) + mox.StubOutWithMock(image_utils, 'resize_image') + image_utils.resize_image(volpath, new_vol_size) + + mox.StubOutWithMock(image_utils, 'qemu_img_info') + img_info = imageutils.QemuImgInfo(qemu_img_info_output) + image_utils.qemu_img_info(volpath).AndReturn(img_info) + mox.ReplayAll() + + self.driver.extend_volume(volume, new_vol_size) + mox.VerifyAll() + + def test_extend_volume_with_failure(self): + new_vol_size = 15 + mox = mox_lib.Mox() + volume = test_utils.create_volume(self.context, host=CONF.host) + volpath = os.path.join(self.volumes_path, volume['name']) + + mox.StubOutWithMock(image_utils, 'resize_image') + image_utils.resize_image(volpath, new_vol_size).AndRaise( + processutils.ProcessExecutionError('error')) + mox.ReplayAll() + + self.assertRaises(exception.VolumeBackendAPIException, + self.driver.extend_volume, volume, new_vol_size) + mox.VerifyAll() + def test_check_for_setup_error_ok(self): self.stubs.Set(GPFSDriver, '_get_gpfs_state', self._fake_gpfs_get_state_active) @@ -497,6 +536,7 @@ class GPFSDriverTestCase(test.TestCase): return data def _fake_qemu_image_resize(self, path, size): + LOG.info('wtf') pass def _fake_delete_gpfs_file(self, fchild): diff --git a/cinder/volume/drivers/gpfs.py b/cinder/volume/drivers/gpfs.py index f64d67feb..407bd5956 100644 --- a/cinder/volume/drivers/gpfs.py +++ b/cinder/volume/drivers/gpfs.py @@ -287,15 +287,15 @@ class GPFSDriver(driver.VolumeDriver): snapshot_path = self.local_path(snapshot) self._create_gpfs_copy(src=snapshot_path, dest=volume_path) self._gpfs_redirect(volume_path) - data = image_utils.qemu_img_info(volume_path) - return {'size': math.ceil(data.virtual_size / 1024.0 ** 3)} + virt_size = self._resize_volume_file(volume, volume['size']) + return {'size': math.ceil(virt_size / units.GiB)} def create_cloned_volume(self, volume, src_vref): src = self.local_path(src_vref) dest = self.local_path(volume) self._create_gpfs_clone(src, dest) - data = image_utils.qemu_img_info(dest) - return {'size': math.ceil(data.virtual_size / 1024.0 ** 3)} + virt_size = self._resize_volume_file(volume, volume['size']) + return {'size': math.ceil(virt_size / units.GiB)} def _delete_gpfs_file(self, fchild): if not os.path.exists(fchild): @@ -452,8 +452,8 @@ class GPFSDriver(driver.VolumeDriver): data["storage_protocol"] = 'file' free, capacity = self._get_available_capacity(self.configuration. gpfs_mount_point_base) - data['total_capacity_gb'] = math.ceil(capacity / 1024.0 ** 3) - data['free_capacity_gb'] = math.ceil(free / 1024.0 ** 3) + data['total_capacity_gb'] = math.ceil(capacity / units.GiB) + data['free_capacity_gb'] = math.ceil(free / units.GiB) data['reserved_percentage'] = 0 data['QoS_support'] = False self._stats = data @@ -526,7 +526,7 @@ class GPFSDriver(driver.VolumeDriver): image_utils.convert_image(image_path, vol_path, 'raw') self._execute('chmod', '666', vol_path, run_as_root=True) - image_utils.resize_image(vol_path, volume['size']) + self._resize_volume_file(volume, volume['size']) return {'provider_location': None}, True @@ -546,7 +546,26 @@ class GPFSDriver(driver.VolumeDriver): volume['id']) image_utils.fetch_to_raw(context, image_service, image_id, self.local_path(volume), size=volume['size']) - image_utils.resize_image(self.local_path(volume), volume['size']) + self._resize_volume_file(volume, volume['size']) + + def _resize_volume_file(self, volume, new_size): + """Resize volume file to new size.""" + vol_path = self.local_path(volume) + try: + image_utils.resize_image(vol_path, new_size) + except processutils.ProcessExecutionError as exc: + LOG.error(_("Failed to resize volume " + "%(volume_id)s, error: %(error)s") % + {'volume_id': volume['id'], + 'error': exc.stderr}) + raise exception.VolumeBackendAPIException(data=exc.stderr) + + data = image_utils.qemu_img_info(vol_path) + return data.virtual_size + + def extend_volume(self, volume, new_size): + """Extend an existing volume.""" + self._resize_volume_file(volume, new_size) def copy_volume_to_image(self, context, volume, image_service, image_meta): """Copy the volume to the specified image."""