Merge "Allow drivers to set share size after revert to snapshot"

This commit is contained in:
Zuul 2024-08-29 14:37:14 +00:00 committed by Gerrit Code Review
commit bfe28f07c0
5 changed files with 74 additions and 23 deletions

View File

@ -1831,6 +1831,10 @@ class NetAppCmodeFileStorageLibrary(object):
self._get_backend_snapshot_name(snapshot['id'])) self._get_backend_snapshot_name(snapshot['id']))
LOG.debug('Restoring snapshot %s', snapshot_name) LOG.debug('Restoring snapshot %s', snapshot_name)
vserver_client.restore_snapshot(share_name, snapshot_name) vserver_client.restore_snapshot(share_name, snapshot_name)
volume = vserver_client.get_volume(share_name)
# When calculating the size, round up to the next GB.
return int(math.ceil(float(volume['size']) / units.Gi))
@na_utils.trace @na_utils.trace
def delete_snapshot(self, context, snapshot, share_server=None, def delete_snapshot(self, context, snapshot, share_server=None,

View File

@ -3463,7 +3463,8 @@ class ShareManager(manager.SchedulerDependentManager):
context, snapshot_instance, snapshot=snapshot) context, snapshot_instance, snapshot=snapshot)
try: try:
self.driver.revert_to_snapshot(context, updated_share_size = self.driver.revert_to_snapshot(
context,
snapshot_instance_dict, snapshot_instance_dict,
share_access_rules, share_access_rules,
snapshot_access_rules, snapshot_access_rules,
@ -3496,15 +3497,37 @@ class ShareManager(manager.SchedulerDependentManager):
resource_id=share_id, resource_id=share_id,
exception=excep) exception=excep)
# fail-safe in case driver returned size is None or invalid
if not updated_share_size:
updated_share_size = snapshot['size']
else:
try:
int(updated_share_size)
except ValueError:
updated_share_size = snapshot['size']
if reservations: if reservations:
if updated_share_size == snapshot['size']:
QUOTAS.commit( QUOTAS.commit(
context, reservations, project_id=project_id, user_id=user_id, context, reservations, project_id=project_id,
share_type_id=share_type_id, user_id=user_id, share_type_id=share_type_id,
) )
else:
# NOTE(kpdev): The driver tells us that the share size wasn't
# modified to the snapshot's size; so no need to commit quota
# changes
QUOTAS.rollback(
context, reservations, project_id=project_id,
user_id=user_id, share_type_id=share_type_id,
)
if updated_share_size != share['size']:
LOG.error("Driver returned an unexpected size %d on "
"revert to snapshot operation. You need to "
"adjust the quota", updated_share_size)
self.db.share_update( self.db.share_update(
context, share_id, context, share_id,
{'status': constants.STATUS_AVAILABLE, 'size': snapshot['size']}) {'status': constants.STATUS_AVAILABLE, 'size': updated_share_size})
self.db.share_snapshot_update( self.db.share_snapshot_update(
context, snapshot_id, {'status': constants.STATUS_AVAILABLE}) context, snapshot_id, {'status': constants.STATUS_AVAILABLE})

View File

