Merge "Fujitsu driver: Improve volume deletion"
This commit is contained in:
commit
e28867ba8d
@ -175,7 +175,7 @@ FAKE_POOLS = [{
|
||||
}]
|
||||
|
||||
FAKE_STATS = {
|
||||
'driver_version': '1.4.1',
|
||||
'driver_version': '1.4.2',
|
||||
'storage_protocol': 'iSCSI',
|
||||
'vendor_name': 'FUJITSU',
|
||||
'QoS_support': True,
|
||||
@ -185,7 +185,7 @@ FAKE_STATS = {
|
||||
'pools': FAKE_POOLS,
|
||||
}
|
||||
FAKE_STATS2 = {
|
||||
'driver_version': '1.4.1',
|
||||
'driver_version': '1.4.2',
|
||||
'storage_protocol': 'FC',
|
||||
'vendor_name': 'FUJITSU',
|
||||
'QoS_support': True,
|
||||
@ -375,8 +375,11 @@ class FakeCIMInstanceName(dict):
|
||||
snaps = FakeCIMInstanceName()
|
||||
snaps['ElementName'] = 'FJosv_OgEZj1mSvKRvIKOExKktlg=='
|
||||
snaps['Name'] = None
|
||||
snaps['DeviceID'] = FAKE_LUN_ID2
|
||||
snaps['SystemName'] = STORAGE_SYSTEM
|
||||
ret.append(snaps)
|
||||
snaps.path = ''
|
||||
snaps.classname = 'FUJITSU_StorageVolume'
|
||||
|
||||
map = FakeCIMInstanceName()
|
||||
map['ElementName'] = 'FJosv_hhJsV9lcMBvAPADrGqucwg=='
|
||||
@ -1037,6 +1040,16 @@ class FJFCDriverTestCase(test.TestCase):
|
||||
'0002\t\r\n0000\tFJosv_0qJ4rpOHgFE8ipcJOMfBmg==\t0F'
|
||||
'\t\r\n0001\tFJosv_OgEZj1mSvKRvIKOExKktlg==\t0D'
|
||||
'\t\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show copy-sessions'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n'
|
||||
'0001\tFFFF\t01\t08\tFF\tFF\t03\t02\tFF\tFF\t05ABD7D2\t'
|
||||
'########################################\t'
|
||||
'########################################\t'
|
||||
'00000281\t00000286\t0001\t00\tFF\t0000000000000800\t'
|
||||
'0000000000000000\t0000000000000100\t0000000000000800\t'
|
||||
'04\t00\t00000000\t2020101009341400\t01\t10\tFFFF\tFFFF\t'
|
||||
'0000000000000000\tFFFFFFFFFFFFFFFF\tFFFFFFFFFFFFFFFF\tFF\t'
|
||||
'FF\t64\t00\t07\t00\t00\t00\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show qos-bandwidth-limit'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0010\t\r\n00\t0000ffff\t0000ffff'
|
||||
'\t0000ffff\t0000ffff\t0000ffff\t0000ffff\t0000ffff'
|
||||
@ -1080,6 +1093,8 @@ class FJFCDriverTestCase(test.TestCase):
|
||||
'\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('set qos-bandwidth-limit'):
|
||||
ret = '%s\r\n00\r\n0001\r\nCLI> ' % exec_cmdline
|
||||
elif exec_cmdline.startswith('stop copy-session'):
|
||||
ret = '%s\r\n00\r\nCLI> ' % exec_cmdline
|
||||
else:
|
||||
ret = None
|
||||
return ret
|
||||
@ -1284,6 +1299,16 @@ class FJISCSIDriverTestCase(test.TestCase):
|
||||
'0002\t\r\n0000\tFJosv_0qJ4rpOHgFE8ipcJOMfBmg==\t0F'
|
||||
'\t\r\n0001\tFJosv_OgEZj1mSvKRvIKOExKktlg==\t0D'
|
||||
'\t\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show copy-sessions'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n'
|
||||
'0001\tFFFF\t01\t08\tFF\tFF\t03\t02\tFF\tFF\t05ABD7D2\t'
|
||||
'########################################\t'
|
||||
'########################################\t'
|
||||
'00000281\t00000286\t0001\t00\tFF\t0000000000000800\t'
|
||||
'0000000000000000\t0000000000000100\t0000000000000800\t'
|
||||
'04\t00\t00000000\t2020101009341400\t01\t10\tFFFF\tFFFF\t'
|
||||
'0000000000000000\tFFFFFFFFFFFFFFFF\tFFFFFFFFFFFFFFFF\tFF\t'
|
||||
'FF\t64\t00\t07\t00\t00\t00\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show qos-bandwidth-limit'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0010\t\r\n00\t0000ffff\t0000ffff'
|
||||
'\t0000ffff\t0000ffff\t0000ffff\t0000ffff\t0000ffff'
|
||||
@ -1515,6 +1540,16 @@ class FJCLITestCase(test.TestCase):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n'
|
||||
'0001\r\n0000\tFJosv_0qJ4rpOHgFE8ipcJOMfBmg==\t01\t00\t00'
|
||||
'\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show copy-sessions'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n'
|
||||
'0001\tFFFF\t01\t08\tFF\tFF\t03\t02\tFF\tFF\t05ABD7D2\t'
|
||||
'########################################\t'
|
||||
'########################################\t'
|
||||
'00000281\t00000286\t0001\t00\tFF\t0000000000000800\t'
|
||||
'0000000000000000\t0000000000000100\t0000000000000800\t'
|
||||
'04\t00\t00000000\t2020101009341400\t01\t10\tFFFF\tFFFF\t'
|
||||
'0000000000000000\tFFFFFFFFFFFFFFFF\tFFFFFFFFFFFFFFFF\tFF\t'
|
||||
'FF\t64\t00\t07\t00\t00\t00\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show qos-bandwidth-limit'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n00\t0000ffff\t0000ffff'
|
||||
'\t0000ffff\t0000ffff\t0000ffff\t0000ffff\t0000ffff'
|
||||
@ -1522,6 +1557,8 @@ class FJCLITestCase(test.TestCase):
|
||||
'CLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('set qos-bandwidth-limit'):
|
||||
ret = '%s\r\n00\r\n0001\r\nCLI> ' % exec_cmdline
|
||||
elif exec_cmdline.startswith('stop copy-session'):
|
||||
ret = '%s\r\n00\r\nCLI> ' % exec_cmdline
|
||||
elif exec_cmdline.startswith('delete volume'):
|
||||
ret = '%s\r\n00\r\nCLI> ' % exec_cmdline
|
||||
else:
|
||||
@ -1608,6 +1645,21 @@ class FJCLITestCase(test.TestCase):
|
||||
volume_number = self.cli._set_volume_qos(**FAKE_QOS_OPTION)
|
||||
self.assertEqual(FAKE_QOS_OUTPUT, volume_number)
|
||||
|
||||
def test_show_copy_sessions(self):
|
||||
FAKE_COPY_SESSION = [{
|
||||
'Source Num': 641,
|
||||
'Dest Num': 646,
|
||||
'Type': 'Snap',
|
||||
'Status': 'Active',
|
||||
'Phase': 'Tracking',
|
||||
'Session ID': 1,
|
||||
}]
|
||||
FAKE_COPY_SESSION_OUTPUT = {**FAKE_CLI_OUTPUT,
|
||||
'message': FAKE_COPY_SESSION}
|
||||
|
||||
cpdatalist = self.cli._show_copy_sessions()
|
||||
self.assertEqual(FAKE_COPY_SESSION_OUTPUT, cpdatalist)
|
||||
|
||||
def test_show_pool_provision(self):
|
||||
FAKE_POOL_PROVIOSN_OPTION = self.create_fake_options(
|
||||
pool_name='abcd1234_TPP')
|
||||
@ -1666,6 +1718,15 @@ class FJCLITestCase(test.TestCase):
|
||||
versioninfo = self.cli._show_enclosure_status()
|
||||
self.assertEqual(FAKE_VERSION_INFO, versioninfo)
|
||||
|
||||
def test_stop_copy_session(self):
|
||||
FAKE_SESSION_ID = '0001'
|
||||
FAKE_STOP_OUTPUT = {**FAKE_CLI_OUTPUT, 'message': []}
|
||||
FAKE_STOP_COPY_SESSION_OPTION = self.create_fake_options(
|
||||
session_id=FAKE_SESSION_ID)
|
||||
stop_output = self.cli._stop_copy_session(
|
||||
**FAKE_STOP_COPY_SESSION_OPTION)
|
||||
self.assertEqual(FAKE_STOP_OUTPUT, stop_output)
|
||||
|
||||
def test_delete_volume(self):
|
||||
FAKE_VOLUME_NAME = 'FJosv_0qJ4rpOHgFE8ipcJOMfBmg=='
|
||||
FAKE_DELETE_OUTPUT = {**FAKE_CLI_OUTPUT, 'message': []}
|
||||
@ -1746,13 +1807,25 @@ class FJCommonTestCase(test.TestCase):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n'
|
||||
'0001\r\n0000\tFJosv_0qJ4rpOHgFE8ipcJOMfBmg==\t01\t00\t00'
|
||||
'\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show copy-sessions'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n'
|
||||
'0001\tFFFF\t01\t08\tFF\tFF\t03\t02\tFF\tFF\t05ABD7D2\t'
|
||||
'########################################\t'
|
||||
'########################################\t'
|
||||
'00000281\t00000286\t0001\t00\tFF\t0000000000000800\t'
|
||||
'0000000000000000\t0000000000000100\t0000000000000800\t'
|
||||
'04\t00\t00000000\t2020101009341400\t01\t10\tFFFF\tFFFF\t'
|
||||
'0000000000000000\tFFFFFFFFFFFFFFFF\tFFFFFFFFFFFFFFFF\tFF\t'
|
||||
'FF\t64\t00\t07\t00\t00\t00\r\nCLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('show qos-bandwidth-limit'):
|
||||
ret = ('\r\nCLI> %s\r\n00\r\n0001\t\r\n00\t0000ffff\t0000ffff'
|
||||
'\t0000ffff\t0000ffff\t0000ffff\t0000ffff\t0000ffff'
|
||||
'\t0000ffff\t0000ffff\t0000ffff\t0000ffff\t0000ffff\r\n'
|
||||
'CLI> ' % exec_cmdline)
|
||||
elif exec_cmdline.startswith('set qos-bandwidth-limit'):
|
||||
ret = '\r\nCLI> %s\r\n00\r\n0001\r\nCLI> ' % exec_cmdline
|
||||
ret = '%s\r\n00\r\n0001\r\nCLI> ' % exec_cmdline
|
||||
elif exec_cmdline.startswith('stop copy-session'):
|
||||
ret = '%s\r\n00\r\nCLI> ' % exec_cmdline
|
||||
else:
|
||||
ret = None
|
||||
return ret
|
||||
@ -1764,6 +1837,19 @@ class FJCommonTestCase(test.TestCase):
|
||||
conn = FakeEternusConnection()
|
||||
return conn
|
||||
|
||||
def test_get_volume_number(self):
|
||||
vol_instance = FakeCIMInstanceName()
|
||||
vol_instance['ElementName'] = 'FJosv_0qJ4rpOHgFE8ipcJOMfBmg=='
|
||||
vol_instance['Purpose'] = '00228+0x06'
|
||||
vol_instance['Name'] = None
|
||||
vol_instance['DeviceID'] = FAKE_LUN_ID1
|
||||
vol_instance['SystemName'] = STORAGE_SYSTEM
|
||||
vol_instance.path = ''
|
||||
vol_instance.classname = 'FUJITSU_StorageVolume'
|
||||
|
||||
volume_no = self.driver.common._get_volume_number(vol_instance)
|
||||
self.assertEqual(FAKE_LUN_NO1, volume_no)
|
||||
|
||||
def test_get_eternus_model(self):
|
||||
ETERNUS_MODEL = self.driver.common._get_eternus_model()
|
||||
self.assertEqual(3, ETERNUS_MODEL)
|
||||
@ -1846,3 +1932,15 @@ class FJCommonTestCase(test.TestCase):
|
||||
self.driver.common._set_limit(FAKE_MODE, FAKE_LIMIT,
|
||||
FAKE_IOPS, FAKE_THROUGHOUTPUT)
|
||||
mock_exec_cli_with_eternus.assert_called_with(exec_cmdline)
|
||||
|
||||
def test_get_copy_sessions_list(self):
|
||||
FAKE_COPY_SESSION = [{
|
||||
'Source Num': 641,
|
||||
'Dest Num': 646,
|
||||
'Type': 'Snap',
|
||||
'Status': 'Active',
|
||||
'Phase': 'Tracking',
|
||||
'Session ID': 1,
|
||||
}]
|
||||
copy_session_list = self.driver.common._get_copy_sessions_list()
|
||||
self.assertEqual(FAKE_COPY_SESSION, copy_session_list)
|
||||
|
@ -50,8 +50,10 @@ class FJDXCLI(object):
|
||||
'show_qos_bandwidth_limit': self._show_qos_bandwidth_limit,
|
||||
'set_qos_bandwidth_limit': self._set_qos_bandwidth_limit,
|
||||
'set_volume_qos': self._set_volume_qos,
|
||||
'show_copy_sessions': self._show_copy_sessions,
|
||||
'show_volume_qos': self._show_volume_qos,
|
||||
'show_enclosure_status': self._show_enclosure_status,
|
||||
'stop_copy_session': self._stop_copy_session,
|
||||
'delete_volume': self._delete_volume
|
||||
}
|
||||
|
||||
@ -276,6 +278,92 @@ class FJDXCLI(object):
|
||||
|
||||
return output
|
||||
|
||||
def _show_copy_sessions(self, **option):
|
||||
"""Get copy sessions."""
|
||||
try:
|
||||
output = self._exec_cli("show copy-sessions", **option)
|
||||
|
||||
# return error
|
||||
rc = output['rc']
|
||||
|
||||
if rc != "0":
|
||||
return output
|
||||
|
||||
cpsdatalist = []
|
||||
clidatalist = output.get('message')
|
||||
|
||||
for clidataline in clidatalist[1:]:
|
||||
clidata = clidataline.split('\t')
|
||||
# Get CopyType
|
||||
if clidata[2] == '01':
|
||||
# CopyKind: OPC
|
||||
if bin(int(clidata[3], 16) & 16) != 0:
|
||||
# eg. 0b10010000
|
||||
temp_type = 'Snap'
|
||||
elif bin(int(clidata[3], 16) & 64) != 0:
|
||||
# eg. 0b11000000
|
||||
temp_type = 'Snap+'
|
||||
else:
|
||||
temp_type = 'Other'
|
||||
elif clidata[2] == '02':
|
||||
# CopyKind: EC
|
||||
if clidata[5] == 'FF':
|
||||
temp_type = 'EC'
|
||||
elif clidata[5] == '10':
|
||||
temp_type = 'Sync_REC'
|
||||
else:
|
||||
temp_type = 'Other'
|
||||
else:
|
||||
temp_type = 'Other'
|
||||
|
||||
# Get Phases
|
||||
if clidata[6] == '00':
|
||||
temp_phase = 'No_Pair'
|
||||
elif clidata[6] == '01':
|
||||
temp_phase = 'Copying'
|
||||
elif clidata[6] == '02':
|
||||
temp_phase = 'Equivalent'
|
||||
elif clidata[6] == '03':
|
||||
temp_phase = 'Tracking'
|
||||
elif clidata[6] == '04':
|
||||
temp_phase = 'Tracking_Copying'
|
||||
elif clidata[6] == '06':
|
||||
temp_phase = 'Readying'
|
||||
else:
|
||||
temp_phase = 'Other'
|
||||
|
||||
# Get CopyStatus
|
||||
if clidata[7] == '00':
|
||||
temp_status = 'Idle'
|
||||
elif clidata[7] == '01':
|
||||
temp_status = 'Reserve'
|
||||
elif clidata[7] == '02':
|
||||
temp_status = 'Active'
|
||||
elif clidata[7] == '03':
|
||||
temp_status = 'Error_Suspend'
|
||||
elif clidata[7] == '04':
|
||||
temp_status = 'Suspend'
|
||||
elif clidata[7] == '05':
|
||||
temp_status = 'Halt'
|
||||
else:
|
||||
temp_status = 'Other'
|
||||
|
||||
cpsdatalist.append({'Source Num': int(clidata[13], 16),
|
||||
'Dest Num': int(clidata[14], 16),
|
||||
'Type': temp_type,
|
||||
'Status': temp_status,
|
||||
'Phase': temp_phase,
|
||||
'Session ID': int(clidata[0], 16)})
|
||||
|
||||
output['message'] = cpsdatalist
|
||||
except Exception as ex:
|
||||
output = {'result': 0,
|
||||
'rc': '4',
|
||||
'message': "Show copy sessions error: %s"
|
||||
% str(ex)}
|
||||
|
||||
return output
|
||||
|
||||
def _show_qos_bandwidth_limit(self, **option):
|
||||
"""Get qos bandwidth limit."""
|
||||
clidata = None
|
||||
@ -394,6 +482,10 @@ class FJDXCLI(object):
|
||||
|
||||
return output
|
||||
|
||||
def _stop_copy_session(self, **option):
|
||||
"""Exec stop copy-session."""
|
||||
return self._exec_cli("stop copy-session", **option)
|
||||
|
||||
def _delete_volume(self, **option):
|
||||
"""Exec delete volume."""
|
||||
return self._exec_cli('delete volume', **option)
|
||||
|
@ -67,10 +67,11 @@ class FJDXCommon(object):
|
||||
1.3.0 - Community base version
|
||||
1.4.0 - Add support for QoS.
|
||||
1.4.1 - Add the method for expanding RAID volumes by CLI.
|
||||
1.4.2 - Add the secondary check for copy-sessions when deleting volumes.
|
||||
|
||||
"""
|
||||
|
||||
VERSION = "1.4.1"
|
||||
VERSION = "1.4.2"
|
||||
stats = {
|
||||
'driver_version': VERSION,
|
||||
'storage_protocol': None,
|
||||
@ -261,7 +262,7 @@ class FJDXCommon(object):
|
||||
'vol_name': volumename,
|
||||
}
|
||||
|
||||
volume_no = "0x" + element['DeviceID'][24:28]
|
||||
volume_no = self._get_volume_number(element)
|
||||
metadata = {
|
||||
'FJ_Backend': systemnamelist[0]['IdentifyingNumber'],
|
||||
'FJ_Volume_Name': volumename,
|
||||
@ -445,36 +446,37 @@ class FJDXCommon(object):
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""Delete volume on ETERNUS."""
|
||||
LOG.debug('delete_volume, volume id: %s.', volume['id'])
|
||||
LOG.debug('delete_volume, volume id: %(vid)s.',
|
||||
{'vid': volume['id']})
|
||||
|
||||
self.conn = self._get_eternus_connection()
|
||||
vol_exist = self._delete_volume_setting(volume)
|
||||
|
||||
if not vol_exist:
|
||||
LOG.debug('delete_volume, volume not found in 1st check.')
|
||||
return False
|
||||
return
|
||||
|
||||
# Check volume existence on ETERNUS again
|
||||
# because volume is deleted when SnapOPC copysession is deleted.
|
||||
vol_instance = self._find_lun(volume)
|
||||
if vol_instance is None:
|
||||
LOG.debug('delete_volume, volume not found in 2nd check, '
|
||||
'but no problem.')
|
||||
return True
|
||||
|
||||
self._delete_volume(vol_instance)
|
||||
return True
|
||||
try:
|
||||
self._delete_volume(volume)
|
||||
except Exception as ex:
|
||||
msg = (_('delete_volume, '
|
||||
'delete volume failed, '
|
||||
'Error information: %s.')
|
||||
% ex)
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
@lockutils.synchronized('ETERNUS-vol', 'cinder-', True)
|
||||
def _delete_volume_setting(self, volume):
|
||||
"""Delete volume setting (HostAffinity, CopySession) on ETERNUS."""
|
||||
LOG.debug('_delete_volume_setting, volume id: %s.', volume['id'])
|
||||
LOG.debug('_delete_volume_setting, '
|
||||
'volume id: %(vid)s.',
|
||||
{'vid': volume['id']})
|
||||
|
||||
# Check the existence of volume.
|
||||
volumename = self._get_volume_name(volume)
|
||||
vol_instance = self._find_lun(volume)
|
||||
|
||||
if vol_instance is None:
|
||||
if not vol_instance:
|
||||
LOG.info('_delete_volume_setting, volumename:%(volumename)s, '
|
||||
'volume not found on ETERNUS.',
|
||||
{'volumename': volumename})
|
||||
@ -514,6 +516,33 @@ class FJDXCommon(object):
|
||||
for cpsession in delete_copysession_list:
|
||||
self._delete_copysession(cpsession)
|
||||
|
||||
volume_no = self._get_volume_number(vol_instance)
|
||||
|
||||
cp_session_list = self._get_copy_sessions_list()
|
||||
for cp in cp_session_list:
|
||||
if cp['Dest Num'] != int(volume_no, 16):
|
||||
continue
|
||||
if cp['Type'] == 'Snap':
|
||||
session_id = cp['Session ID']
|
||||
|
||||
param_dict = ({'session-id': session_id})
|
||||
rc, emsg, clidata = self._exec_eternus_cli(
|
||||
'stop_copy_session',
|
||||
**param_dict)
|
||||
|
||||
if rc != 0:
|
||||
msg = (_('_delete_volume_setting, '
|
||||
'stop_copy_session failed. '
|
||||
'Return code: %(rc)lu, '
|
||||
'Error: %(errormsg)s, '
|
||||
'Message: %(clidata)s.')
|
||||
% {'rc': rc,
|
||||
'errormsg': emsg,
|
||||
'clidata': clidata})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
break
|
||||
|
||||
LOG.debug('_delete_volume_setting, '
|
||||
'wait_cpsession: %(wait_cpsession)s, '
|
||||
'delete_cpsession: %(delete_cpsession)s, complete.',
|
||||
@ -522,15 +551,22 @@ class FJDXCommon(object):
|
||||
return True
|
||||
|
||||
@lockutils.synchronized('ETERNUS-vol', 'cinder-', True)
|
||||
def _delete_volume(self, vol_instance):
|
||||
def _delete_volume(self, volume):
|
||||
"""Delete volume on ETERNUS."""
|
||||
LOG.debug('_delete_volume, volume name: %s.',
|
||||
vol_instance['ElementName'])
|
||||
LOG.debug('_delete_volume, volume id: %(vid)s.',
|
||||
{'vid': volume['id']})
|
||||
|
||||
vol_instance = self._find_lun(volume)
|
||||
|
||||
if not vol_instance:
|
||||
LOG.debug('_delete_volume, volume not found in 2nd check, '
|
||||
'but no problem.')
|
||||
return
|
||||
|
||||
volumename = vol_instance['ElementName']
|
||||
|
||||
configservice = self._find_eternus_service(CONSTANTS.STOR_CONF)
|
||||
if configservice is None:
|
||||
if not configservice:
|
||||
msg = (_('_delete_volume, volumename: %(volumename)s, '
|
||||
'Storage Configuration Service not found.')
|
||||
% {'volumename': volumename})
|
||||
@ -698,7 +734,7 @@ class FJDXCommon(object):
|
||||
'vol_name': d_volumename,
|
||||
}
|
||||
|
||||
sdv_no = "0x" + element['DeviceID'][24:28]
|
||||
sdv_no = self._get_volume_number(element)
|
||||
metadata = {'FJ_SDV_Name': d_volumename,
|
||||
'FJ_SDV_No': sdv_no,
|
||||
'FJ_Pool_Name': eternus_pool}
|
||||
@ -710,9 +746,7 @@ class FJDXCommon(object):
|
||||
'snapshot id: %(sid)s, volume id: %(vid)s.',
|
||||
{'sid': snapshot['id'], 'vid': snapshot['volume_id']})
|
||||
|
||||
vol_exist = self.delete_volume(snapshot)
|
||||
LOG.debug('delete_snapshot, vol_exist: %s.', vol_exist)
|
||||
return vol_exist
|
||||
self.delete_volume(snapshot)
|
||||
|
||||
def initialize_connection(self, volume, connector):
|
||||
"""Allow connection to connector and return connection info."""
|
||||
@ -1421,8 +1455,7 @@ class FJDXCommon(object):
|
||||
'classname: %s.', classname)
|
||||
|
||||
try:
|
||||
services = self._enum_eternus_instance_names(
|
||||
str(classname))
|
||||
services = self._enum_eternus_instance_names(str(classname))
|
||||
except Exception:
|
||||
msg = (_('_find_eternus_service, '
|
||||
'classname: %(classname)s, '
|
||||
@ -2426,7 +2459,7 @@ class FJDXCommon(object):
|
||||
|
||||
for vol_instance in vollist:
|
||||
if src_id:
|
||||
volume_no = "0x" + vol_instance['DeviceID'][24:28]
|
||||
volume_no = self._get_volume_number(vol_instance)
|
||||
try:
|
||||
# Skip hidden tppv volumes.
|
||||
if int(src_id) == int(volume_no, 16):
|
||||
@ -2536,6 +2569,22 @@ class FJDXCommon(object):
|
||||
|
||||
return ret
|
||||
|
||||
def _get_volume_number(self, vol):
|
||||
"""Get volume no(return a hex string)."""
|
||||
if self.model_name == CONSTANTS.DX_S2:
|
||||
volume_number = "0x%04X" % int(vol['DeviceID'][-5:])
|
||||
else:
|
||||
volume_number = "0x" + vol['DeviceID'][24:28]
|
||||
|
||||
LOG.debug('_get_volume_number: %s.', volume_number)
|
||||
return volume_number
|
||||
|
||||
def _exec_eternus_smis_ReferenceNames(self, classname,
|
||||
conn=None,
|
||||
**param_dict):
|
||||
ret = conn.ReferenceNames(classname, **param_dict)
|
||||
return ret
|
||||
|
||||
def _check_user(self):
|
||||
"""Check whether user's role is accessible to ETERNUS and Software."""
|
||||
ret = True
|
||||
@ -3131,3 +3180,30 @@ class FJDXCommon(object):
|
||||
'clidata': clidata})
|
||||
LOG.warning(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
def _get_copy_sessions_list(self, **param):
|
||||
"""Get copy sessions list."""
|
||||
LOG.debug('_get_copy_sessions_list, Enter method.')
|
||||
|
||||
rc, emsg, clidata = self._exec_eternus_cli(
|
||||
'show_copy_sessions',
|
||||
**param
|
||||
)
|
||||
|
||||
if rc != 0:
|
||||
msg = (_('_get_copy_sessions_list, '
|
||||
'get copy sessions failed. '
|
||||
'Return code: %(rc)lu, '
|
||||
'Error: %(emsg)s, '
|
||||
'Message: %(clidata)s.')
|
||||
% {'rc': rc,
|
||||
'emsg': emsg,
|
||||
'clidata': clidata})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
LOG.debug('_get_copy_sessions_list, Exit method, '
|
||||
'copy sessions list: %(clidata)s. ',
|
||||
{'clidata': clidata})
|
||||
|
||||
return clidata
|
||||
|
@ -87,8 +87,14 @@ class FJDXFCDriver(driver.FibreChannelDriver):
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""Delete volume on ETERNUS."""
|
||||
LOG.debug('delete_volume, '
|
||||
'volume id: %s, Enter method.', volume['id'])
|
||||
|
||||
self.common.delete_volume(volume)
|
||||
|
||||
LOG.debug('delete_volume, '
|
||||
'volume id: %s, delete succeed.', volume['id'])
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
"""Creates a snapshot."""
|
||||
location, metadata = self.common.create_snapshot(snapshot)
|
||||
|
@ -94,8 +94,14 @@ class FJDXISCSIDriver(driver.ISCSIDriver):
|
||||
|
||||
def delete_volume(self, volume):
|
||||
"""Delete volume on ETERNUS."""
|
||||
LOG.debug('delete_volume, '
|
||||
'volume id: %s, Enter method.', volume['id'])
|
||||
|
||||
self.common.delete_volume(volume)
|
||||
|
||||
LOG.debug('delete_volume, '
|
||||
'volume id: %s, delete succeed.', volume['id'])
|
||||
|
||||
def create_snapshot(self, snapshot):
|
||||
"""Creates a snapshot."""
|
||||
element_path, metadata = self.common.create_snapshot(snapshot)
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Fujitsu ETERNUS DX driver: Improve volume deletion
|
||||
|
||||
To improve the volume deletion process, add a step to check associated copy
|
||||
sessions. Additionally, it also improves the process of retrieving
|
||||
storage-managed volume numbers.
|
||||
|
||||
There was a problem where the volume could not be deleted because the copy
|
||||
session information acquired by SMI-S IF from ETERNUS DX Storage, which was
|
||||
cached and did not reflect the information that had just been executed.
|
||||
|
||||
This problem has been addressed through improvements in information
|
||||
retrieval.
|
Loading…
Reference in New Issue
Block a user