[Netapp] make deleted volume retention period configurable
The NetApp driver now supports user configurable volume delete retention period (in hours). Also, the max value of share manager config option ``unused_share_server_cleanup_interval`` is updated to possible max value of retention period because if a share server gets deleted, the volume recovery queue also gets purged. Co-Authored-By: Maurice Escher <maurice.escher@sap.com> Closes-bug: #2085112 Change-Id: I578de1ce5b162e8d378d94f1ea7ac83a394a1fcd
This commit is contained in:
parent
27f3663a46
commit
998f9f24cf
@ -80,6 +80,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
||||
ontapi_1_191 = ontapi_version >= (1, 191)
|
||||
ontap_9_10 = self.get_system_version()['version-tuple'] >= (9, 10, 0)
|
||||
ontap_9_10_1 = self.get_system_version()['version-tuple'] >= (9, 10, 1)
|
||||
ontap_9_11_1 = self.get_system_version()['version-tuple'] >= (9, 11, 1)
|
||||
|
||||
self.features.add_feature('SNAPMIRROR_V2', supported=ontapi_1_20)
|
||||
self.features.add_feature('SYSTEM_METRICS', supported=ontapi_1_2x)
|
||||
@ -106,6 +107,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
||||
self.features.add_feature('SVM_MIGRATE', supported=ontap_9_10)
|
||||
self.features.add_feature('SNAPLOCK', supported=ontapi_1_100)
|
||||
self.features.add_feature('UNIFIED_AGGR', supported=ontap_9_10_1)
|
||||
self.features.add_feature('DELETE_RETENTION_HOURS',
|
||||
supported=ontap_9_11_1)
|
||||
|
||||
def _invoke_vserver_api(self, na_element, vserver):
|
||||
server = copy.copy(self.connection)
|
||||
@ -181,10 +184,11 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
||||
@na_utils.trace
|
||||
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
||||
root_volume_name, aggregate_names, ipspace_name,
|
||||
security_cert_expire_days):
|
||||
security_cert_expire_days, delete_retention_hours):
|
||||
"""Creates new vserver and assigns aggregates."""
|
||||
self._create_vserver(
|
||||
vserver_name, aggregate_names, ipspace_name,
|
||||
delete_retention_hours,
|
||||
root_volume_name=root_volume_name,
|
||||
root_volume_aggregate_name=root_volume_aggregate_name,
|
||||
root_volume_security_style='unix',
|
||||
@ -193,14 +197,15 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
||||
|
||||
@na_utils.trace
|
||||
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
||||
ipspace_name):
|
||||
ipspace_name, delete_retention_hours):
|
||||
"""Creates new 'dp_destination' vserver and assigns aggregates."""
|
||||
self._create_vserver(
|
||||
vserver_name, aggregate_names, ipspace_name,
|
||||
subtype='dp_destination')
|
||||
delete_retention_hours, subtype='dp_destination')
|
||||
|
||||
@na_utils.trace
|
||||
def _create_vserver(self, vserver_name, aggregate_names, ipspace_name,
|
||||
delete_retention_hours,
|
||||
root_volume_name=None, root_volume_aggregate_name=None,
|
||||
root_volume_security_style=None,
|
||||
name_server_switch=None, subtype=None):
|
||||
@ -235,6 +240,11 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
||||
'aggr-list': aggr_list,
|
||||
'vserver-name': vserver_name,
|
||||
}
|
||||
if (delete_retention_hours != 0 and
|
||||
self.features.DELETE_RETENTION_HOURS):
|
||||
modify_args.update(
|
||||
{'volume-delete-retention-hours': delete_retention_hours})
|
||||
|
||||
self.send_request('vserver-modify', modify_args)
|
||||
|
||||
@na_utils.trace
|
||||
|
@ -4347,7 +4347,7 @@ class NetAppRestClient(object):
|
||||
@na_utils.trace
|
||||
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
||||
root_volume_name, aggregate_names, ipspace_name,
|
||||
security_cert_expire_days):
|
||||
security_cert_expire_days, delete_retention_hours):
|
||||
"""Creates new vserver and assigns aggregates."""
|
||||
|
||||
# NOTE(nahimsouza): root_volume_aggregate_name and root_volume_name
|
||||
@ -4355,19 +4355,20 @@ class NetAppRestClient(object):
|
||||
# the vserver creation by REST API
|
||||
self._create_vserver(
|
||||
vserver_name, aggregate_names, ipspace_name,
|
||||
name_server_switch=['files'])
|
||||
delete_retention_hours, name_server_switch=['files'])
|
||||
self._modify_security_cert(vserver_name, security_cert_expire_days)
|
||||
|
||||
@na_utils.trace
|
||||
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
||||
ipspace_name):
|
||||
ipspace_name, delete_retention_hours):
|
||||
"""Creates new 'dp_destination' vserver and assigns aggregates."""
|
||||
self._create_vserver(
|
||||
vserver_name, aggregate_names, ipspace_name,
|
||||
subtype='dp_destination')
|
||||
delete_retention_hours, subtype='dp_destination')
|
||||
|
||||
@na_utils.trace
|
||||
def _create_vserver(self, vserver_name, aggregate_names, ipspace_name,
|
||||
delete_retention_hours,
|
||||
name_server_switch=None, subtype=None):
|
||||
"""Creates new vserver and assigns aggregates."""
|
||||
body = {
|
||||
@ -4387,6 +4388,9 @@ class NetAppRestClient(object):
|
||||
for aggr_name in aggregate_names:
|
||||
body['aggregates'].append({'name': aggr_name})
|
||||
|
||||
if delete_retention_hours != 0:
|
||||
body['retention_period'] = delete_retention_hours
|
||||
|
||||
self.send_request('/svm/svms', 'post', body=body)
|
||||
|
||||
@na_utils.trace
|
||||
|
@ -333,7 +333,8 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
||||
self._client.create_vserver_dp_destination(
|
||||
vserver_name,
|
||||
aggregate_names,
|
||||
ipspace_name)
|
||||
ipspace_name,
|
||||
self.configuration.netapp_delete_retention_hours)
|
||||
# Set up port and broadcast domain for the current ipspace
|
||||
self._create_port_and_broadcast_domain(
|
||||
ipspace_name, network_info[0])
|
||||
@ -347,7 +348,8 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
||||
self.configuration.netapp_root_volume,
|
||||
aggr_set,
|
||||
ipspace_name,
|
||||
self.configuration.netapp_security_cert_expire_days)
|
||||
self.configuration.netapp_security_cert_expire_days,
|
||||
self.configuration.netapp_delete_retention_hours)
|
||||
|
||||
vserver_client = self._get_api_client(vserver=vserver_name)
|
||||
|
||||
|
@ -107,6 +107,11 @@ netapp_provisioning_opts = [
|
||||
cfg.StrOpt('netapp_root_volume',
|
||||
default='root',
|
||||
help='Root volume name.'),
|
||||
cfg.IntOpt('netapp_delete_retention_hours',
|
||||
min=0,
|
||||
default=12,
|
||||
help='The number of hours that a deleted volume should be '
|
||||
'retained before the delete is completed.'),
|
||||
cfg.IntOpt('netapp_volume_snapshot_reserve_percent',
|
||||
min=0,
|
||||
max=90,
|
||||
|
@ -87,7 +87,7 @@ share_manager_opts = [
|
||||
cfg.IntOpt('unused_share_server_cleanup_interval',
|
||||
default=10,
|
||||
help='Unallocated share servers reclamation time interval '
|
||||
'(minutes). Minimum value is 10 minutes, maximum is 60 '
|
||||
'(minutes). Minimum value is 10 minutes, maximum is 720 '
|
||||
'minutes. The reclamation function is run every '
|
||||
'10 minutes and delete share servers which were unused '
|
||||
'more than unused_share_server_cleanup_interval option '
|
||||
@ -95,7 +95,7 @@ share_manager_opts = [
|
||||
'will wait for a share server to go unutilized before '
|
||||
'deleting it.',
|
||||
min=10,
|
||||
max=60),
|
||||
max=720),
|
||||
cfg.IntOpt('replica_state_update_interval',
|
||||
default=300,
|
||||
help='This value, specified in seconds, determines how often '
|
||||
|
@ -52,6 +52,7 @@ NODE_VSERVER_NAME = 'fake_node_vserver'
|
||||
NFS_VERSIONS = ['nfs3', 'nfs4.0']
|
||||
SECURITY_CERT_DEFAULT_EXPIRE_DAYS = 365
|
||||
SECURITY_CERT_LARGE_EXPIRE_DAYS = 3652
|
||||
DELETE_RETENTION_HOURS = 12
|
||||
ROOT_AGGREGATE_NAMES = ('root_aggr1', 'root_aggr2')
|
||||
ROOT_VOLUME_AGGREGATE_NAME = 'fake_root_aggr'
|
||||
ROOT_VOLUME_NAME = 'fake_root_volume'
|
||||
|
@ -419,6 +419,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
|
||||
def test_create_vserver_no_ipspace(self):
|
||||
|
||||
self.client.features.add_feature('DELETE_RETENTION_HOURS')
|
||||
self.mock_object(self.client, 'send_request')
|
||||
self.mock_object(self.client,
|
||||
'_modify_security_cert',
|
||||
@ -434,7 +435,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
vserver_modify_args = {
|
||||
'aggr-list': [{'aggr-name': aggr_name} for aggr_name
|
||||
in fake.SHARE_AGGREGATE_NAMES],
|
||||
'vserver-name': fake.VSERVER_NAME
|
||||
'vserver-name': fake.VSERVER_NAME,
|
||||
'volume-delete-retention-hours': 16,
|
||||
}
|
||||
|
||||
self.client.create_vserver(fake.VSERVER_NAME,
|
||||
@ -442,7 +444,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
None,
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS,
|
||||
16)
|
||||
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-create', vserver_create_args),
|
||||
@ -453,6 +456,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
def test_create_vserver_with_ipspace(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
self.client.features.add_feature('DELETE_RETENTION_HOURS')
|
||||
self.mock_object(self.client, 'send_request')
|
||||
self.mock_object(self.client,
|
||||
'_modify_security_cert',
|
||||
@ -469,6 +473,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
vserver_modify_args = {
|
||||
'aggr-list': [{'aggr-name': aggr_name} for aggr_name
|
||||
in fake.SHARE_AGGREGATE_NAMES],
|
||||
'volume-delete-retention-hours': 24,
|
||||
'vserver-name': fake.VSERVER_NAME
|
||||
}
|
||||
|
||||
@ -477,7 +482,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
fake.IPSPACE_NAME,
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS,
|
||||
24)
|
||||
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-create', vserver_create_args),
|
||||
@ -539,6 +545,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
def test_create_vserver_dp_destination(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
self.client.features.add_feature('DELETE_RETENTION_HOURS')
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
vserver_create_args = {
|
||||
@ -549,13 +556,15 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
vserver_modify_args = {
|
||||
'aggr-list': [{'aggr-name': aggr_name} for aggr_name
|
||||
in fake.SHARE_AGGREGATE_NAMES],
|
||||
'volume-delete-retention-hours': 18,
|
||||
'vserver-name': fake.VSERVER_NAME
|
||||
}
|
||||
|
||||
self.client.create_vserver_dp_destination(
|
||||
fake.VSERVER_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
fake.IPSPACE_NAME)
|
||||
fake.IPSPACE_NAME,
|
||||
18)
|
||||
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-create', vserver_create_args),
|
||||
@ -570,7 +579,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
fake.IPSPACE_NAME,
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS,
|
||||
10)
|
||||
|
||||
def test_get_vserver_root_volume_name(self):
|
||||
|
||||
|
@ -5029,10 +5029,12 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
||||
self.client.create_vserver(fake.VSERVER_NAME, None, None,
|
||||
[fake.SHARE_AGGREGATE_NAME],
|
||||
fake.IPSPACE_NAME,
|
||||
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
|
||||
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS,
|
||||
fake.DELETE_RETENTION_HOURS)
|
||||
mock.assert_called_once_with(fake.VSERVER_NAME,
|
||||
[fake.SHARE_AGGREGATE_NAME],
|
||||
fake.IPSPACE_NAME,
|
||||
fake.DELETE_RETENTION_HOURS,
|
||||
name_server_switch=['files'])
|
||||
self.client._modify_security_cert.assert_called_once_with(
|
||||
fake.VSERVER_NAME,
|
||||
@ -5991,12 +5993,14 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
||||
'ipspace.name': fake.IPSPACE_NAME,
|
||||
'aggregates': [{
|
||||
'name': fake.SHARE_AGGREGATE_NAME
|
||||
}]
|
||||
}],
|
||||
'retention_period': fake.DELETE_RETENTION_HOURS,
|
||||
}
|
||||
|
||||
self.client._create_vserver(fake.VSERVER_NAME,
|
||||
[fake.SHARE_AGGREGATE_NAME],
|
||||
fake.IPSPACE_NAME,
|
||||
fake.DELETE_RETENTION_HOURS,
|
||||
fake.FAKE_SERVER_SWITCH_NAME,
|
||||
fake.FAKE_SUBTYPE)
|
||||
|
||||
@ -6819,10 +6823,12 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
||||
mock_vserver = self.mock_object(self.client, '_create_vserver')
|
||||
self.client.create_vserver_dp_destination(fake.VSERVER_NAME,
|
||||
fake.FAKE_AGGR_LIST,
|
||||
fake.IPSPACE_NAME)
|
||||
fake.IPSPACE_NAME,
|
||||
fake.DELETE_RETENTION_HOURS)
|
||||
mock_vserver.assert_called_once_with(fake.VSERVER_NAME,
|
||||
fake.FAKE_AGGR_LIST,
|
||||
fake.IPSPACE_NAME,
|
||||
fake.DELETE_RETENTION_HOURS,
|
||||
subtype='dp_destination')
|
||||
|
||||
@ddt.data(':', '.')
|
||||
|
@ -734,7 +734,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
self.library._client.create_vserver.assert_called_once_with(
|
||||
vserver_name, fake.ROOT_VOLUME_AGGREGATE, fake.ROOT_VOLUME,
|
||||
set(fake.AGGREGATES), fake.IPSPACE,
|
||||
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
|
||||
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS,
|
||||
fake.DELETE_RETENTION_HOURS)
|
||||
self.library._get_api_client.assert_called_once_with(
|
||||
vserver=vserver_name)
|
||||
self.library._create_vserver_lifs.assert_called_once_with(
|
||||
@ -799,7 +800,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
fake.NETWORK_INFO)
|
||||
create_server_mock = self.library._client.create_vserver_dp_destination
|
||||
create_server_mock.assert_called_once_with(
|
||||
vserver_name, fake.AGGREGATES, fake.IPSPACE)
|
||||
vserver_name, fake.AGGREGATES, fake.IPSPACE,
|
||||
fake.DELETE_RETENTION_HOURS)
|
||||
self.library._create_port_and_broadcast_domain.assert_called_once_with(
|
||||
fake.IPSPACE, fake.NETWORK_INFO)
|
||||
self.library._get_flexgroup_aggr_set.assert_not_called()
|
||||
|
@ -72,6 +72,7 @@ ROOT_AGGREGATES = ('root_aggr_1', 'root_aggr_2')
|
||||
ROOT_VOLUME_AGGREGATE = 'manila1'
|
||||
SECURITY_CERT_DEFAULT_EXPIRE_DAYS = 365
|
||||
SECURITY_CERT_LARGE_EXPIRE_DAYS = 3652
|
||||
DELETE_RETENTION_HOURS = 12
|
||||
ROOT_VOLUME = 'root'
|
||||
CLUSTER_NODE = 'cluster1_01'
|
||||
CLUSTER_NODES = ('cluster1_01', 'cluster1_02')
|
||||
|
@ -4666,7 +4666,7 @@ class ShareManagerTestCase(test.TestCase):
|
||||
self.share_manager._validate_segmentation_id,
|
||||
network_info)
|
||||
|
||||
@ddt.data(10, 36, 60)
|
||||
@ddt.data(10, 36, 720)
|
||||
def test_verify_server_cleanup_interval_valid_cases(self, val):
|
||||
data = dict(DEFAULT=dict(unused_share_server_cleanup_interval=val))
|
||||
with test_utils.create_temp_config_with_opts(data):
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
The NetApp ONTAP driver now supports user configurable volume delete
|
||||
retention period (``netapp_volume_delete_retention_hours``). The max value
|
||||
of config option ``unused_share_server_cleanup_interval`` is updated to
|
||||
possible max value of retention period because if a share server gets
|
||||
deleted, the volume recovery queue also gets purged.
|
||||
For more details, please check
|
||||
`Launchpad bug #2085112 <https://bugs.launchpad.net/manila/+bug/2085112>`_
|
Loading…
x
Reference in New Issue
Block a user