@ -2449,6 +2449,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
'_get_vserver', '_get_vserver',
mock.Mock(return_value=(fake.VSERVER1, mock.Mock(return_value=(fake.VSERVER1,
vserver_client))) vserver_client)))
vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
fake_snapshot = copy.deepcopy(fake.SNAPSHOT) fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
if use_snap_provider_location: if use_snap_provider_location:
fake_snapshot['provider_location'] = 'fake-provider-location' fake_snapshot['provider_location'] = 'fake-provider-location'
@ -2458,7 +2459,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
result = self.library.revert_to_snapshot( result = self.library.revert_to_snapshot(
self.context, fake_snapshot, share_server=fake.SHARE_SERVER) self.context, fake_snapshot, share_server=fake.SHARE_SERVER)
self.assertIsNone(result) self.assertIsNotNone(result)
share_name = self.library._get_backend_share_name( share_name = self.library._get_backend_share_name(
fake_snapshot['share_id']) fake_snapshot['share_id'])
snapshot_name = (self.library._get_backend_snapshot_name( snapshot_name = (self.library._get_backend_snapshot_name(

View File

@ -7930,9 +7930,12 @@ class ShareManagerTestCase(test.TestCase):
mock.ANY, share, snapshot, reservations, share_access_rules, mock.ANY, share, snapshot, reservations, share_access_rules,
snapshot_access_rules, share_id=share_id) snapshot_access_rules, share_id=share_id)
@ddt.data(None, 'fake_reservations') @ddt.data((None, False),
def test__revert_to_snapshot(self, reservations): (None, True),
('fake_reservations', False),
('fake_reservations', True))
@ddt.unpack
def test__revert_to_snapshot(self, reservations, revert_return_share_size):
mock_quotas_rollback = self.mock_object(quota.QUOTAS, 'rollback') mock_quotas_rollback = self.mock_object(quota.QUOTAS, 'rollback')
mock_quotas_commit = self.mock_object(quota.QUOTAS, 'commit') mock_quotas_commit = self.mock_object(quota.QUOTAS, 'commit')
self.mock_object( self.mock_object(
@ -7944,14 +7947,15 @@ class ShareManagerTestCase(test.TestCase):
share = fakes.fake_share( share = fakes.fake_share(
id=share_id, instance={'id': 'fake_instance_id', id=share_id, instance={'id': 'fake_instance_id',
'share_type_id': 'fake_share_type_id'}, 'share_type_id': 'fake_share_type_id'},
project_id='fake_project', user_id='fake_user', size=2) project_id='fake_project', user_id='fake_user',
size=5 if revert_return_share_size else 3)
snapshot_instance = fakes.fake_snapshot_instance( snapshot_instance = fakes.fake_snapshot_instance(
share_id=share_id, share=share, name='fake_snapshot', share_id=share_id, share=share, name='fake_snapshot',
share_instance=share['instance']) share_instance=share['instance'])
snapshot = fakes.fake_snapshot( snapshot = fakes.fake_snapshot(
id='fake_snapshot_id', share_id=share_id, share=share, id='fake_snapshot_id', share_id=share_id, share=share,
instance=snapshot_instance, project_id='fake_project', instance=snapshot_instance, project_id='fake_project',
user_id='fake_user', size=1) user_id='fake_user', size=4)
share_access_rules = [] share_access_rules = []
snapshot_access_rules = [] snapshot_access_rules = []
@ -7965,6 +7969,8 @@ class ShareManagerTestCase(test.TestCase):
self.share_manager.db, 'share_update') self.share_manager.db, 'share_update')
mock_share_snapshot_update = self.mock_object( mock_share_snapshot_update = self.mock_object(
self.share_manager.db, 'share_snapshot_update') self.share_manager.db, 'share_snapshot_update')
mock_driver.revert_to_snapshot.return_value = (
5 if revert_return_share_size else None)
self.share_manager._revert_to_snapshot(self.context, share, snapshot, self.share_manager._revert_to_snapshot(self.context, share, snapshot,
reservations, reservations,
@ -7978,8 +7984,15 @@ class ShareManagerTestCase(test.TestCase):
share_access_rules, snapshot_access_rules, share_access_rules, snapshot_access_rules,
share_server=None) share_server=None)
self.assertFalse(mock_quotas_rollback.called)
if reservations: if reservations:
if revert_return_share_size:
mock_quotas_rollback.assert_called_once_with(
mock.ANY, reservations, project_id='fake_project',
user_id='fake_user',
share_type_id=(
snapshot_instance['share_instance']['share_type_id']))
else:
self.assertFalse(mock_quotas_rollback.called)
mock_quotas_commit.assert_called_once_with( mock_quotas_commit.assert_called_once_with(
mock.ANY, reservations, project_id='fake_project', mock.ANY, reservations, project_id='fake_project',
user_id='fake_user', user_id='fake_user',
@ -7990,7 +8003,8 @@ class ShareManagerTestCase(test.TestCase):
mock_share_update.assert_called_once_with( mock_share_update.assert_called_once_with(
mock.ANY, share_id, mock.ANY, share_id,
{'status': constants.STATUS_AVAILABLE, 'size': snapshot['size']}) {'status': constants.STATUS_AVAILABLE,
'size': 5 if revert_return_share_size else 4})
mock_share_snapshot_update.assert_called_once_with( mock_share_snapshot_update.assert_called_once_with(
mock.ANY, 'fake_snapshot_id', mock.ANY, 'fake_snapshot_id',
{'status': constants.STATUS_AVAILABLE}) {'status': constants.STATUS_AVAILABLE})

View File

@ -0,0 +1,9 @@
---
fixes:
- |
When reverting shares to snapshots that are larger or smaller than
the share, some storage systems such as NetApp ONTAP always defer
to the larger of the two sizes. Manila's share manager interface now
accounts for this behavior, and adjusts project quotas appropriately.
For more details, please check
Launchpad `bug 2064502 <https://bugs.launchpad.net/manila/+bug/2064502>`_