Merge "NetApp cDOT driver should not report untenable pools"

This commit is contained in:
Jenkins 2016-10-13 17:17:05 +00:00 committed by Gerrit Code Review
commit 34a1879e6b
9 changed files with 234 additions and 38 deletions

View File

@ -444,7 +444,51 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
return sorted(ports, key=sort_key, reverse=True)
@na_utils.trace
def list_aggregates(self):
def list_root_aggregates(self):
"""Get names of all aggregates that contain node root volumes."""
desired_attributes = {
'aggr-attributes': {
'aggregate-name': None,
'aggr-raid-attributes': {
'has-local-root': None,
'has-partner-root': None,
},
},
}
aggrs = self._get_aggregates(desired_attributes=desired_attributes)
root_aggregates = []
for aggr in aggrs:
aggr_name = aggr.get_child_content('aggregate-name')
aggr_raid_attrs = aggr.get_child_by_name('aggr-raid-attributes')
local_root = strutils.bool_from_string(
aggr_raid_attrs.get_child_content('has-local-root'))
partner_root = strutils.bool_from_string(
aggr_raid_attrs.get_child_content('has-partner-root'))
if local_root or partner_root:
root_aggregates.append(aggr_name)
return root_aggregates
@na_utils.trace
def list_non_root_aggregates(self):
"""Get names of all aggregates that don't contain node root volumes."""
query = {
'aggr-attributes': {
'aggr-raid-attributes': {
'has-local-root': 'false',
'has-partner-root': 'false',
}
},
}
return self._list_aggregates(query=query)
@na_utils.trace
def _list_aggregates(self, query=None):
"""Get names of all aggregates."""
try:
api_args = {
@ -454,6 +498,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
},
},
}
if query:
api_args['query'] = query
result = self.send_iter_request('aggr-get-iter', api_args)
aggr_list = result.get_child_by_name(
'attributes-list').get_children()

View File

@ -100,7 +100,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
@na_utils.trace
def _find_matching_aggregates(self):
"""Find all aggregates match pattern."""
aggregate_names = self._client.list_aggregates()
aggregate_names = self._client.list_non_root_aggregates()
pattern = self.configuration.netapp_aggregate_name_search_pattern
return [aggr_name for aggr_name in aggregate_names
if re.match(pattern, aggr_name)]

View File

@ -115,9 +115,15 @@ class NetAppCmodeSingleSVMFileStorageLibrary(
"""Find all aggregates match pattern."""
vserver_client = self._get_api_client(vserver=self._vserver)
aggregate_names = vserver_client.list_vserver_aggregates()
root_aggregate_names = []
if self._have_cluster_creds:
root_aggregate_names = self._client.list_root_aggregates()
pattern = self.configuration.netapp_aggregate_name_search_pattern
return [aggr_name for aggr_name in aggregate_names
if re.match(pattern, aggr_name)]
if re.match(pattern, aggr_name) and
aggr_name not in root_aggregate_names]
@na_utils.trace
def get_network_allocations_number(self):

View File

