Merge "[NetApp] Pause and resume clone split during rename snapshot"

This commit is contained in:
Zuul 2024-05-21 21:23:20 +00:00 committed by Gerrit Code Review
commit b415ce83ac
8 changed files with 76 additions and 12 deletions

View File

@ -3522,6 +3522,12 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
msg_args = {'snapshot': snapshot_name, 'volume': volume_name}
LOG.info(msg, msg_args)
# Snapshots are locked by clone(s), so split the clone(s)
snapshot_children = self.get_clone_children_for_snapshot(
volume_name, snapshot_name)
for snapshot_child in snapshot_children:
self.volume_clone_split_start(snapshot_child['name'])
@na_utils.trace
def prune_deleted_snapshots(self):
"""Deletes non-busy snapshots that were previously soft-deleted."""

View File

@ -2034,6 +2034,25 @@ class NetAppRestClient(object):
f'/storage/volumes/{uuid}/snapshots/{snapshot_uuid}',
'delete')
@na_utils.trace
def soft_delete_snapshot(self, volume_name, snapshot_name):
"""Deletes a volume snapshot, or renames it if delete fails."""
try:
self.delete_snapshot(volume_name, snapshot_name)
except netapp_api.NaApiError:
self.rename_snapshot(volume_name,
snapshot_name,
DELETED_PREFIX + snapshot_name)
msg = _('Soft-deleted snapshot %(snapshot)s on volume %(volume)s.')
msg_args = {'snapshot': snapshot_name, 'volume': volume_name}
LOG.info(msg, msg_args)
# Snapshots are locked by clone(s), so split the clone(s)
snapshot_children = self.get_clone_children_for_snapshot(
volume_name, snapshot_name)
for snapshot_child in snapshot_children:
self.volume_clone_split_start(snapshot_child['name'])
@na_utils.trace
def rename_snapshot(self, volume_name, snapshot_name, new_snapshot_name):
"""Renames the snapshot."""

View File

@ -1883,13 +1883,14 @@ class NetAppCmodeFileStorageLibrary(object):
vserver_client.delete_snapshot(share_name, snapshot_name)
elif backend_snapshot['locked_by_clone']:
# Snapshots are locked by clone(s), so split the clone(s)
snapshot_children = vserver_client.get_clone_children_for_snapshot(
share_name, snapshot_name)
for snapshot_child in snapshot_children:
vserver_client.volume_clone_split_start(snapshot_child['name'])
if is_flexgroup:
# Snapshots are locked by clone(s), so split the clone(s)
snap_children = vserver_client.get_clone_children_for_snapshot(
share_name, snapshot_name)
for snapshot_child in snap_children:
vserver_client.volume_clone_split_start(
snapshot_child['name'])
# NOTE(felipe_rodrigues): ONTAP does not allow rename a
# FlexGroup snapshot, so it cannot be soft deleted. It will
# wait for all split clones complete.

View File

@ -142,6 +142,13 @@ FPOLICY_EXT_TO_EXCLUDE_LIST = ['jpg', 'mp3']
JOB_ID = 123
JOB_STATE = 'success'
CDOT_CLONE_CHILD_1 = 'fake_child_1'
CDOT_CLONE_CHILD_2 = 'fake_child_2'
CDOT_CLONE_CHILDREN = [
{'name': CDOT_CLONE_CHILD_1},
{'name': CDOT_CLONE_CHILD_2},
]
NETWORK_INTERFACES = [{
'interface_name': 'fake_interface',
'address': IP_ADDRESS,

View File

@ -5116,6 +5116,11 @@ class NetAppClientCmodeTestCase(test.TestCase):
mock_delete_snapshot = self.mock_object(
self.client, 'delete_snapshot', self._mock_api_error())
mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
mock_get_clone_children_for_snapshot = self.mock_object(
self.client, 'get_clone_children_for_snapshot',
mock.Mock(return_value=fake.CDOT_CLONE_CHILDREN))
mock_volume_clone_split_start = self.mock_object(
self.client, 'volume_clone_split_start')
self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
@ -5124,6 +5129,12 @@ class NetAppClientCmodeTestCase(test.TestCase):
mock_rename_snapshot.assert_called_once_with(
fake.SHARE_NAME, fake.SNAPSHOT_NAME,
'deleted_manila_' + fake.SNAPSHOT_NAME)
mock_get_clone_children_for_snapshot.assert_called_once_with(
fake.SHARE_NAME, fake.SNAPSHOT_NAME)
mock_volume_clone_split_start.assert_has_calls([
mock.call(fake.CDOT_CLONE_CHILD_1),
mock.call(fake.CDOT_CLONE_CHILD_2),
])
def test_prune_deleted_snapshots(self):

View File

@ -5941,6 +5941,17 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
ignore_owners)
mock_sr.assert_has_calls(calls)
def test_soft_delete_snapshot(self):
mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot')
mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
mock_delete_snapshot.assert_called_once_with(
fake.SHARE_NAME, fake.SNAPSHOT_NAME)
self.assertFalse(mock_rename_snapshot.called)
def test_volume_has_luns(self):
mock_sr = self.mock_object(self.client, 'send_request')
self.mock_object(self.client, '_has_records',

View File

@ -2618,13 +2618,14 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
is_flexgroup=is_flexgroup)
self.assertFalse(vserver_client.delete_snapshot.called)
vserver_client.get_clone_children_for_snapshot.assert_called_once_with(
fake.SHARE_NAME, fake.SNAPSHOT_NAME)
vserver_client.volume_clone_split_start.assert_has_calls([
mock.call(fake.CDOT_CLONE_CHILD_1),
mock.call(fake.CDOT_CLONE_CHILD_2),
])
if is_flexgroup:
(vserver_client.
get_clone_children_for_snapshot.assert_called_once_with(
fake.SHARE_NAME, fake.SNAPSHOT_NAME))
vserver_client.volume_clone_split_start.assert_has_calls([
mock.call(fake.CDOT_CLONE_CHILD_1),
mock.call(fake.CDOT_CLONE_CHILD_2),
])
mock_is_flexgroup_share.assert_called_once_with(
vserver_client, fake.SHARE_NAME, fake.SNAPSHOT_NAME)
vserver_client.soft_delete_snapshot.assert_not_called()

View File

@ -0,0 +1,8 @@
---
fixes:
- |
In case of NetApp ONTAP driver, when snpashots are soft deleted (i.e. they
are renamed if delete fails) sometime we face issue in during rename. This
is due to busy snapshots. To overcome this, Manila will stop clone split,
perform rename and start clone split again. For more details, please refer
to `launchpad bug 2025641 <https://bugs.launchpad.net/manila/+bug/2025641>`_