diff --git a/cinder/tests/unit/volume/drivers/nec/test_volume.py b/cinder/tests/unit/volume/drivers/nec/test_volume.py index edcfdcb9706..c75732489e4 100644 --- a/cinder/tests/unit/volume/drivers/nec/test_volume.py +++ b/cinder/tests/unit/volume/drivers/nec/test_volume.py @@ -877,6 +877,33 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase): self.assertEqual('127.0.0.1:3260', info['data']['target_portals'][0]) self.assertEqual(88, info['data']['target_luns'][0]) + @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI._execute', + patch_execute) + @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI.view_all', + patch_view_all) + def test_iscsi_terminate_connection(self): + self.vol.id = "46045673-41e7-44a7-9333-02f07feab04b" + connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255", + 'multipath': True} + ret = self._iscsi_terminate_connection(self.vol, connector) + self.assertIsNone(ret) + + @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI._execute', + patch_execute) + @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI.view_all', + patch_view_all) + def test_iscsi_terminate_connection_negative(self): + self.vol.id = "46045673-41e7-44a7-9333-02f07feab04b" + connector = {'initiator': "iqn.1994-05.com.redhat:d1d8e8f23255", + 'multipath': True} + with self.assertRaisesRegexp(exception.VolumeBackendAPIException, + r'Failed to unregister Logical Disk from' + r' Logical Disk Set \(iSM31064\)'): + mock_del = mock.Mock() + self._cli.delldsetld = mock_del + self._cli.delldsetld.return_value = False, 'iSM31064' + self._iscsi_terminate_connection(self.vol, connector) + @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI._execute', patch_execute) @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI.view_all', @@ -915,6 +942,13 @@ class ExportTest(volume_helper.MStorageDSVDriver, test.TestCase): self.assertEqual( '2A00000991020012', info['data']['initiator_target_map']['10000090FAA0786B'][3]) + with self.assertRaisesRegexp(exception.VolumeBackendAPIException, + r'Failed to unregister Logical Disk from' + r' Logical Disk Set \(iSM31064\)'): + mock_del = mock.Mock() + self._cli.delldsetld = mock_del + self._cli.delldsetld.return_value = False, 'iSM31064' + self._fc_terminate_connection(self.vol, connector) @mock.patch('cinder.volume.drivers.nec.cli.MStorageISMCLI._execute', patch_execute) diff --git a/cinder/volume/drivers/nec/volume_common.py b/cinder/volume/drivers/nec/volume_common.py index 73bccc98228..aa4bda67191 100644 --- a/cinder/volume/drivers/nec/volume_common.py +++ b/cinder/volume/drivers/nec/volume_common.py @@ -153,7 +153,7 @@ def convert_to_id(value62): class MStorageVolumeCommon(object): """M-Series Storage volume common class.""" - VERSION = '1.10.1' + VERSION = '1.10.2' WIKI_NAME = 'NEC_Cinder_CI' def do_setup(self, context): diff --git a/cinder/volume/drivers/nec/volume_helper.py b/cinder/volume/drivers/nec/volume_helper.py index 0d9a568d526..df3b32c7df0 100644 --- a/cinder/volume/drivers/nec/volume_helper.py +++ b/cinder/volume/drivers/nec/volume_helper.py @@ -1180,7 +1180,50 @@ class MStorageDriver(volume_common.MStorageVolumeCommon): def iscsi_terminate_connection(self, volume, connector): msgparm = ('Volume ID = %(id)s, Connector = %(connector)s' % {'id': volume.id, 'connector': connector}) - LOG.info('Terminated iSCSI Connection (%s)', msgparm) + + try: + self._iscsi_terminate_connection(volume, connector) + LOG.info('Terminated iSCSI Connection (%s)', msgparm) + except exception.CinderException as e: + with excutils.save_and_reraise_exception(): + LOG.warning('Failed to Terminate iSCSI Connection ' + '(%(msgparm)s) (%(exception)s)', + {'msgparm': msgparm, 'exception': e}) + + def _iscsi_terminate_connection(self, volume, connector): + if self._properties['ldset_name'] != '': + LOG.debug('Ldset is specified. Access control setting ' + 'is not deleted automatically.') + return + + if connector is None: + LOG.debug('Connector is not specified. Nothing to do.') + return + + # delete unused access control setting. + xml = self._cli.view_all(self._properties['ismview_path']) + pools, lds, ldsets, used_ldns, hostports, max_ld_count = ( + self.configs(xml)) + + ldname = self.get_ldname( + volume.id, self._properties['ld_name_format']) + if ldname not in lds: + LOG.debug('Logical Disk `%s` has unbound already.', ldname) + return + + ldset = self._validate_iscsildset_exist(ldsets, connector) + retnum, errnum = self._cli.delldsetld(ldset['ldsetname'], ldname) + if retnum is not True: + if 'iSM31065' in errnum: + LOG.debug('LD `%(ld)s` already deleted ' + 'from LD Set `%(ldset)s`?', + {'ld': ldname, 'ldset': ldset['ldsetname']}) + else: + msg = (_('Failed to unregister Logical Disk from ' + 'Logical Disk Set (%s)') % errnum) + raise exception.VolumeBackendAPIException(data=msg) + LOG.debug('LD `%(ld)s` deleted from LD Set `%(ldset)s`.', + {'ld': ldname, 'ldset': ldset['ldsetname']}) def iscsi_terminate_connection_snapshot(self, snapshot, connector, **kwargs): @@ -1342,6 +1385,26 @@ class MStorageDriver(volume_common.MStorageVolumeCommon): info['data'] = {'target_wwn': target_wwns, 'initiator_target_map': init_targ_map} + if connector is not None and self._properties['ldset_name'] == '': + # delete LD from LD set. + ldname = self.get_ldname( + volume.id, self._properties['ld_name_format']) + if ldname not in lds: + LOG.debug('Logical Disk `%s` has unbound already.', ldname) + return info + + ldset = self._validate_fcldset_exist(ldsets, connector) + retnum, errnum = self._cli.delldsetld(ldset['ldsetname'], ldname) + if retnum is not True: + if 'iSM31065' in errnum: + LOG.debug('LD `%(ld)s` already deleted ' + 'from LD Set `%(ldset)s`?', + {'ld': ldname, 'ldset': ldset['ldsetname']}) + else: + msg = (_('Failed to unregister Logical Disk from ' + 'Logical Disk Set (%s)') % errnum) + raise exception.VolumeBackendAPIException(data=msg) + LOG.debug('_fc_terminate_connection' '(Volume ID = %(id)s, connector = %(connector)s, ' 'info = %(info)s) End.',