From 01467f62413be38bfde7a7efed8b4d3fb01c7af8 Mon Sep 17 00:00:00 2001 From: peter_wang Date: Thu, 28 May 2015 20:38:56 -0400 Subject: [PATCH] Add 'source-id' and 'source-name' support in VNX driver Currently, VNX driver only supports 'id' as the id-type in manage/unmanage volume. With release of new version python-cinderclient, 'source-id' and 'source-name' are preferred id-type when using cinder manage. This fix is to add 'source-id' and 'source-name' support and obsolete the self-defined 'id' support. Change-Id: Ia0619123ff56e44da98c4f12c554474c8fe6093c closes-bug: 1450280 --- cinder/tests/unit/test_emc_vnxdirect.py | 27 +++++++- cinder/volume/drivers/emc/emc_cli_fc.py | 10 ++- cinder/volume/drivers/emc/emc_cli_iscsi.py | 10 ++- cinder/volume/drivers/emc/emc_vnx_cli.py | 78 +++++++++++----------- 4 files changed, 76 insertions(+), 49 deletions(-) diff --git a/cinder/tests/unit/test_emc_vnxdirect.py b/cinder/tests/unit/test_emc_vnxdirect.py index 0ef8a5383..2edfa4302 100644 --- a/cinder/tests/unit/test_emc_vnxdirect.py +++ b/cinder/tests/unit/test_emc_vnxdirect.py @@ -363,7 +363,8 @@ class EMCVNXCLIDriverTestData(object): } test_lun_id = 1 - test_existing_ref = {'id': test_lun_id} + test_existing_ref = {'source-id': test_lun_id} + test_existing_ref_source_name = {'source-name': 'vol1'} test_pool_name = 'unit_test_pool' device_map = { '1122334455667788': { @@ -2389,23 +2390,39 @@ Time Remaining: 0 second(s) commands = [lun_rename_cmd] results = [SUCCEED] + self.configuration.storage_vnx_pool_name = \ + self.testData.test_pool_name fake_cli = self.driverSetup(commands, results) - self.driver.cli._client.command_execute = fake_cli self.driver.manage_existing( self.testData.test_volume_with_type, self.testData.test_existing_ref) expected = [mock.call(*lun_rename_cmd, poll=False)] fake_cli.assert_has_calls(expected) + def test_manage_existing_source_name(self): + lun_rename_cmd = ('lun', '-modify', '-l', self.testData.test_lun_id, + '-newName', 'vol_with_type', '-o') + commands = [lun_rename_cmd] + + results = [SUCCEED] + fake_cli = self.driverSetup(commands, results) + self.driver.manage_existing( + self.testData.test_volume_with_type, + self.testData.test_existing_ref_source_name) + expected = [mock.call(*lun_rename_cmd, poll=False)] + fake_cli.assert_has_calls(expected) + def test_manage_existing_lun_in_another_pool(self): get_lun_cmd = ('lun', '-list', '-l', self.testData.test_lun_id, '-state', '-userCap', '-owner', '-attachedSnapshot', '-poolName') - commands = [get_lun_cmd] invalid_pool_name = "fake_pool" + commands = [get_lun_cmd] results = [self.testData.LUN_PROPERTY('lun_name', pool_name=invalid_pool_name)] + self.configuration.storage_vnx_pool_name = invalid_pool_name fake_cli = self.driverSetup(commands, results) + # mock the command executor ex = self.assertRaises( exception.ManageExistingInvalidReference, self.driver.manage_existing_get_size, @@ -2424,7 +2441,11 @@ Time Remaining: 0 second(s) test_size = 2 commands = [get_lun_cmd] results = [self.testData.LUN_PROPERTY('lun_name', size=test_size)] + + self.configuration.storage_vnx_pool_name = \ + self.testData.test_pool_name fake_cli = self.driverSetup(commands, results) + get_size = self.driver.manage_existing_get_size( self.testData.test_volume_with_type, self.testData.test_existing_ref) diff --git a/cinder/volume/drivers/emc/emc_cli_fc.py b/cinder/volume/drivers/emc/emc_cli_fc.py index 88ebda3e1..3a4e39752 100644 --- a/cinder/volume/drivers/emc/emc_cli_fc.py +++ b/cinder/volume/drivers/emc/emc_cli_fc.py @@ -57,6 +57,7 @@ class EMCCLIFCDriver(driver.FibreChannelDriver): 6.0.0 - Over subscription support Create consistency group from cgsnapshot support Multiple pools support enhancement + Manage/unmanage volume revise """ def __init__(self, *args, **kwargs): @@ -210,11 +211,14 @@ class EMCCLIFCDriver(driver.FibreChannelDriver): volume['name'] which is how drivers traditionally map between a cinder volume and the associated backend storage object. - existing_ref:{ - 'id':lun_id + manage_existing_ref:{ + 'source-id': + } + or + manage_existing_ref:{ + 'source-name': } """ - LOG.debug("Reference lun id %s.", existing_ref['id']) self.cli.manage_existing(volume, existing_ref) def manage_existing_get_size(self, volume, existing_ref): diff --git a/cinder/volume/drivers/emc/emc_cli_iscsi.py b/cinder/volume/drivers/emc/emc_cli_iscsi.py index 909d495b8..464c8db95 100644 --- a/cinder/volume/drivers/emc/emc_cli_iscsi.py +++ b/cinder/volume/drivers/emc/emc_cli_iscsi.py @@ -55,6 +55,7 @@ class EMCCLIISCSIDriver(driver.ISCSIDriver): 6.0.0 - Over subscription support Create consistency group from cgsnapshot support Multiple pools support enhancement + Manage/unmanage volume revise """ def __init__(self, *args, **kwargs): @@ -189,11 +190,14 @@ class EMCCLIISCSIDriver(driver.ISCSIDriver): volume['name'] which is how drivers traditionally map between a cinder volume and the associated backend storage object. - existing_ref:{ - 'id':lun_id + manage_existing_ref:{ + 'source-id': + } + or + manage_existing_ref:{ + 'source-name': } """ - LOG.debug("Reference lun id %s.", existing_ref['id']) self.cli.manage_existing(volume, existing_ref) def manage_existing_get_size(self, volume, existing_ref): diff --git a/cinder/volume/drivers/emc/emc_vnx_cli.py b/cinder/volume/drivers/emc/emc_vnx_cli.py index 2f98454e9..88dfa60e7 100644 --- a/cinder/volume/drivers/emc/emc_vnx_cli.py +++ b/cinder/volume/drivers/emc/emc_vnx_cli.py @@ -565,15 +565,11 @@ class CommandLineHelper(object): self._wait_for_a_condition(lun_is_extented) - def lun_rename(self, lun_id, new_name, poll=False): - """This function used to rename a lun to match - the expected name for the volume. - """ + def rename_lun(self, lun_id, new_name, poll=False): command_lun_rename = ('lun', '-modify', '-l', lun_id, '-newName', new_name, '-o') - out, rc = self.command_execute(*command_lun_rename, poll=poll) if rc != 0: @@ -2974,52 +2970,54 @@ class EMCVnxCliBase(object): return conn_info return do_terminate_connection() - def manage_existing_get_size(self, volume, ref): + def manage_existing_get_size(self, volume, existing_ref): """Returns size of volume to be managed by manage_existing.""" - - # Check that the reference is valid - if 'id' not in ref: - reason = _('Reference must contain lun_id element.') + if 'source-id' in existing_ref: + data = self._client.get_lun_by_id( + existing_ref['source-id'], + properties=self._client.LUN_WITH_POOL) + elif 'source-name' in existing_ref: + data = self._client.get_lun_by_name( + existing_ref['source-name'], + properties=self._client.LUN_WITH_POOL) + else: + reason = _('Reference must contain source-id or source-name key.') raise exception.ManageExistingInvalidReference( - existing_ref=ref, - reason=reason) - - # Check for existence of the lun - data = self._client.get_lun_by_id( - ref['id'], - properties=self._client.LUN_WITH_POOL) - if data is None: - reason = _('Find no lun with the specified id %s.') % ref['id'] - raise exception.ManageExistingInvalidReference(existing_ref=ref, - reason=reason) - - pool = self.get_target_storagepool(volume, None) - if pool and data['pool'] != pool: - reason = (_('The input lun %(lun_id)s is in pool %(poolname)s ' + existing_ref=existing_ref, reason=reason) + target_pool = self.get_target_storagepool(volume) + if target_pool and data['pool'] != target_pool: + reason = (_('The imported lun %(lun_id)s is in pool %(lun_pool)s ' 'which is not managed by the host %(host)s.') - % {'lun_id': ref['id'], - 'poolname': data['pool'], + % {'lun_id': data['lun_id'], + 'lun_pool': data['pool'], 'host': volume['host']}) - raise exception.ManageExistingInvalidReference(existing_ref=ref, - reason=reason) + raise exception.ManageExistingInvalidReference( + existing_ref=existing_ref, reason=reason) return data['total_capacity_gb'] - def manage_existing(self, volume, ref): + def manage_existing(self, volume, manage_existing_ref): """Imports the existing backend storage object as a volume. - Renames the backend storage object so that it matches the, - volume['name'] which is how drivers traditionally map between a - cinder volume and the associated backend storage object. - - existing_ref:{ - 'id':lun_id + manage_existing_ref:{ + 'source-id': + } + or + manage_existing_ref:{ + 'source-name': } """ - - self._client.lun_rename(ref['id'], volume['name']) + if 'source-id' in manage_existing_ref: + lun_id = manage_existing_ref['source-id'] + elif 'source-name' in manage_existing_ref: + lun_id = self._client.get_lun_by_name( + manage_existing_ref['source-name'], poll=False)['lun_id'] + else: + reason = _('Reference must contain source-id or source-name key.') + raise exception.ManageExistingInvalidReference( + existing_ref=manage_existing_ref, reason=reason) + self._client.rename_lun(lun_id, volume['name']) model_update = {'provider_location': - self._build_provider_location_for_lun(ref['id'])} - + self._build_provider_location_for_lun(lun_id)} return model_update def get_login_ports(self, connector): -- 2.45.2