From b07c1a759c8a0cdaaaaaf3e6f1ad7402bf631a44 Mon Sep 17 00:00:00 2001 From: Vipin Balachandran Date: Thu, 5 Jun 2014 16:21:27 +0530 Subject: [PATCH] VMware:Fix params for copy-image-to-volume While creating a volume from stream-optimized image, the adapter type in the image meta-data and the profile in the volume type extra spec are ignored. This change fix those missing parameters. Partial-Bug: #1284284 Closes-Bug: #1332482 Change-Id: I46c4755989fe61e0e654ca6daa3c3af0655071f0 --- cinder/tests/test_vmware_vmdk.py | 22 ++++++++++++--- cinder/volume/drivers/vmware/vmdk.py | 42 ++++++++++++++++++---------- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/cinder/tests/test_vmware_vmdk.py b/cinder/tests/test_vmware_vmdk.py index 51c2f53b4..08afb6d7f 100644 --- a/cinder/tests/test_vmware_vmdk.py +++ b/cinder/tests/test_vmware_vmdk.py @@ -1027,10 +1027,13 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase): @mock.patch.object(vmware_images, 'fetch_stream_optimized_image') @mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk') @mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume') + @mock.patch.object(VMDK_DRIVER, '_get_storage_profile_id') @mock.patch.object(VMDK_DRIVER, 'session') @mock.patch.object(VMDK_DRIVER, 'volumeops') - def test_copy_image_to_volume_stream_optimized(self, volumeops, + def test_copy_image_to_volume_stream_optimized(self, + volumeops, session, + get_profile_id, _select_ds_for_volume, _extend_virtual_disk, fetch_optimized_image): @@ -1040,12 +1043,14 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase): """ self._test_copy_image_to_volume_stream_optimized(volumeops, session, + get_profile_id, _select_ds_for_volume, _extend_virtual_disk, fetch_optimized_image) def _test_copy_image_to_volume_stream_optimized(self, volumeops, session, + get_profile_id, _select_ds_for_volume, _extend_virtual_disk, fetch_optimized_image): @@ -1055,9 +1060,10 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase): size = 5 * units.Gi size_gb = float(size) / units.Gi fake_volume_size = 1 + size_gb + adapter_type = 'ide' fake_image_meta = {'disk_format': 'vmdk', 'size': size, - 'properties': {'vmware_disktype': - 'streamOptimized'}} + 'properties': {'vmware_disktype': 'streamOptimized', + 'vmware_adaptertype': adapter_type}} image_service = mock.Mock(glance.GlanceImageService) fake_host = mock.sentinel.host fake_rp = mock.sentinel.rp @@ -1092,14 +1098,19 @@ class VMwareEsxVmdkDriverTestCase(test.TestCase): _select_ds_for_volume.side_effect = None _select_ds_for_volume.return_value = (fake_host, fake_rp, fake_folder, fake_summary) + profile_id = 'profile-1' + get_profile_id.return_value = profile_id self._driver.copy_image_to_volume(fake_context, fake_volume, image_service, fake_image_id) image_service.show.assert_called_with(fake_context, fake_image_id) _select_ds_for_volume.assert_called_with(fake_volume) + get_profile_id.assert_called_once_with(fake_volume) volumeops.get_create_spec.assert_called_with(fake_volume['name'], 0, fake_disk_type, - fake_summary.name) + fake_summary.name, + profile_id, + adapter_type) self.assertTrue(fetch_optimized_image.called) fetch_optimized_image.assert_called_with(fake_context, timeout, image_service, @@ -1882,10 +1893,12 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase): @mock.patch.object(vmware_images, 'fetch_stream_optimized_image') @mock.patch.object(VMDK_DRIVER, '_extend_vmdk_virtual_disk') @mock.patch.object(VMDK_DRIVER, '_select_ds_for_volume') + @mock.patch.object(VMDK_DRIVER, '_get_storage_profile_id') @mock.patch.object(VMDK_DRIVER, 'session') @mock.patch.object(VMDK_DRIVER, 'volumeops') def test_copy_image_to_volume_stream_optimized(self, volumeops, session, + get_profile_id, _select_ds_for_volume, _extend_virtual_disk, fetch_optimized_image): @@ -1895,6 +1908,7 @@ class VMwareVcVmdkDriverTestCase(VMwareEsxVmdkDriverTestCase): """ self._test_copy_image_to_volume_stream_optimized(volumeops, session, + get_profile_id, _select_ds_for_volume, _extend_virtual_disk, fetch_optimized_image) diff --git a/cinder/volume/drivers/vmware/vmdk.py b/cinder/volume/drivers/vmware/vmdk.py index a7d908603..4ced19cfc 100644 --- a/cinder/volume/drivers/vmware/vmdk.py +++ b/cinder/volume/drivers/vmware/vmdk.py @@ -429,6 +429,15 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): EAGER_ZEROED_THICK_VMDK_TYPE), THIN_VMDK_TYPE) + def _get_storage_profile_id(self, volume): + storage_profile = self._get_storage_profile(volume) + profile_id = None + if self._storage_policy_enabled and storage_profile: + profile = self.volumeops.retrieve_profile_id(storage_profile) + if profile: + profile_id = profile.uniqueId + return profile_id + def _create_backing(self, volume, host, create_params={}): """Create volume backing under the given host. @@ -446,12 +455,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): datastores) # check if a storage profile needs to be associated with the backing VM - storage_profile = self._get_storage_profile(volume) - profileId = None - if self._storage_policy_enabled and storage_profile: - profile = self.volumeops.retrieve_profile_id(storage_profile) - if profile: - profileId = profile.uniqueId + profile_id = self._get_storage_profile_id(volume) # default is a backing with single disk disk_less = create_params.get(CREATE_PARAM_DISK_LESS, False) @@ -463,7 +467,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): resource_pool, host, summary.name, - profileId) + profile_id) # create a backing with single disk disk_type = VMwareEsxVmdkDriver._get_disk_type(volume) @@ -477,7 +481,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): resource_pool, host, summary.name, - profileId, + profile_id, adapter_type) def _relocate_backing(self, volume, backing, host): @@ -882,7 +886,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): raise exception.VolumeBackendAPIException(data=err_msg) def _fetch_stream_optimized_image(self, context, volume, image_service, - image_id, image_size): + image_id, image_size, adapter_type): """Creates volume from image using HttpNfc VM import. Uses Nfc API to download the VMDK file from Glance. Nfc creates the @@ -903,6 +907,7 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): "%(size)s GB." % {'ds': summary.name, 'size': size_gb}) # prepare create spec for backing vm + profile_id = self._get_storage_profile_id(volume) disk_type = VMwareEsxVmdkDriver._get_disk_type(volume) # The size of stream optimized glance image is often suspect, @@ -911,7 +916,9 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): vm_create_spec = self.volumeops.get_create_spec(volume['name'], dummy_disk_size, disk_type, - summary.name) + summary.name, + profile_id, + adapter_type) # convert vm_create_spec to vm_import_spec cf = self.session.vim.client.factory vm_import_spec = cf.create('ns0:VirtualMachineImportSpec') @@ -1001,18 +1008,23 @@ class VMwareEsxVmdkDriver(driver.VolumeDriver): metadata = image_service.show(context, image_id) VMwareEsxVmdkDriver._validate_disk_format(metadata['disk_format']) - # Get disk_type for vmdk disk - disk_type = None + # Get the disk type, adapter type and size of vmdk image + disk_type = 'preallocated' + adapter_type = 'lsiLogic' image_size_in_bytes = metadata['size'] properties = metadata['properties'] - if properties and 'vmware_disktype' in properties: - disk_type = properties['vmware_disktype'] + if properties: + if 'vmware_disktype' in properties: + disk_type = properties['vmware_disktype'] + if 'vmware_adaptertype' in properties: + adapter_type = properties['vmware_adaptertype'] try: if disk_type == 'streamOptimized': self._fetch_stream_optimized_image(context, volume, image_service, image_id, - image_size_in_bytes) + image_size_in_bytes, + adapter_type) else: self._fetch_flat_image(context, volume, image_service, image_id, image_size_in_bytes) -- 2.45.2