[NetApp] Fix DHSS mode fails to create share on a new pool

This patch fixes #1928241 checking if the share pool name
is in vserver aggregates list, if it is not, the share server
cannot be reused and a new one is created. This fix also
includes NetApp Flexgroup and Flexvol.

Closes-Bug: #1928241
Change-Id: I24bf98f6d7c962ff9430748ff0bc88c647b9946c
This commit is contained in:
andrebeltrami 2022-03-21 08:43:09 -03:00 committed by Felipe Rodrigues
parent aaead1795c
commit 7e08ed4ce5
4 changed files with 155 additions and 16 deletions

View File

@ -904,6 +904,18 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
or vserver_info.get('subtype') != 'default'):
return False
if share:
share_pool = share_utils.extract_host(
share['host'], level='pool')
if self._is_flexgroup_pool(share_pool):
share_pool_list = self._get_flexgroup_aggregate_list(
share_pool)
else:
share_pool_list = [share_pool]
aggr_list = client.list_vserver_aggregates()
if not set(share_pool_list).issubset(set(aggr_list)):
return False
if self.is_nfs_config_supported:
# NOTE(felipe_rodrigues): Do not check that the share nfs_config
# matches with the group nfs_config, because the API guarantees

View File

@ -1765,11 +1765,13 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_client)))
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake.VSERVER_INFO))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
server = self.library.choose_share_server_compatible_with_share(
None, fake.SHARE_SERVERS, fake.SHARE, None, share_group)
None, fake.SHARE_SERVERS, fake.SHARE_2, None, share_group)
mock_get_extra_spec.assert_called_once_with(fake.SHARE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_get_nfs_config.assert_called_once_with(fake.EXTRA_SPEC)
self.assertEqual(expected_server, server)
@ -1803,13 +1805,15 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_client)))
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake.VSERVER_INFO))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
server = self.library.choose_share_server_compatible_with_share(
None, fake.SHARE_SERVERS, fake.SHARE, None, share_group)
None, fake.SHARE_SERVERS, fake.SHARE_2, None, share_group)
self.assertEqual(expected_server, server)
if nfs_config_support:
mock_get_extra_spec.assert_called_once_with(fake.SHARE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_get_nfs_config.assert_called_once_with(fake.EMPTY_EXTRA_SPEC)
@ddt.data(
@ -1843,13 +1847,15 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_client)))
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake.VSERVER_INFO))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
server = self.library.choose_share_server_compatible_with_share(
None, fake.SHARE_SERVERS, fake.SHARE)
None, fake.SHARE_SERVERS, fake.SHARE_2)
self.assertEqual(expected_server, server)
if nfs_config_support:
mock_get_extra_spec.assert_called_once_with(fake.SHARE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_get_nfs_config.assert_called_once_with(fake.EXTRA_SPEC)
@ddt.data(
@ -1886,13 +1892,15 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_client)))
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake.VSERVER_INFO))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
server = self.library.choose_share_server_compatible_with_share(
None, share_servers, fake.SHARE)
None, share_servers, fake.SHARE_2)
self.assertEqual(expected_server, server)
if nfs_config_support:
mock_get_extra_spec.assert_called_once_with(fake.SHARE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_get_nfs_config.assert_called_once_with(fake.EMPTY_EXTRA_SPEC)
def test_manage_existing_error(self):
@ -1989,6 +1997,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self, expected_server, nfs_config, share_servers,
nfs_config_supported=True):
self.library.is_nfs_config_supported = nfs_config_supported
mock_client = mock.Mock()
self.mock_object(
share_types, "get_share_type_extra_specs",
mock.Mock(return_value=fake.EXTRA_SPEC))
@ -2000,7 +2009,6 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.library,
'_check_nfs_config_extra_specs_validity',
mock.Mock())
mock_client = mock.Mock()
self.mock_object(self.library, '_get_vserver',
mock.Mock(return_value=('fake_name',
mock_client)))
@ -3418,14 +3426,16 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_get_provisioning_opts = self.mock_object(
self.library, '_get_provisioning_options',
mock.Mock(return_value={}))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
result = self.library.choose_share_server_compatible_with_share(
None, [fake.SHARE_SERVER], fake.SHARE_INSTANCE,
None, [fake.SHARE_SERVER], fake.SHARE_2,
None, share_group
)
expected_result = fake.SHARE_SERVER if compatible else None
self.assertEqual(expected_result, result)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_INSTANCE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
if (share_group and
share_group['share_server_id'] != fake.SHARE_SERVER['id']):
@ -3459,6 +3469,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_client)))
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake.VSERVER_INFO))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
mock_get_policies = self.mock_object(
mock_client, 'get_fpolicy_policies_status',
mock.Mock(return_value=policies))
@ -3467,13 +3479,13 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock.Mock(return_value=reusable_scope))
result = self.library.choose_share_server_compatible_with_share(
None, [fake.SHARE_SERVER], fake.SHARE_INSTANCE,
None, [fake.SHARE_SERVER], fake.SHARE_2,
None, None
)
expected_result = fake.SHARE_SERVER if compatible else None
self.assertEqual(expected_result, result)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_INSTANCE)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
mock_client.get_vserver_info.assert_called_once_with(
fake.VSERVER1,
)
@ -3483,7 +3495,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
mock_get_policies.assert_called_once()
if len(policies) >= self.library.FPOLICY_MAX_VSERVER_POLICIES:
mock_reusable_scope.assert_called_once_with(
fake.SHARE_INSTANCE, mock_client,
fake.SHARE_2, mock_client,
fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
@ -3518,6 +3530,71 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
fake.VSERVER1,
)
def test_choose_share_server_compatible_with_different_aggrs(self):
self.library.is_nfs_config_supported = False
mock_client = mock.Mock()
self.mock_object(self.library, '_get_vserver',
mock.Mock(return_value=(fake.VSERVER1,
mock_client)))
fake_vserver_info = {
'operational_state': 'running',
'state': 'running',
'subtype': 'default'
}
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake_vserver_info))
mock_get_extra_spec = self.mock_object(
share_types, 'get_extra_specs_from_share',
mock.Mock(return_value='fake_extra_specs'))
mock_get_provisioning_opts = self.mock_object(
self.library, '_get_provisioning_options',
mock.Mock(return_value={}))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
result = self.library.choose_share_server_compatible_with_share(
None, [fake.SHARE_SERVER], fake.SHARE_INSTANCE, None)
self.assertIsNone(result)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_INSTANCE)
mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
def test_choose_share_server_compatible_with_flexgroups(self):
self.library.is_nfs_config_supported = False
mock_client = mock.Mock()
self.mock_object(self.library, '_get_vserver',
mock.Mock(return_value=(fake.VSERVER1,
mock_client)))
fake_vserver_info = {
'operational_state': 'running',
'state': 'running',
'subtype': 'default'
}
self.mock_object(mock_client, 'get_vserver_info',
mock.Mock(return_value=fake_vserver_info))
mock_get_extra_spec = self.mock_object(
share_types, 'get_extra_specs_from_share',
mock.Mock(return_value='fake_extra_specs'))
mock_get_provisioning_opts = self.mock_object(
self.library, '_get_provisioning_options',
mock.Mock(return_value={}))
self.mock_object(mock_client, 'list_vserver_aggregates',
mock.Mock(return_value=fake.FLEXGROUP_POOL_AGGR))
self.mock_object(self.library, '_is_flexgroup_pool',
mock.Mock(return_value=True))
self.mock_object(self.library, '_get_flexgroup_aggregate_list',
mock.Mock(return_value=fake.FLEXGROUP_POOL_AGGR))
result = self.library.choose_share_server_compatible_with_share(
None, [fake.SHARE_SERVER], fake.SHARE_FLEXGROUP, None)
expected_result = fake.SHARE_SERVER
self.assertEqual(expected_result, result)
self.library._get_vserver.assert_called_once_with(
fake.SHARE_SERVER, backend_name=fake.BACKEND_NAME
)
mock_client.get_vserver_info.assert_called_once_with(
fake.VSERVER1,
)
mock_get_extra_spec.assert_called_once_with(fake.SHARE_FLEXGROUP)
mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
def test__create_port_and_broadcast_domain(self):
self.mock_object(self.library._client,
'list_cluster_nodes',

View File

@ -65,6 +65,8 @@ FREE_CAPACITY = 10000000000
TOTAL_CAPACITY = 20000000000
AGGREGATE = 'manila_aggr_1'
AGGREGATES = ('manila_aggr_1', 'manila_aggr_2')
AGGR_POOL_NAME = 'manila_aggr_1'
FLEXGROUP_POOL_NAME = 'flexgroup_pool'
ROOT_AGGREGATES = ('root_aggr_1', 'root_aggr_2')
ROOT_VOLUME_AGGREGATE = 'manila1'
ROOT_VOLUME = 'root'
@ -86,6 +88,10 @@ MANILA_HOST_NAME_2 = '%(host)s@%(backend)s#%(pool)s' % {
'host': HOST_NAME, 'backend': BACKEND_NAME, 'pool': POOL_NAME_2}
MANILA_HOST_NAME_3 = '%(host)s@%(backend)s#%(pool)s' % {
'host': HOST_NAME, 'backend': BACKEND_NAME_2, 'pool': POOL_NAME_2}
MANILA_HOST_NAME_AGGR = '%(host)s@%(backend)s#%(pool)s' % {
'host': HOST_NAME, 'backend': BACKEND_NAME, 'pool': AGGR_POOL_NAME}
MANILA_HOST_NAME_FLEXG_AGGR = '%(host)s@%(backend)s#%(pool)s' % {
'host': HOST_NAME, 'backend': BACKEND_NAME, 'pool': FLEXGROUP_POOL_NAME}
SERVER_HOST = '%(host)s@%(backend)s' % {
'host': HOST_NAME, 'backend': BACKEND_NAME}
SERVER_HOST_2 = '%(host)s@%(backend)s' % {
@ -140,6 +146,46 @@ SHARE = {
'share_id': SHARE_ID,
}
SHARE_2 = {
'id': SHARE_ID,
'host': MANILA_HOST_NAME_AGGR,
'project_id': TENANT_ID,
'name': SHARE_NAME,
'size': SHARE_SIZE,
'share_proto': 'fake',
'share_type_id': 'fake_share_type_id',
'share_network_id': '5dfe0898-e2a1-4740-9177-81c7d26713b0',
'share_server_id': '7e6a2cc8-871f-4b1d-8364-5aad0f98da86',
'network_info': {
'network_allocations': [{'ip_address': 'ip'}]
},
'replica_state': constants.REPLICA_STATE_ACTIVE,
'status': constants.STATUS_AVAILABLE,
'share_server': None,
'encrypt': False,
'share_id': SHARE_ID,
}
SHARE_FLEXGROUP = {
'id': SHARE_ID,
'host': MANILA_HOST_NAME_FLEXG_AGGR,
'project_id': TENANT_ID,
'name': SHARE_NAME,
'size': SHARE_SIZE,
'share_proto': 'fake',
'share_type_id': 'fake_share_type_id',
'share_network_id': '5dfe0898-e2a1-4740-9177-81c7d26713b0',
'share_server_id': '7e6a2cc8-871f-4b1d-8364-5aad0f98da86',
'network_info': {
'network_allocations': [{'ip_address': 'ip'}]
},
'replica_state': constants.REPLICA_STATE_ACTIVE,
'status': constants.STATUS_AVAILABLE,
'share_server': None,
'encrypt': False,
'share_id': SHARE_ID,
}
SHARE_INSTANCE = {
'id': SHARE_INSTANCE_ID,
'share_id': SHARE_ID,
@ -871,8 +917,6 @@ AGGREGATE_CAPACITIES = {
}
}
FLEXGROUP_POOL_NAME = 'flexgroup_pool'
FLEXGROUP_POOL_AGGR = [AGGREGATES[0], AGGREGATES[1]]
FLEXGROUP_POOL_OPT = {

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixes `bug #1928241 <https://bugs.launchpad.net/manila/+bug/1928241>`_.
The NetApp ONTAP driver will now avoid reusing a share server during
the share creation in case the share server does not span the selected pool.