diff --git a/cinder/tests/unit/volume/drivers/vmware/test_fcd.py b/cinder/tests/unit/volume/drivers/vmware/test_fcd.py index 818168eca21..412c123b92b 100644 --- a/cinder/tests/unit/volume/drivers/vmware/test_fcd.py +++ b/cinder/tests/unit/volume/drivers/vmware/test_fcd.py @@ -65,16 +65,19 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): self._driver = fcd.VMwareVStorageObjectDriver( configuration=self._config) self._driver._vc_version = self.VC_VERSION + self._driver._storage_policy_enabled = True self._context = context.get_admin_context() @mock.patch.object(VMDK_DRIVER, 'do_setup') @mock.patch.object(FCD_DRIVER, 'volumeops') def test_do_setup(self, vops, vmdk_do_setup): + self._driver._storage_policy_enabled = False self._driver.do_setup(self._context) + vmdk_do_setup.assert_called_once_with(self._context) - self.assertFalse(self._driver._storage_policy_enabled) vops.set_vmx_version.assert_called_once_with('vmx-13') self.assertTrue(self._driver._use_fcd_snapshot) + self.assertTrue(self._driver._storage_policy_enabled) def test_get_volume_stats(self): stats = self._driver.get_volume_stats() @@ -117,8 +120,12 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): project_id) return fake_volume.fake_volume_obj(self._context, **vol) + @mock.patch.object(FCD_DRIVER, '_get_storage_profile') @mock.patch.object(FCD_DRIVER, '_select_datastore') - def test_select_ds_fcd(self, select_datastore): + def test_select_ds_fcd(self, select_datastore, get_storage_profile): + profile = mock.sentinel.profile + get_storage_profile.return_value = profile + datastore = mock.sentinel.datastore summary = mock.Mock(datastore=datastore) select_datastore.return_value = (mock.ANY, mock.ANY, summary) @@ -126,7 +133,8 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): volume = self._create_volume_obj() ret = self._driver._select_ds_fcd(volume) self.assertEqual(datastore, ret) - exp_req = {hub.DatastoreSelector.SIZE_BYTES: volume.size * units.Gi} + exp_req = {hub.DatastoreSelector.SIZE_BYTES: volume.size * units.Gi, + hub.DatastoreSelector.PROFILE_NAME: profile} select_datastore.assert_called_once_with(exp_req) @mock.patch.object(FCD_DRIVER, '_select_datastore') @@ -177,14 +185,19 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): @mock.patch.object(FCD_DRIVER, '_select_ds_fcd') @mock.patch.object(FCD_DRIVER, '_get_disk_type') + @mock.patch.object(FCD_DRIVER, '_get_storage_profile_id') @mock.patch.object(FCD_DRIVER, 'volumeops') - def test_create_volume(self, vops, get_disk_type, select_ds_fcd): + def test_create_volume(self, vops, get_storage_profile_id, get_disk_type, + select_ds_fcd): ds_ref = mock.sentinel.ds_ref select_ds_fcd.return_value = ds_ref disk_type = mock.sentinel.disk_type get_disk_type.return_value = disk_type + profile_id = mock.sentinel.profile_id + get_storage_profile_id.return_value = profile_id + fcd_loc = mock.Mock() provider_loc = mock.sentinel.provider_loc fcd_loc.provider_location.return_value = provider_loc @@ -196,7 +209,8 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): select_ds_fcd.assert_called_once_with(volume) get_disk_type.assert_called_once_with(volume) vops.create_fcd.assert_called_once_with( - volume.name, volume.size * units.Ki, ds_ref, disk_type) + volume.name, volume.size * units.Ki, ds_ref, disk_type, + profile_id=profile_id) @mock.patch.object(volumeops.FcdLocation, 'from_provider_location') @mock.patch.object(FCD_DRIVER, 'volumeops') @@ -269,10 +283,12 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): '_create_virtual_disk_from_preallocated_image') @mock.patch.object(FCD_DRIVER, 'volumeops') @mock.patch.object(datastore, 'DatastoreURL') + @mock.patch.object(FCD_DRIVER, '_get_storage_profile_id') @ddt.data(vmdk.ImageDiskType.PREALLOCATED, vmdk.ImageDiskType.SPARSE, vmdk.ImageDiskType.STREAM_OPTIMIZED) def test_copy_image_to_volume(self, disk_type, + get_storage_profile_id, datastore_url_cls, vops, create_disk_from_preallocated_image, @@ -303,6 +319,9 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): ds_url = mock.sentinel.ds_url datastore_url_cls.return_value = ds_url + profile_id = mock.sentinel.profile_id + get_storage_profile_id.return_value = profile_id + fcd_loc = mock.Mock() provider_location = mock.sentinel.provider_location fcd_loc.provider_location.return_value = provider_location @@ -331,6 +350,7 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): str(ds_url), volume.name, summary.datastore) + vops.update_fcd_policy.assert_called_once_with(fcd_loc, profile_id) @mock.patch.object(volumeops.FcdLocation, 'from_provider_location') @mock.patch.object(FCD_DRIVER, 'volumeops') @@ -420,7 +440,7 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): self.assertEqual(dest_fcd_loc, ret) from_provider_loc.assert_called_once_with(provider_loc) vops.clone_fcd.assert_called_once_with( - name, fcd_loc, dest_ds_ref, disk_type) + name, fcd_loc, dest_ds_ref, disk_type, profile_id=None) @mock.patch.object(FCD_DRIVER, '_select_ds_fcd') @mock.patch.object(FCD_DRIVER, '_clone_fcd') @@ -519,16 +539,21 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): @mock.patch.object(FCD_DRIVER, '_select_ds_fcd') @mock.patch.object(FCD_DRIVER, '_get_disk_type') + @mock.patch.object(FCD_DRIVER, '_get_storage_profile_id') @mock.patch.object(FCD_DRIVER, '_clone_fcd') @mock.patch.object(FCD_DRIVER, '_extend_if_needed') def test_create_volume_from_fcd( - self, extend_if_needed, clone_fcd, get_disk_type, select_ds_fcd): + self, extend_if_needed, clone_fcd, get_storage_profile_id, + get_disk_type, select_ds_fcd): ds_ref = mock.sentinel.ds_ref select_ds_fcd.return_value = ds_ref disk_type = mock.sentinel.disk_type get_disk_type.return_value = disk_type + profile_id = mock.sentinel.profile_id + get_storage_profile_id.return_value = profile_id + cloned_fcd_loc = mock.Mock() dest_provider_loc = mock.sentinel.dest_provider_loc cloned_fcd_loc.provider_location.return_value = dest_provider_loc @@ -543,17 +568,19 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): select_ds_fcd.test_assert_called_once_with(volume) get_disk_type.test_assert_called_once_with(volume) clone_fcd.assert_called_once_with( - provider_loc, volume.name, ds_ref, disk_type=disk_type) + provider_loc, volume.name, ds_ref, disk_type=disk_type, + profile_id=profile_id) extend_if_needed.assert_called_once_with( cloned_fcd_loc, cur_size, volume.size) @mock.patch.object(FCD_DRIVER, '_create_volume_from_fcd') @mock.patch.object(volumeops.FcdSnapshotLocation, 'from_provider_location') + @mock.patch.object(FCD_DRIVER, '_get_storage_profile_id') @mock.patch.object(FCD_DRIVER, 'volumeops') @mock.patch.object(FCD_DRIVER, '_extend_if_needed') def _test_create_volume_from_snapshot( - self, extend_if_needed, vops, from_provider_loc, - create_volume_from_fcd, use_fcd_snapshot=False): + self, extend_if_needed, vops, get_storage_profile_id, + from_provider_loc, create_volume_from_fcd, use_fcd_snapshot=False): src_volume = self._create_volume_obj(vol_id=self.SRC_VOL_ID) snapshot = fake_snapshot.fake_snapshot_obj( self._context, volume=src_volume) @@ -563,6 +590,9 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): fcd_snap_loc = mock.sentinel.fcd_snap_loc from_provider_loc.return_value = fcd_snap_loc + profile_id = mock.sentinel.profile_id + get_storage_profile_id.return_value = profile_id + fcd_loc = mock.Mock() provider_loc = mock.sentinel.provider_loc fcd_loc.provider_location.return_value = provider_loc @@ -574,7 +604,7 @@ class VMwareVStorageObjectDriverTestCase(test.TestCase): if use_fcd_snapshot: self.assertEqual({'provider_location': provider_loc}, ret) vops.create_fcd_from_snapshot.assert_called_once_with( - fcd_snap_loc, volume.name) + fcd_snap_loc, volume.name, profile_id=profile_id) extend_if_needed.assert_called_once_with( fcd_loc, snapshot.volume_size, volume.size) else: diff --git a/cinder/tests/unit/volume/drivers/vmware/test_vmware_volumeops.py b/cinder/tests/unit/volume/drivers/vmware/test_vmware_volumeops.py index 6d9fa8108aa..260486de9bb 100644 --- a/cinder/tests/unit/volume/drivers/vmware/test_vmware_volumeops.py +++ b/cinder/tests/unit/volume/drivers/vmware/test_vmware_volumeops.py @@ -1925,13 +1925,18 @@ class VolumeOpsTestCase(test.TestCase): @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' '_create_fcd_backing_spec') - def test_create_fcd(self, create_fcd_backing_spec): + @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' + '_create_profile_spec') + def test_create_fcd(self, create_profile_spec, create_fcd_backing_spec): spec = mock.Mock() self.session.vim.client.factory.create.return_value = spec backing_spec = mock.sentinel.backing_spec create_fcd_backing_spec.return_value = backing_spec + profile_spec = mock.sentinel.profile_spec + create_profile_spec.return_value = profile_spec + task = mock.sentinel.task self.session.invoke_api.return_value = task @@ -1945,7 +1950,9 @@ class VolumeOpsTestCase(test.TestCase): ds_ref_val = mock.sentinel.ds_ref_val ds_ref = mock.Mock(value=ds_ref_val) disk_type = mock.sentinel.disk_type - ret = self.vops.create_fcd(name, size_mb, ds_ref, disk_type) + profile_id = mock.sentinel.profile_id + ret = self.vops.create_fcd( + name, size_mb, ds_ref, disk_type, profile_id=profile_id) self.assertEqual(fcd_id, ret.fcd_id) self.assertEqual(ds_ref_val, ret.ds_ref_val) @@ -1955,6 +1962,9 @@ class VolumeOpsTestCase(test.TestCase): self.assertEqual(1024, spec.capacityInMB) self.assertEqual(name, spec.name) self.assertEqual(backing_spec, spec.backingSpec) + self.assertEqual([profile_spec], spec.profile) + create_profile_spec.assert_called_once_with( + self.session.vim.client.factory, profile_id) self.session.invoke_api.assert_called_once_with( self.session.vim, 'CreateDisk_Task', @@ -1983,13 +1993,18 @@ class VolumeOpsTestCase(test.TestCase): @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' '_create_fcd_backing_spec') - def test_clone_fcd(self, create_fcd_backing_spec): + @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' + '_create_profile_spec') + def test_clone_fcd(self, create_profile_spec, create_fcd_backing_spec): spec = mock.Mock() self.session.vim.client.factory.create.return_value = spec backing_spec = mock.sentinel.backing_spec create_fcd_backing_spec.return_value = backing_spec + profile_spec = mock.sentinel.profile_spec + create_profile_spec.return_value = profile_spec + task = mock.sentinel.task self.session.invoke_api.return_value = task @@ -2008,7 +2023,9 @@ class VolumeOpsTestCase(test.TestCase): dest_ds_ref_val = mock.sentinel.dest_ds_ref_val dest_ds_ref = mock.Mock(value=dest_ds_ref_val) disk_type = mock.sentinel.disk_type - ret = self.vops.clone_fcd(name, fcd_location, dest_ds_ref, disk_type) + profile_id = mock.sentinel.profile_id + ret = self.vops.clone_fcd( + name, fcd_location, dest_ds_ref, disk_type, profile_id=profile_id) self.assertEqual(fcd_id, ret.fcd_id) self.assertEqual(dest_ds_ref_val, ret.ds_ref_val) @@ -2017,6 +2034,9 @@ class VolumeOpsTestCase(test.TestCase): create_fcd_backing_spec.assert_called_once_with(disk_type, dest_ds_ref) self.assertEqual(name, spec.name) self.assertEqual(backing_spec, spec.backingSpec) + self.assertEqual([profile_spec], spec.profile) + create_profile_spec.assert_called_once_with( + self.session.vim.client.factory, profile_id) self.session.invoke_api.assert_called_once_with( self.session.vim, 'CloneVStorageObject_Task', @@ -2172,10 +2192,15 @@ class VolumeOpsTestCase(test.TestCase): snapshotId=fcd_snap_id) self.session.wait_for_task(task) - def test_create_fcd_from_snapshot(self): + @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' + '_create_profile_spec') + def test_create_fcd_from_snapshot(self, create_profile_spec): task = mock.sentinel.task self.session.invoke_api.return_value = task + profile_spec = mock.sentinel.profile_spec + create_profile_spec.return_value = profile_spec + task_info = mock.Mock() fcd_id = mock.sentinel.fcd_id task_info.result.config.id.id = fcd_id @@ -2192,10 +2217,14 @@ class VolumeOpsTestCase(test.TestCase): fcd_snap_loc.id.return_value = fcd_snap_id name = mock.sentinel.name - ret = self.vops.create_fcd_from_snapshot(fcd_snap_loc, name) + profile_id = mock.sentinel.profile_id + ret = self.vops.create_fcd_from_snapshot( + fcd_snap_loc, name, profile_id=profile_id) self.assertEqual(fcd_id, ret.fcd_id) self.assertEqual(ds_ref_val, ret.ds_ref_val) + create_profile_spec.assert_called_once_with( + self.session.vim.client.factory, profile_id) self.session.invoke_api.assert_called_once_with( self.session.vim, 'CreateDiskFromSnapshot_Task', @@ -2203,9 +2232,48 @@ class VolumeOpsTestCase(test.TestCase): id=fcd_id, datastore=ds_ref, snapshotId=fcd_snap_id, - name=name) + name=name, + profile=[profile_spec]) self.session.wait_for_task.assert_called_once_with(task) + @mock.patch('cinder.volume.drivers.vmware.volumeops.VMwareVolumeOps.' + '_create_profile_spec') + @ddt.data(mock.sentinel.profile_id, None) + def test_update_fcd_policy(self, profile_id, create_profile_spec): + cf = self.session.vim.client.factory + if profile_id: + profile_spec = mock.sentinel.profile_spec + create_profile_spec.return_value = profile_spec + else: + empty_profile_spec = mock.sentinel.empty_profile_spec + cf.create.return_value = empty_profile_spec + + task = mock.sentinel.task + self.session.invoke_api.return_value = task + + fcd_location = mock.Mock() + fcd_id = mock.sentinel.fcd_id + fcd_location.id.return_value = fcd_id + ds_ref = mock.Mock() + fcd_location.ds_ref.return_value = ds_ref + + self.vops.update_fcd_policy(fcd_location, profile_id) + if profile_id: + create_profile_spec.assert_called_once_with(cf, profile_id) + exp_profile_spec = profile_spec + else: + cf.create.assert_called_once_with( + 'ns0:VirtualMachineEmptyProfileSpec') + exp_profile_spec = empty_profile_spec + self.session.invoke_api.assert_called_once_with( + self.session.vim, + 'UpdateVStorageObjectPolicy_Task', + self.session.vim.service_content.vStorageObjectManager, + id=fcd_id, + datastore=ds_ref, + profile=[exp_profile_spec]) + self.session.wait_for_task(task) + class VirtualDiskPathTest(test.TestCase): """Unit tests for VirtualDiskPath.""" diff --git a/cinder/volume/drivers/vmware/fcd.py b/cinder/volume/drivers/vmware/fcd.py index ef7d3ad9ada..8b5e94f46bd 100644 --- a/cinder/volume/drivers/vmware/fcd.py +++ b/cinder/volume/drivers/vmware/fcd.py @@ -44,7 +44,8 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): # 1.0 - initial version based on vSphere 6.5 vStorageObject APIs # 1.1 - support for vStorageObject snapshot APIs - VERSION = '1.1.0' + # 1.2 - support for SPBM storage policies + VERSION = '1.2.0' # ThirdPartySystems wiki page CI_WIKI_NAME = "VMware_CI" @@ -60,10 +61,11 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): :param context: The admin context. """ super(VMwareVStorageObjectDriver, self).do_setup(context) - self._storage_policy_enabled = False self.volumeops.set_vmx_version('vmx-13') - self._use_fcd_snapshot = versionutils.is_compatible( + vc_67_compatible = versionutils.is_compatible( '6.7.0', self._vc_version, same_major=False) + self._use_fcd_snapshot = vc_67_compatible + self._storage_policy_enabled = vc_67_compatible def get_volume_stats(self, refresh=False): """Collects volume backend stats. @@ -80,6 +82,10 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): def _select_ds_fcd(self, volume): req = {} req[hub.DatastoreSelector.SIZE_BYTES] = volume.size * units.Gi + + if self._storage_policy_enabled: + req[hub.DatastoreSelector.PROFILE_NAME] = ( + self._get_storage_profile(volume)) (_host_ref, _resource_pool, summary) = self._select_datastore(req) return summary.datastore @@ -106,6 +112,12 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): VMwareVStorageObjectDriver, self)._get_disk_type(volume) return vops.VirtualDiskType.get_virtual_disk_type(extra_spec_disk_type) + def _get_storage_profile_id(self, volume): + if self._storage_policy_enabled: + return super( + VMwareVStorageObjectDriver, self)._get_storage_profile_id( + volume) + def create_volume(self, volume): """Create a new volume on the backend. @@ -114,8 +126,10 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): """ disk_type = self._get_disk_type(volume) ds_ref = self._select_ds_fcd(volume) + profile_id = self._get_storage_profile_id(volume) fcd_loc = self.volumeops.create_fcd( - volume.name, volume.size * units.Ki, ds_ref, disk_type) + volume.name, volume.size * units.Ki, ds_ref, disk_type, + profile_id=profile_id) return {'provider_location': fcd_loc.provider_location()} def _delete_fcd(self, provider_loc): @@ -204,6 +218,11 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): fcd_loc = self.volumeops.register_disk( str(vmdk_url), volume.name, summary.datastore) + + profile_id = self._get_storage_profile_id(volume) + if profile_id: + self.volumeops.update_fcd_policy(fcd_loc, profile_id) + return {'provider_location': fcd_loc.provider_location()} def copy_volume_to_image(self, context, volume, image_service, image_meta): @@ -264,9 +283,11 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): self.volumeops.extend_fcd(fcd_loc, new_size * units.Ki) def _clone_fcd(self, provider_loc, name, dest_ds_ref, - disk_type=vops.VirtualDiskType.THIN): + disk_type=vops.VirtualDiskType.THIN, + profile_id=None): fcd_loc = vops.FcdLocation.from_provider_location(provider_loc) - return self.volumeops.clone_fcd(name, fcd_loc, dest_ds_ref, disk_type) + return self.volumeops.clone_fcd( + name, fcd_loc, dest_ds_ref, disk_type, profile_id=profile_id) def create_snapshot(self, snapshot): """Creates a snapshot. @@ -309,8 +330,10 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): def _create_volume_from_fcd(self, provider_loc, cur_size, volume): ds_ref = self._select_ds_fcd(volume) disk_type = self._get_disk_type(volume) + profile_id = self._get_storage_profile_id(volume) cloned_fcd_loc = self._clone_fcd( - provider_loc, volume.name, ds_ref, disk_type=disk_type) + provider_loc, volume.name, ds_ref, disk_type=disk_type, + profile_id=profile_id) self._extend_if_needed(cloned_fcd_loc, cur_size, volume.size) return {'provider_location': cloned_fcd_loc.provider_location()} @@ -324,8 +347,9 @@ class VMwareVStorageObjectDriver(vmdk.VMwareVcVmdkDriver): fcd_snap_loc = vops.FcdSnapshotLocation.from_provider_location( snapshot.provider_location) if fcd_snap_loc: + profile_id = self._get_storage_profile_id(volume) fcd_loc = self.volumeops.create_fcd_from_snapshot( - fcd_snap_loc, volume.name) + fcd_snap_loc, volume.name, profile_id=profile_id) self._extend_if_needed(fcd_loc, snapshot.volume_size, volume.size) return {'provider_location': fcd_loc.provider_location()} else: diff --git a/cinder/volume/drivers/vmware/volumeops.py b/cinder/volume/drivers/vmware/volumeops.py index bf1411f0b15..914cefdcf25 100644 --- a/cinder/volume/drivers/vmware/volumeops.py +++ b/cinder/volume/drivers/vmware/volumeops.py @@ -1783,12 +1783,22 @@ class VMwareVolumeOps(object): backing_spec.datastore = ds_ref return backing_spec - def create_fcd(self, name, size_mb, ds_ref, disk_type): - spec = self._session.vim.client.factory.create('ns0:VslmCreateSpec') + def _create_profile_spec(self, cf, profile_id): + profile_spec = cf.create('ns0:VirtualMachineDefinedProfileSpec') + profile_spec.profileId = profile_id + return profile_spec + + def create_fcd(self, name, size_mb, ds_ref, disk_type, profile_id=None): + cf = self._session.vim.client.factory + spec = cf.create('ns0:VslmCreateSpec') spec.capacityInMB = size_mb spec.name = name spec.backingSpec = self._create_fcd_backing_spec(disk_type, ds_ref) + if profile_id: + profile_spec = self._create_profile_spec(cf, profile_id) + spec.profile = [profile_spec] + LOG.debug("Creating fcd with spec: %(spec)s on datastore: %(ds_ref)s.", {'spec': spec, 'ds_ref': ds_ref}) vstorage_mgr = self._session.vim.service_content.vStorageObjectManager @@ -1812,13 +1822,18 @@ class VMwareVolumeOps(object): datastore=fcd_location.ds_ref()) self._session.wait_for_task(task) - def clone_fcd(self, name, fcd_location, dest_ds_ref, disk_type): + def clone_fcd( + self, name, fcd_location, dest_ds_ref, disk_type, profile_id=None): cf = self._session.vim.client.factory spec = cf.create('ns0:VslmCloneSpec') spec.name = name spec.backingSpec = self._create_fcd_backing_spec(disk_type, dest_ds_ref) + if profile_id: + profile_spec = self._create_profile_spec(cf, profile_id) + spec.profile = [profile_spec] + LOG.debug("Copying fcd: %(fcd_loc)s to datastore: %(ds_ref)s with " "spec: %(spec)s.", {'fcd_loc': fcd_location, @@ -1921,12 +1936,16 @@ class VMwareVolumeOps(object): snapshotId=fcd_snap_loc.id(cf)) self._session.wait_for_task(task) - def create_fcd_from_snapshot(self, fcd_snap_loc, name): + def create_fcd_from_snapshot(self, fcd_snap_loc, name, profile_id=None): LOG.debug("Creating fcd with name: %(name)s from fcd snapshot: " "%(snap)s.", {'name': name, 'snap': fcd_snap_loc}) vstorage_mgr = self._session.vim.service_content.vStorageObjectManager cf = self._session.vim.client.factory + if profile_id: + profile = [self._create_profile_spec(cf, profile_id)] + else: + profile = None task = self._session.invoke_api( self._session.vim, 'CreateDiskFromSnapshot_Task', @@ -1934,7 +1953,8 @@ class VMwareVolumeOps(object): id=fcd_snap_loc.fcd_loc.id(cf), datastore=fcd_snap_loc.fcd_loc.ds_ref(), snapshotId=fcd_snap_loc.id(cf), - name=name) + name=name, + profile=profile) task_info = self._session.wait_for_task(task) fcd_loc = FcdLocation.create(task_info.result.config.id, fcd_snap_loc.fcd_loc.ds_ref()) @@ -1942,6 +1962,27 @@ class VMwareVolumeOps(object): LOG.debug("Created fcd: %s.", fcd_loc) return fcd_loc + def update_fcd_policy(self, fcd_location, profile_id): + LOG.debug("Changing fcd: %(fcd_loc)s storage policy to %(policy)s.", + {'fcd_loc': fcd_location, 'policy': profile_id}) + + vstorage_mgr = self._session.vim.service_content.vStorageObjectManager + cf = self._session.vim.client.factory + if profile_id is None: + profile_spec = cf.create('ns0:VirtualMachineEmptyProfileSpec') + else: + profile_spec = self._create_profile_spec(cf, profile_id) + task = self._session.invoke_api( + self._session.vim, + 'UpdateVStorageObjectPolicy_Task', + vstorage_mgr, + id=fcd_location.id(cf), + datastore=fcd_location.ds_ref(), + profile=[profile_spec]) + self._session.wait_for_task(task) + + LOG.debug("Updated fcd storage policy to %s.", profile_id) + class FcdLocation(object): diff --git a/releasenotes/notes/vmware_fcd_storage_policy-636d6a95f1c44b6e.yaml b/releasenotes/notes/vmware_fcd_storage_policy-636d6a95f1c44b6e.yaml new file mode 100644 index 00000000000..2d8e7825021 --- /dev/null +++ b/releasenotes/notes/vmware_fcd_storage_policy-636d6a95f1c44b6e.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Added vSphere storage policy support in VMwareVStorageObjectDriver. + The storage policies that must be associated with the volumes can + be specified using volume type extra-spec key 'vmware:storage_profile' + similar to VMware VMDK driver. The vSphere version must be 6.7 or + above to use this feature.