NetApp: Implement share metadata update method

Consider two metadata keys i.e. snapshot_policy and showmount.

Partially-implements: blueprint pass-resource-metadata-updates-to-backend-drivers
Depends-on: If4297cca3249359f72976800db2112ea9c61c06f
Change-Id: I042a2caa5884ddea09ecfa0028d01758c18af5a3
This commit is contained in:
Kiran Pawar 2024-07-29 14:40:43 +00:00
parent 4bf505404a
commit 52d423f606
12 changed files with 216 additions and 2 deletions

View File

@ -3733,7 +3733,8 @@ class ShareDriver(object):
"""
raise NotImplementedError()
def update_share_from_metadata(self, context, share, metadata):
def update_share_from_metadata(self, context, share, metadata,
share_server=None):
"""Update the share from metadata.
Driver must implement this method if needs to perform some action
@ -3743,5 +3744,6 @@ class ShareDriver(object):
:param share: Share instance model with share data.
:param metadata: Dict contains key-value pair where driver will
perform necessary action based on key.
:param share_server: Reference to the share server.
"""
raise NotImplementedError()

View File

@ -1600,6 +1600,14 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
'Data ONTAP driver')
raise exception.NetAppException(msg % security_service['type'])
@na_utils.trace
def update_showmount(self, showmount):
"""Update show mount for vserver. """
nfs_service_modify_arg = {
'showmount': showmount
}
self.send_request('nfs-service-modify', nfs_service_modify_arg)
@na_utils.trace
def enable_nfs(self, versions, nfs_config=None):
"""Enables NFS on Vserver."""
@ -2326,6 +2334,27 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
return api_args
@na_utils.trace
def update_volume_snapshot_policy(self, volume_name, snapshot_policy):
"""Set snapshot policy for the specified volume."""
api_args = {
'query': {
'volume-attributes': {
'volume-id-attributes': {
'name': volume_name,
},
},
},
'attributes': {
'volume-attributes': {
'volume-snapshot-attributes': {
'snapshot-policy': snapshot_policy,
},
},
},
}
self.send_request('volume-modify-iter', api_args)
@na_utils.trace
@manila_utils.retry(retry_param=exception.NetAppException,
interval=3,

View File

@ -1110,6 +1110,18 @@ class NetAppRestClient(object):
'compression': compression,
}
@na_utils.trace
def update_volume_snapshot_policy(self, volume_name, snapshot_policy):
"""Set snapshot policy for the specified volume."""
volume = self._get_volume_by_args(vol_name=volume_name)
uuid = volume['uuid']
body = {
'snapshot_policy.name': snapshot_policy
}
# update snapshot policy
self.send_request(f'/storage/volumes/{uuid}', 'patch', body=body)
@na_utils.trace
def update_volume_efficiency_attributes(self, volume_name, dedup_enabled,
compression_enabled,
@ -4686,6 +4698,26 @@ class NetAppRestClient(object):
}
raise exception.NetAppException(msg % msg_args)
@na_utils.trace
def update_showmount(self, showmount):
"""Update show mount for vserver. """
# Get SVM UUID.
query = {
'name': self.vserver,
'fields': 'uuid'
}
res = self.send_request('/svm/svms', 'get', query=query)
if not res.get('records'):
msg = _('Vserver %s not found.') % self.vserver
raise exception.NetAppException(msg)
svm_id = res.get('records')[0]['uuid']
body = {
'showmount_enabled': showmount,
}
self.send_request(f'/protocols/nfs/services/{svm_id}', 'patch',
body=body)
@na_utils.trace
def enable_nfs(self, versions, nfs_config=None):
"""Enables NFS on Vserver."""

View File

@ -398,3 +398,8 @@ class NetAppCmodeMultiSvmShareDriver(driver.ShareDriver):
def delete_backup(self, context, backup, share, **kwargs):
return self.library.delete_backup(context, backup, share, **kwargs)
def update_share_from_metadata(self, context, share, metadata,
share_server=None):
self.library.update_share_from_metadata(
context, share, metadata, share_server=share_server)

View File

@ -362,3 +362,8 @@ class NetAppCmodeSingleSvmShareDriver(driver.ShareDriver):
def delete_backup(self, context, backup, share, **kwargs):
return self.library.delete_backup(context, backup, share, **kwargs)
def update_share_from_metadata(self, context, share, metadata,
share_server=None):
self.library.update_share_from_metadata(
context, share, metadata, share_server=share_server)

View File

@ -5014,3 +5014,29 @@ class NetAppCmodeFileStorageLibrary(object):
# Delete Vserver
if share_server is not None:
self._delete_backup_vserver(backup, des_vserver)
@na_utils.trace
def update_volume_snapshot_policy(self, share, snapshot_policy,
share_server=None):
share_name = self._get_backend_share_name(share['id'])
_, vserver_client = self._get_vserver(share_server=share_server)
vserver_client.update_volume_snapshot_policy(share_name,
snapshot_policy)
@na_utils.trace
def update_showmount(self, share, showmount, share_server=None):
_, vserver_client = self._get_vserver(share_server=share_server)
vserver_client.update_showmount(showmount)
@na_utils.trace
def update_share_from_metadata(self, context, share, metadata,
share_server=None):
metadata_update_func_map = {
"snapshot_policy": "update_volume_snapshot_policy",
"showmount": "update_showmount",
}
for k, v in metadata.items():
update_func = getattr(self, metadata_update_func_map.get(k))
if update_func:
update_func(share, v, share_server=share_server)

View File

@ -6759,9 +6759,10 @@ class ShareManager(manager.SchedulerDependentManager):
def update_share_from_metadata(self, context, share_id, metadata):
share = self.db.share_get(context, share_id)
share_instance = self._get_share_instance(context, share)
share_server = self._get_share_server(context, share_instance)
try:
self.driver.update_share_from_metadata(context, share_instance,
metadata)
metadata, share_server)
self.message_api.create(
context,
message_field.Action.UPDATE_METADATA,

View File

@ -1054,3 +1054,10 @@ class DummyDriver(driver.ShareDriver):
{'backup': backup['id'],
'share': share_instance['share_id']})
return {'total_progress': '100'}
def update_share_from_metadata(self, context, share_instance, metadata,
share_server=None):
LOG.debug("Updated share %(share)s. Metadata %(metadata)s "
"applied successfully.",
{'share': share_instance['share_id'],
'metadata': metadata})

View File

@ -2534,6 +2534,19 @@ class NetAppClientCmodeTestCase(test.TestCase):
self.client.send_request.assert_has_calls([
mock.call('vserver-modify', vserver_modify_args)])
def test_update_showmount(self):
self.mock_object(self.client, 'send_request')
fake_showmount = 'true'
self.client.update_showmount(fake_showmount)
nfs_service_modify_args = {
'showmount': fake_showmount,
}
self.client.send_request.assert_called_once_with(
'nfs-service-modify', nfs_service_modify_args)
@ddt.data({'tcp-max-xfer-size': 10000}, {}, None)
def test_enable_nfs(self, nfs_config):
@ -3490,6 +3503,32 @@ class NetAppClientCmodeTestCase(test.TestCase):
self.assertFalse(result)
def test_update_volume_snapshot_policy(self):
self.mock_object(self.client, 'send_request')
self.client.update_volume_snapshot_policy(fake.SHARE_NAME,
fake.SNAPSHOT_POLICY_NAME)
volume_modify_iter_api_args = {
'query': {
'volume-attributes': {
'volume-id-attributes': {
'name': fake.SHARE_NAME,
},
},
},
'attributes': {
'volume-attributes': {
'volume-snapshot-attributes': {
'snapshot-policy': fake.SNAPSHOT_POLICY_NAME,
},
},
},
}
self.client.send_request.assert_called_once_with(
'volume-modify-iter', volume_modify_iter_api_args)
def test_enable_dedup(self):
self.mock_object(self.client, 'send_request')

View File

@ -2766,6 +2766,23 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
self.client.get_job_state,
'fake_uuid')
def test_update_volume_snapshot_policy(self):
return_uuid = {
'uuid': 'fake_uuid'
}
mock_get_vol = self.mock_object(self.client, '_get_volume_by_args',
mock.Mock(return_value=return_uuid))
mock_sr = self.mock_object(self.client, 'send_request')
self.client.update_volume_snapshot_policy('fake_volume_name',
fake.SNAPSHOT_POLICY_NAME)
body = {
'snapshot_policy.name': fake.SNAPSHOT_POLICY_NAME
}
mock_sr.assert_called_once_with('/storage/volumes/fake_uuid',
'patch', body=body)
mock_get_vol.assert_called_once_with(vol_name='fake_volume_name')
@ddt.data(True, False)
def test_update_volume_efficiency_attributes(self, status):
response = {
@ -4499,6 +4516,31 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
self.client.send_request.assert_called_once_with(
'/svm/peers/fake_uuid', 'delete', enable_tunneling=False)
def test_update_showmount(self):
query = {
'name': fake.VSERVER_NAME,
'fields': 'uuid'
}
response_svm = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
self.client.vserver = fake.VSERVER_NAME
self.mock_object(self.client,
'send_request',
mock.Mock(side_effect=[response_svm, None]))
fake_showmount = 'true'
self.client.update_showmount(fake_showmount)
svm_id = response_svm.get('records')[0]['uuid']
body = {
'showmount_enabled': fake_showmount,
}
self.client.send_request.assert_has_calls([
mock.call('/svm/svms', 'get', query=query),
mock.call(f'/protocols/nfs/services/{svm_id}',
'patch', body=body)
])
@ddt.data({'tcp-max-xfer-size': 10000}, {}, None)
def test_enable_nfs(self, nfs_config):
self.mock_object(self.client, '_get_unique_svm_by_name',

View File

@ -8905,3 +8905,23 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.mock_object(mock_des_client,
'list_volume_snapshots',
mock.Mock(return_value=snap_list))
def test_update_share_from_metadata(self):
metadata = {
"snapshot_policy": "daily",
"showmount": "True",
}
share_instance = fake.SHARE_INSTANCE
mock_update_volume_snapshot_policy = self.mock_object(
self.library, 'update_volume_snapshot_policy')
mock_update_showmount = self.mock_object(
self.library, 'update_showmount')
self.library.update_share_from_metadata(self.context, share_instance,
metadata)
mock_update_volume_snapshot_policy.assert_called_once_with(
share_instance, "daily", share_server=None)
mock_update_showmount.assert_called_once_with(
share_instance, "True", share_server=None)

View File

@ -0,0 +1,6 @@
---
fixes:
- |
The NetApp ONTAP driver is now able to update the current `snapshot_policy`
and/or both `showmount` configurations in a pre-created share. Please use
the share metadata set feature to update these values.