From 9c41319a1007cc484ba18482d2a19b15970640b6 Mon Sep 17 00:00:00 2001 From: lihaijing Date: Tue, 19 Jun 2018 13:37:45 +0800 Subject: [PATCH] Fix vmware disk type changed when volume type is eagerZeroedThick Create a volume from an image, choose "eagerZeroedThick" volume_type. But login in Vcenter, you will get a "lazyZeroedThick" volume. There is no problem when creating a blank vmware volume. The reason is: when creating a volume from image, if volueme_size > image_size, the last step is to extend backing volume. In the method extend_virtual_disk(), there is a parameter "eager_zero", which determining if the free space is zeroed out. The param "eager_zero" default value is "False", and not to be changed to "True" in creating an eagerZeroedThick volume from an image. So the actuall volume type is different with designated volume type. We can add a paramter "disk_type" in _extend_backing() method, determining which type disk to extend. Then pass "False" or "True" to extend_virtual_disk() as "eager_zero". Change-Id: I29978b69d21c2583da152f9fbf1264ada8f079e6 Closes-Bug: #1777430 --- .../volume/drivers/vmware/test_vmware_vmdk.py | 59 ++++++++++++++----- cinder/volume/drivers/vmware/vmdk.py | 20 ++++--- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py b/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py index 831873a7d7f..1b38c2b4fc4 100644 --- a/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py +++ b/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py @@ -581,6 +581,7 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): image_id) validate_disk_format.assert_called_once_with(image_meta['disk_format']) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch('cinder.volume.drivers.vmware.vmdk.VMwareVcVmdkDriver.' '_validate_disk_format') @mock.patch.object(VMDK_DRIVER, '_get_adapter_type', @@ -604,6 +605,7 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): validate_image_adapter_type, get_adapter_type, validate_disk_format, + get_disk_type, vmware_disk_type='streamOptimized', backing_disk_size=VOL_SIZE, call_extend_backing=False, @@ -618,6 +620,9 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.get_backing.return_value = backing vops.get_disk_size.return_value = backing_disk_size * units.Gi + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type + context = mock.sentinel.context volume = self._create_volume_dict() image_id = mock.sentinel.image_id @@ -642,7 +647,8 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.get_disk_size.assert_called_once_with(backing) if call_extend_backing: - extend_backing.assert_called_once_with(backing, volume['size']) + extend_backing.assert_called_once_with(backing, volume['size'], + disk_type) else: self.assertFalse(extend_backing.called) @@ -1578,16 +1584,19 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.get_vmdk_path.return_value = vmdk_path dc = mock.sentinel.datacenter vops.get_dc.return_value = dc + disk_type = mock.sentinel.disk_type + eager_zero = (True if disk_type == "eagerZeroedThick" else False) backing = mock.sentinel.backing new_size = 1 - self._driver._extend_backing(backing, new_size) + self._driver._extend_backing(backing, new_size, disk_type) vops.get_vmdk_path.assert_called_once_with(backing) vops.get_dc.assert_called_once_with(backing) vops.extend_virtual_disk.assert_called_once_with(new_size, vmdk_path, - dc) + dc, + eager_zero) @mock.patch.object(VMDK_DRIVER, 'session') @mock.patch('oslo_vmware.vim_util.get_vc_version') @@ -2025,11 +2034,12 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): volume['volume_type_id'], 'clone_type', default_value=volumeops.FULL_CLONE_TYPE) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume') @mock.patch.object(VMDK_DRIVER, '_extend_backing') def _test_clone_backing( - self, extend_backing, select_ds_for_volume, vops, + self, extend_backing, select_ds_for_volume, vops, get_disk_type, clone_type=volumeops.FULL_CLONE_TYPE, extend_needed=False, vc60=False): host = mock.sentinel.host @@ -2042,6 +2052,9 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): clone = mock.sentinel.clone vops.clone_backing.return_value = clone + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type + if vc60: self._driver._vc_version = '6.0' else: @@ -2091,7 +2104,8 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.update_backing_disk_uuid.assert_not_called() if volume.size > src_vsize: - extend_backing.assert_called_once_with(clone, volume.size) + extend_backing.assert_called_once_with(clone, volume.size, + disk_type) else: extend_backing.assert_not_called() @@ -2284,10 +2298,13 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): host=host, resource_pool=rp, folder=folder, disks_to_clone=[vol_dev_uuid]) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_extend_backing') def _test_extend_backing_if_needed( - self, extend_backing, vops, extend=True): + self, extend_backing, vops, get_disk_type, extend=True): + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type if extend: vol_size = 2 else: @@ -2301,7 +2318,8 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.get_disk_size.assert_called_once_with(backing) if extend: - extend_backing.assert_called_once_with(backing, vol_size) + extend_backing.assert_called_once_with(backing, vol_size, + disk_type) else: extend_backing.assert_not_called() @@ -3106,26 +3124,35 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): self.assertFalse(extend_backing.called) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_extend_backing') - def test_extend_volume(self, extend_backing, vops): + def test_extend_volume(self, extend_backing, vops, get_disk_type): backing = mock.sentinel.backing vops.get_backing.return_value = backing + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type + volume = self._create_volume_dict() new_size = 2 self._driver.extend_volume(volume, new_size) - extend_backing.assert_called_once_with(backing, new_size) + extend_backing.assert_called_once_with(backing, new_size, disk_type) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_extend_backing') @mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume') def test_extend_volume_with_no_disk_space(self, select_ds_for_volume, - extend_backing, vops): + extend_backing, vops, + get_disk_type): backing = mock.sentinel.backing vops.get_backing.return_value = backing + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type + extend_backing.side_effect = [exceptions.NoDiskSpaceException, None] host = mock.sentinel.host @@ -3147,24 +3174,28 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): host) vops.move_backing_to_folder(backing, folder) - extend_backing_calls = [mock.call(backing, new_size), - mock.call(backing, new_size)] + extend_backing_calls = [mock.call(backing, new_size, disk_type), + mock.call(backing, new_size, disk_type)] self.assertEqual(extend_backing_calls, extend_backing.call_args_list) + @mock.patch.object(VMDK_DRIVER, '_get_disk_type') @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_extend_backing') def test_extend_volume_with_extend_backing_error( - self, extend_backing, vops): + self, extend_backing, vops, get_disk_type): backing = mock.sentinel.backing vops.get_backing.return_value = backing + disk_type = mock.sentinel.disk_type + get_disk_type.return_value = disk_type + extend_backing.side_effect = exceptions.VimException("Error") volume = self._create_volume_dict() new_size = 2 self.assertRaises(exceptions.VimException, self._driver.extend_volume, volume, new_size) - extend_backing.assert_called_once_with(backing, new_size) + extend_backing.assert_called_once_with(backing, new_size, disk_type) @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch.object(VMDK_DRIVER, '_get_volume_group_folder') diff --git a/cinder/volume/drivers/vmware/vmdk.py b/cinder/volume/drivers/vmware/vmdk.py index be7e8b5a455..df3974b4ef2 100644 --- a/cinder/volume/drivers/vmware/vmdk.py +++ b/cinder/volume/drivers/vmware/vmdk.py @@ -1273,7 +1273,7 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): LOG.info("Done copying image: %(id)s to volume: %(vol)s.", {'id': image_id, 'vol': volume['name']}) - def _extend_backing(self, backing, new_size_in_gb): + def _extend_backing(self, backing, new_size_in_gb, disk_type): """Extend volume backing's virtual disk. :param backing: volume backing @@ -1281,8 +1281,9 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): """ root_vmdk_path = self.volumeops.get_vmdk_path(backing) datacenter = self.volumeops.get_dc(backing) + eager_zero = disk_type == EAGER_ZEROED_THICK_VMDK_TYPE self.volumeops.extend_virtual_disk(new_size_in_gb, root_vmdk_path, - datacenter) + datacenter, eager_zero) def copy_image_to_volume(self, context, volume, image_service, image_id): """Creates volume from image. @@ -1359,7 +1360,8 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): {'name': volume['name'], 'vol_size': volume_size, 'disk_size': disk_size}) - self._extend_backing(backing, volume['size']) + self._extend_backing(backing, volume['size'], + VMwareVcVmdkDriver._get_disk_type(volume)) # TODO(vbala): handle volume_size < disk_size case. def copy_volume_to_image(self, context, volume, image_service, image_meta): @@ -1623,7 +1625,8 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): # try extending vmdk in place try: - self._extend_backing(backing, new_size) + self._extend_backing(backing, new_size, + VMwareVcVmdkDriver._get_disk_type(volume)) LOG.info("Successfully extended volume: %(vol)s to size: " "%(size)s GB.", {'vol': vol_name, 'size': new_size}) @@ -1646,7 +1649,8 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): self.volumeops.relocate_backing(backing, summary.datastore, rp, host) self.volumeops.move_backing_to_folder(backing, folder) - self._extend_backing(backing, new_size) + self._extend_backing(backing, new_size, + VMwareVcVmdkDriver._get_disk_type(volume)) except exceptions.VMwareDriverException: with excutils.save_and_reraise_exception(): LOG.error("Failed to extend volume: %(vol)s to size: " @@ -2031,7 +2035,8 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): # we need to extend/resize the capacity of the vmdk virtual disk from # the size of the source volume to the volume size. if volume['size'] > src_vsize: - self._extend_backing(clone, volume['size']) + self._extend_backing(clone, volume['size'], + VMwareVcVmdkDriver._get_disk_type(volume)) LOG.info("Successfully created clone: %s.", clone) def _create_volume_from_template(self, volume, path): @@ -2129,7 +2134,8 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): volume_size = volume.size * units.Gi disk_size = self.volumeops.get_disk_size(backing) if volume_size > disk_size: - self._extend_backing(backing, volume.size) + self._extend_backing(backing, volume.size, + VMwareVcVmdkDriver._get_disk_type(volume)) def _create_volume_from_temp_backing(self, volume, tmp_backing): try: