PowerMax Driver - Fix for GVG snapshot delete

If a Generic Volume Group (PowerMax storage group) has volumes
added or removed from it since a group snapshot was taken, the
deletion of this group snapshot will fail unless a force flag
is supplied.

Change-Id: I97bdc54e41aa51bf44e986cc1779b92acea2b47d
This commit is contained in:
Helen Walsh 2021-08-19 15:11:30 +01:00
parent d3ab9ccbaf
commit 794e31bba3
3 changed files with 27 additions and 3 deletions

View File

@ -14,6 +14,7 @@
# under the License. # under the License.
from unittest import mock from unittest import mock
from unittest.mock import call
from cinder import exception from cinder import exception
from cinder.tests.unit import test from cinder.tests.unit import test
@ -497,6 +498,23 @@ class PowerMaxProvisionTest(test.TestCase):
array, snap_name, source_group_name) array, snap_name, source_group_name)
mock_del.assert_not_called() mock_del.assert_not_called()
@mock.patch.object(rest.PowerMaxRest,
'get_storage_group_snap_id_list',
return_value=[tpd.PowerMaxData.snap_id])
@mock.patch.object(rest.PowerMaxRest,
'delete_storagegroup_snap')
def test_delete_group_replica_exception_call_args(
self, mck_del_ss, mck_snap_list):
array = self.data.array
snap_name = self.data.group_snapshot_name
source_group_name = self.data.storagegroup_name_source
self.provision.delete_group_replica(
array, snap_name, source_group_name)
expected = [call('000197800123', 'Grp_source_sg',
'Grp_snapshot', 118749976833, force=True)]
self.assertEqual(expected, mck_del_ss.call_args_list)
def test_link_and_break_replica(self): def test_link_and_break_replica(self):
array = self.data.array array = self.data.array
source_group_name = self.data.storagegroup_name_source source_group_name = self.data.storagegroup_name_source

View File

@ -663,7 +663,8 @@ class PowerMaxProvision(object):
snap_id_list.sort(reverse=True) snap_id_list.sort(reverse=True)
for snap_id in snap_id_list: for snap_id in snap_id_list:
self.rest.delete_storagegroup_snap( self.rest.delete_storagegroup_snap(
array, source_group_name, snap_name, snap_id) array, source_group_name, snap_name, snap_id,
force=True)
else: else:
LOG.debug("Unable to get snap ids for: %(srcGroup)s.", LOG.debug("Unable to get snap ids for: %(srcGroup)s.",
{'srcGroup': source_group_name}) {'srcGroup': source_group_name})

View File

@ -3116,14 +3116,18 @@ class PowerMaxRest(object):
job, extra_specs) job, extra_specs)
def delete_storagegroup_snap(self, array, source_group, def delete_storagegroup_snap(self, array, source_group,
snap_name, snap_id): snap_name, snap_id, force=False):
"""Delete a snapVx snapshot of a storage group. """Delete a snapVx snapshot of a storage group.
:param array: the array serial number :param array: the array serial number
:param source_group: the source group name :param source_group: the source group name
:param snap_name: the name of the snapshot :param snap_name: the name of the snapshot
:param snap_id: the unique snap id of the SnapVX :param snap_id: the unique snap id of the SnapVX
:param force: optional force flag
""" """
force_flag = "true" if force else "false"
query_params = {'force': force_flag} if force else None
postfix_uri = "/snapid/%s" % snap_id if self.is_snap_id else ( postfix_uri = "/snapid/%s" % snap_id if self.is_snap_id else (
"/generation/%s" % snap_id) "/generation/%s" % snap_id)
@ -3133,7 +3137,8 @@ class PowerMaxRest(object):
'postfix_uri': postfix_uri}) 'postfix_uri': postfix_uri})
self.delete_resource( self.delete_resource(
array, REPLICATION, 'storagegroup', resource_name=resource_name) array, REPLICATION, 'storagegroup', resource_name=resource_name,
params=query_params)
def get_storage_group_snap_id_list( def get_storage_group_snap_id_list(
self, array, source_group, snap_name): self, array, source_group, snap_name):