@ -38,6 +38,7 @@ VSERVER_NAME_2 = 'fake_vserver_2'
ADMIN_VSERVER_NAME = 'fake_admin_vserver'
NODE_VSERVER_NAME = 'fake_node_vserver'
NFS_VERSIONS = ['nfs3', 'nfs4.0']
ROOT_AGGREGATE_NAMES = ('root_aggr1', 'root_aggr2')
ROOT_VOLUME_AGGREGATE_NAME = 'fake_root_aggr'
ROOT_VOLUME_NAME = 'fake_root_volume'
SHARE_AGGREGATE_NAME = 'fake_aggr1'
@ -791,34 +792,21 @@ AGGR_GET_NAMES_RESPONSE = etree.XML("""
<attributes-list>
<aggr-attributes>
<aggr-raid-attributes>
<plexes>
<plex-attributes>
<plex-name>/%(aggr1)s/plex0</plex-name>
<raidgroups>
<raidgroup-attributes>
<raidgroup-name>/%(aggr1)s/plex0/rg0</raidgroup-name>
</raidgroup-attributes>
</raidgroups>
</plex-attributes>
</plexes>
</aggr-raid-attributes>
<aggregate-name>%(root1)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
</aggr-raid-attributes>
<aggregate-name>%(root2)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
</aggr-raid-attributes>
<aggregate-name>%(aggr1)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
<plexes>
<plex-attributes>
<plex-name>/%(aggr2)s/plex0</plex-name>
<raidgroups>
<raidgroup-attributes>
<raidgroup-name>/%(aggr2)s/plex0/rg0</raidgroup-name>
</raidgroup-attributes>
<raidgroup-attributes>
<raidgroup-name>/%(aggr2)s/plex0/rg1</raidgroup-name>
</raidgroup-attributes>
</raidgroups>
</plex-attributes>
</plexes>
</aggr-raid-attributes>
<aggregate-name>%(aggr2)s</aggregate-name>
</aggr-attributes>
@ -826,6 +814,8 @@ AGGR_GET_NAMES_RESPONSE = etree.XML("""
<num-records>2</num-records>
</results>
""" % {
'root1': ROOT_AGGREGATE_NAMES[0],
'root2': ROOT_AGGREGATE_NAMES[1],
'aggr1': SHARE_AGGREGATE_NAMES[0],
'aggr2': SHARE_AGGREGATE_NAMES[1],
})
@ -1268,6 +1258,72 @@ AGGR_GET_ITER_SSC_RESPONSE = etree.XML("""
</results>
""" % {'aggr1': SHARE_AGGREGATE_NAMES[0]})
AGGR_GET_ITER_ROOT_AGGR_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>true</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(root1)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>true</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(root2)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>false</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(aggr1)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>false</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(aggr2)s</aggregate-name>
</aggr-attributes>
</attributes-list>
<num-records>6</num-records>
</results>
""" % {
'root1': ROOT_AGGREGATE_NAMES[0],
'root2': ROOT_AGGREGATE_NAMES[1],
'aggr1': SHARE_AGGREGATE_NAMES[0],
'aggr2': SHARE_AGGREGATE_NAMES[1],
})
AGGR_GET_ITER_NON_ROOT_AGGR_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>false</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(aggr1)s</aggregate-name>
</aggr-attributes>
<aggr-attributes>
<aggr-raid-attributes>
<has-local-root>false</has-local-root>
<has-partner-root>false</has-partner-root>
</aggr-raid-attributes>
<aggregate-name>%(aggr2)s</aggregate-name>
</aggr-attributes>
</attributes-list>
<num-records>6</num-records>
</results>
""" % {
'aggr1': SHARE_AGGREGATE_NAMES[0],
'aggr2': SHARE_AGGREGATE_NAMES[1],
})
VOLUME_GET_NAME_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>

View File

@ -796,16 +796,80 @@ class NetAppClientCmodeTestCase(test.TestCase):
self.assertSequenceEqual(fake.SORTED_PORTS_ALL_SPEEDS, result)
def test_list_root_aggregates(self):
api_response = netapp_api.NaElement(
fake.AGGR_GET_ITER_ROOT_AGGR_RESPONSE)
self.mock_object(self.client,
'send_iter_request',
mock.Mock(return_value=api_response))
result = self.client.list_root_aggregates()
aggr_get_iter_args = {
'desired-attributes': {
'aggr-attributes': {
'aggregate-name': None,
'aggr-raid-attributes': {
'has-local-root': None,
'has-partner-root': None,
},
},
}
}
self.assertSequenceEqual(fake.ROOT_AGGREGATE_NAMES, result)
self.client.send_iter_request.assert_has_calls([
mock.call('aggr-get-iter', aggr_get_iter_args)])
def test_list_non_root_aggregates(self):
api_response = netapp_api.NaElement(
fake.AGGR_GET_ITER_NON_ROOT_AGGR_RESPONSE)
self.mock_object(self.client,
'send_iter_request',
mock.Mock(return_value=api_response))
result = self.client.list_non_root_aggregates()
aggr_get_iter_args = {
'query': {
'aggr-attributes': {
'aggr-raid-attributes': {
'has-local-root': 'false',
'has-partner-root': 'false',
}
},
},
'desired-attributes': {
'aggr-attributes': {
'aggregate-name': None,
},
},
}
self.assertSequenceEqual(fake.SHARE_AGGREGATE_NAMES, result)
self.client.send_iter_request.assert_has_calls([
mock.call('aggr-get-iter', aggr_get_iter_args)])
def test_list_aggregates(self):
api_response = netapp_api.NaElement(fake.AGGR_GET_NAMES_RESPONSE)
self.mock_object(self.client,
'send_request',
'send_iter_request',
mock.Mock(return_value=api_response))
result = self.client.list_aggregates()
result = self.client._list_aggregates()
self.assertSequenceEqual(fake.SHARE_AGGREGATE_NAMES, result)
aggr_get_iter_args = {
'desired-attributes': {
'aggr-attributes': {
'aggregate-name': None,
},
},
}
self.assertSequenceEqual(
fake.ROOT_AGGREGATE_NAMES + fake.SHARE_AGGREGATE_NAMES, result)
self.client.send_iter_request.assert_has_calls([
mock.call('aggr-get-iter', aggr_get_iter_args)])
def test_list_aggregates_not_found(self):
@ -815,7 +879,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
mock.Mock(return_value=api_response))
self.assertRaises(exception.NetAppException,
self.client.list_aggregates)
self.client._list_aggregates)
def test_list_vserver_aggregates(self):

View File

@ -186,14 +186,16 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
def test_find_matching_aggregates(self):
self.mock_object(self.client,
'list_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
mock_list_non_root_aggregates = self.mock_object(
self.client, 'list_non_root_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
self.library.configuration.netapp_aggregate_name_search_pattern = (
'.*_aggr_1')
result = self.library._find_matching_aggregates()
self.assertListEqual([fake.AGGREGATES[0]], result)
mock_list_non_root_aggregates.assert_called_once_with()
def test_setup_server(self):

View File

@ -15,6 +15,7 @@
Unit tests for the NetApp Data ONTAP cDOT single-SVM storage driver library.
"""
import ddt
import mock
from oslo_log import log
@ -26,6 +27,7 @@ from manila import test
import manila.tests.share.drivers.netapp.dataontap.fakes as fake
@ddt.ddt
class NetAppFileStorageLibraryTestCase(test.TestCase):
def setUp(self):
@ -164,19 +166,32 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.assertTrue(mock_vserver_client.prune_deleted_snapshots.called)
self.assertTrue(mock_super.called)
def test_find_matching_aggregates(self):
@ddt.data(True, False)
def test_find_matching_aggregates(self, have_cluster_creds):
self.library._have_cluster_creds = have_cluster_creds
aggregates = fake.AGGREGATES + fake.ROOT_AGGREGATES
mock_vserver_client = mock.Mock()
mock_vserver_client.list_vserver_aggregates.return_value = (
fake.AGGREGATES)
mock_vserver_client.list_vserver_aggregates.return_value = aggregates
self.mock_object(self.library,
'_get_api_client',
mock.Mock(return_value=mock_vserver_client))
mock_client = mock.Mock()
mock_client.list_root_aggregates.return_value = fake.ROOT_AGGREGATES
self.library._client = mock_client
self.library.configuration.netapp_aggregate_name_search_pattern = (
'.*_aggr_1')
result = self.library._find_matching_aggregates()
self.assertListEqual([fake.AGGREGATES[0]], result)
if have_cluster_creds:
self.assertListEqual([fake.AGGREGATES[0]], result)
mock_client.list_root_aggregates.assert_called_once_with()
else:
self.assertListEqual([fake.AGGREGATES[0], fake.ROOT_AGGREGATES[0]],
result)
self.assertFalse(mock_client.list_root_aggregates.called)
def test_get_network_allocations_number(self):
self.assertEqual(0, self.library.get_network_allocations_number())

View File

@ -54,6 +54,7 @@ FREE_CAPACITY = 10000000000
TOTAL_CAPACITY = 20000000000
AGGREGATE = 'manila_aggr_1'
AGGREGATES = ('manila_aggr_1', 'manila_aggr_2')
ROOT_AGGREGATES = ('root_aggr_1', 'root_aggr_2')
ROOT_VOLUME_AGGREGATE = 'manila1'
ROOT_VOLUME = 'root'
CLUSTER_NODE = 'cluster1_01'

View File

@ -0,0 +1,6 @@
---
fixes:
- The NetApp cDOT driver now explicitly filters root aggregates
from the pools reported to the manila scheduler if the driver
is operating with cluster credentials.