Check flashcopy mapping before deleting volume
Check the flashcopy mapping relationship before deleting volume. Currently the volume stays in 'deleting' if there is fcmapping for IBM storwize/SVC driver. Change it to stop the fcmapping first if the volume is the target volume of the fcmapping. DocImpact Change-Id: I99fdbbeda4151d4e02ebd6a0ede9a49eb2abc618 Closes-Bug: 1534118
This commit is contained in:
parent
5097a9eff5
commit
a2bac00c50
@ -3409,6 +3409,50 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
|||||||
self.driver.delete_volume(vol1)
|
self.driver.delete_volume(vol1)
|
||||||
self._assert_vol_exists(vol1['name'], False)
|
self._assert_vol_exists(vol1['name'], False)
|
||||||
|
|
||||||
|
def test_storwize_svc_delete_vol_with_fcmap(self):
|
||||||
|
vol1 = self._create_volume()
|
||||||
|
# create two snapshots
|
||||||
|
snap1 = self._generate_vol_info(vol1['name'], vol1['id'])
|
||||||
|
snap2 = self._generate_vol_info(vol1['name'], vol1['id'])
|
||||||
|
self.driver.create_snapshot(snap1)
|
||||||
|
self.driver.create_snapshot(snap2)
|
||||||
|
vol2 = self._generate_vol_info(None, None)
|
||||||
|
vol3 = self._generate_vol_info(None, None)
|
||||||
|
|
||||||
|
# Create vol from the second snapshot
|
||||||
|
if self.USESIM:
|
||||||
|
self.sim.error_injection('lsfcmap', 'speed_up')
|
||||||
|
self.driver.create_volume_from_snapshot(vol2, snap2)
|
||||||
|
if self.USESIM:
|
||||||
|
# validate copyrate was set on the flash copy
|
||||||
|
for i, fcmap in self.sim._fcmappings_list.items():
|
||||||
|
if fcmap['target'] == vol2['name']:
|
||||||
|
self.assertEqual('copying', fcmap['status'])
|
||||||
|
self._assert_vol_exists(vol2['name'], True)
|
||||||
|
|
||||||
|
if self.USESIM:
|
||||||
|
self.sim.error_injection('lsfcmap', 'speed_up')
|
||||||
|
self.driver.create_cloned_volume(vol3, vol2)
|
||||||
|
|
||||||
|
if self.USESIM:
|
||||||
|
# validate copyrate was set on the flash copy
|
||||||
|
for i, fcmap in self.sim._fcmappings_list.items():
|
||||||
|
if fcmap['target'] == vol3['name']:
|
||||||
|
self.assertEqual('copying', fcmap['status'])
|
||||||
|
self._assert_vol_exists(vol3['name'], True)
|
||||||
|
|
||||||
|
# Delete in the 'opposite' order to make sure it works
|
||||||
|
self.driver.delete_volume(vol3)
|
||||||
|
self._assert_vol_exists(vol3['name'], False)
|
||||||
|
self.driver.delete_volume(vol2)
|
||||||
|
self._assert_vol_exists(vol2['name'], False)
|
||||||
|
self.driver.delete_snapshot(snap2)
|
||||||
|
self._assert_vol_exists(snap2['name'], False)
|
||||||
|
self.driver.delete_snapshot(snap1)
|
||||||
|
self._assert_vol_exists(snap1['name'], False)
|
||||||
|
self.driver.delete_volume(vol1)
|
||||||
|
self._assert_vol_exists(vol1['name'], False)
|
||||||
|
|
||||||
def test_storwize_svc_volumes(self):
|
def test_storwize_svc_volumes(self):
|
||||||
# Create a first volume
|
# Create a first volume
|
||||||
volume = self._generate_vol_info(None, None)
|
volume = self._generate_vol_info(None, None)
|
||||||
|
@ -1419,7 +1419,8 @@ class StorwizeHelpers(object):
|
|||||||
return None
|
return None
|
||||||
return resp[0]
|
return resp[0]
|
||||||
|
|
||||||
def _check_vdisk_fc_mappings(self, name, allow_snaps=True):
|
def _check_vdisk_fc_mappings(self, name,
|
||||||
|
allow_snaps=True, allow_fctgt=False):
|
||||||
"""FlashCopy mapping check helper."""
|
"""FlashCopy mapping check helper."""
|
||||||
LOG.debug('Loopcall: _check_vdisk_fc_mappings(), vdisk %s.', name)
|
LOG.debug('Loopcall: _check_vdisk_fc_mappings(), vdisk %s.', name)
|
||||||
mapping_ids = self._get_vdisk_fc_mappings(name)
|
mapping_ids = self._get_vdisk_fc_mappings(name)
|
||||||
@ -1433,6 +1434,12 @@ class StorwizeHelpers(object):
|
|||||||
copy_rate = attrs['copy_rate']
|
copy_rate = attrs['copy_rate']
|
||||||
status = attrs['status']
|
status = attrs['status']
|
||||||
|
|
||||||
|
if allow_fctgt and target == name and status == 'copying':
|
||||||
|
self.ssh.stopfcmap(map_id)
|
||||||
|
attrs = self._get_flashcopy_mapping_attributes(map_id)
|
||||||
|
if attrs:
|
||||||
|
status = attrs['status']
|
||||||
|
|
||||||
if copy_rate == '0':
|
if copy_rate == '0':
|
||||||
if source == name:
|
if source == name:
|
||||||
# Vdisk with snapshots. Return False if snapshot
|
# Vdisk with snapshots. Return False if snapshot
|
||||||
@ -1463,18 +1470,20 @@ class StorwizeHelpers(object):
|
|||||||
if status == 'prepared':
|
if status == 'prepared':
|
||||||
self.ssh.stopfcmap(map_id)
|
self.ssh.stopfcmap(map_id)
|
||||||
self.ssh.rmfcmap(map_id)
|
self.ssh.rmfcmap(map_id)
|
||||||
elif status == 'idle_or_copied':
|
elif status in ['idle_or_copied', 'stopped']:
|
||||||
# Prepare failed
|
# Prepare failed or stopped
|
||||||
self.ssh.rmfcmap(map_id)
|
self.ssh.rmfcmap(map_id)
|
||||||
else:
|
else:
|
||||||
wait_for_copy = True
|
wait_for_copy = True
|
||||||
if not wait_for_copy or not len(mapping_ids):
|
if not wait_for_copy or not len(mapping_ids):
|
||||||
raise loopingcall.LoopingCallDone(retvalue=True)
|
raise loopingcall.LoopingCallDone(retvalue=True)
|
||||||
|
|
||||||
def ensure_vdisk_no_fc_mappings(self, name, allow_snaps=True):
|
def ensure_vdisk_no_fc_mappings(self, name, allow_snaps=True,
|
||||||
|
allow_fctgt=False):
|
||||||
"""Ensure vdisk has no flashcopy mappings."""
|
"""Ensure vdisk has no flashcopy mappings."""
|
||||||
timer = loopingcall.FixedIntervalLoopingCall(
|
timer = loopingcall.FixedIntervalLoopingCall(
|
||||||
self._check_vdisk_fc_mappings, name, allow_snaps)
|
self._check_vdisk_fc_mappings, name,
|
||||||
|
allow_snaps, allow_fctgt)
|
||||||
# Create a timer greenthread. The default volume service heart
|
# Create a timer greenthread. The default volume service heart
|
||||||
# beat is every 10 seconds. The flashcopy usually takes hours
|
# beat is every 10 seconds. The flashcopy usually takes hours
|
||||||
# before it finishes. Don't set the sleep interval shorter
|
# before it finishes. Don't set the sleep interval shorter
|
||||||
@ -1558,7 +1567,8 @@ class StorwizeHelpers(object):
|
|||||||
if not self.is_vdisk_defined(vdisk):
|
if not self.is_vdisk_defined(vdisk):
|
||||||
LOG.info(_LI('Tried to delete non-existent vdisk %s.'), vdisk)
|
LOG.info(_LI('Tried to delete non-existent vdisk %s.'), vdisk)
|
||||||
return
|
return
|
||||||
self.ensure_vdisk_no_fc_mappings(vdisk)
|
self.ensure_vdisk_no_fc_mappings(vdisk, allow_snaps=True,
|
||||||
|
allow_fctgt=True)
|
||||||
self.ssh.rmvdisk(vdisk, force=force)
|
self.ssh.rmvdisk(vdisk, force=force)
|
||||||
LOG.debug('Leave: delete_vdisk: vdisk %s.', vdisk)
|
LOG.debug('Leave: delete_vdisk: vdisk %s.', vdisk)
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- Fixed StorWize/SVC error causing volume deletion to get
|
||||||
|
stuck in the 'deleting' state when using FlashCopy.
|
Loading…
x
Reference in New Issue
Block a user