Merge "NetApp cDOT: Apply network MTU to VLAN ports"

This commit is contained in:
Jenkins 2016-08-15 16:26:11 +00:00 committed by Gerrit Code Review
commit 51a93d1ca8
6 changed files with 103 additions and 37 deletions
manila
share/drivers/netapp/dataontap
tests/share/drivers/netapp/dataontap
releasenotes/notes

@ -473,7 +473,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
@na_utils.trace @na_utils.trace
def create_network_interface(self, ip, netmask, vlan, node, port, def create_network_interface(self, ip, netmask, vlan, node, port,
vserver_name, lif_name, ipspace_name): vserver_name, lif_name, ipspace_name, mtu):
"""Creates LIF on VLAN port.""" """Creates LIF on VLAN port."""
home_port_name = port home_port_name = port
@ -482,8 +482,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
home_port_name = '%(port)s-%(tag)s' % {'port': port, 'tag': vlan} home_port_name = '%(port)s-%(tag)s' % {'port': port, 'tag': vlan}
if self.features.BROADCAST_DOMAINS: if self.features.BROADCAST_DOMAINS:
self._ensure_broadcast_domain_for_port(node, home_port_name, self._ensure_broadcast_domain_for_port(
ipspace=ipspace_name) node, home_port_name, mtu, ipspace=ipspace_name)
LOG.debug('Creating LIF %(lif)s for Vserver %(vserver)s ', LOG.debug('Creating LIF %(lif)s for Vserver %(vserver)s ',
{'lif': lif_name, 'vserver': vserver_name}) {'lif': lif_name, 'vserver': vserver_name})
@ -554,7 +554,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
raise exception.NetAppException(msg % msg_args) raise exception.NetAppException(msg % msg_args)
@na_utils.trace @na_utils.trace
def _ensure_broadcast_domain_for_port(self, node, port, def _ensure_broadcast_domain_for_port(self, node, port, mtu,
domain=DEFAULT_BROADCAST_DOMAIN, domain=DEFAULT_BROADCAST_DOMAIN,
ipspace=DEFAULT_IPSPACE): ipspace=DEFAULT_IPSPACE):
"""Ensure a port is in a broadcast domain. Create one if necessary. """Ensure a port is in a broadcast domain. Create one if necessary.
@ -572,6 +572,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
# Port already in desired ipspace and broadcast domain. # Port already in desired ipspace and broadcast domain.
if (port_info['ipspace'] == ipspace if (port_info['ipspace'] == ipspace
and port_info['broadcast-domain'] == domain): and port_info['broadcast-domain'] == domain):
self._modify_broadcast_domain(domain, ipspace, mtu)
return return
# If in another broadcast domain, remove port from it. # If in another broadcast domain, remove port from it.
@ -582,7 +583,9 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
# If desired broadcast domain doesn't exist, create it. # If desired broadcast domain doesn't exist, create it.
if not self._broadcast_domain_exists(domain, ipspace): if not self._broadcast_domain_exists(domain, ipspace):
self._create_broadcast_domain(domain, ipspace) self._create_broadcast_domain(domain, ipspace, mtu)
else:
self._modify_broadcast_domain(domain, ipspace, mtu)
# Move the port into the broadcast domain where it is needed. # Move the port into the broadcast domain where it is needed.
self._add_port_to_broadcast_domain(node, port, domain, ipspace) self._add_port_to_broadcast_domain(node, port, domain, ipspace)
@ -640,7 +643,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
return self._has_records(result) return self._has_records(result)
@na_utils.trace @na_utils.trace
def _create_broadcast_domain(self, domain, ipspace, mtu=1500): def _create_broadcast_domain(self, domain, ipspace, mtu):
"""Create a broadcast domain.""" """Create a broadcast domain."""
api_args = { api_args = {
'ipspace': ipspace, 'ipspace': ipspace,
@ -649,6 +652,16 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
} }
self.send_request('net-port-broadcast-domain-create', api_args) self.send_request('net-port-broadcast-domain-create', api_args)
@na_utils.trace
def _modify_broadcast_domain(self, domain, ipspace, mtu):
"""Modify a broadcast domain."""
api_args = {
'ipspace': ipspace,
'broadcast-domain': domain,
'mtu': mtu,
}
self.send_request('net-port-broadcast-domain-modify', api_args)
@na_utils.trace @na_utils.trace
def _delete_broadcast_domain(self, domain, ipspace): def _delete_broadcast_domain(self, domain, ipspace):
"""Delete a broadcast domain.""" """Delete a broadcast domain."""
@ -658,6 +671,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
} }
self.send_request('net-port-broadcast-domain-destroy', api_args) self.send_request('net-port-broadcast-domain-destroy', api_args)
@na_utils.trace
def _delete_broadcast_domains_for_ipspace(self, ipspace_name): def _delete_broadcast_domains_for_ipspace(self, ipspace_name):
"""Deletes all broadcast domains in an IPspace.""" """Deletes all broadcast domains in an IPspace."""
ipspaces = self.get_ipspaces(ipspace_name=ipspace_name) ipspaces = self.get_ipspaces(ipspace_name=ipspace_name)

@ -36,6 +36,7 @@ from manila import utils
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
SUPPORTED_NETWORK_TYPES = (None, 'flat', 'vlan') SUPPORTED_NETWORK_TYPES = (None, 'flat', 'vlan')
SEGMENTED_NETWORK_TYPES = ('vlan',) SEGMENTED_NETWORK_TYPES = ('vlan',)
DEFAULT_MTU = 1500
class NetAppCmodeMultiSVMFileStorageLibrary( class NetAppCmodeMultiSVMFileStorageLibrary(
@ -274,13 +275,15 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
ip_address = network_allocation['ip_address'] ip_address = network_allocation['ip_address']
netmask = utils.cidr_to_netmask(network_allocation['cidr']) netmask = utils.cidr_to_netmask(network_allocation['cidr'])
vlan = network_allocation['segmentation_id'] vlan = network_allocation['segmentation_id']
network_mtu = network_allocation.get('mtu')
mtu = network_mtu or DEFAULT_MTU
if not vserver_client.network_interface_exists( if not vserver_client.network_interface_exists(
vserver_name, node_name, port, ip_address, netmask, vlan): vserver_name, node_name, port, ip_address, netmask, vlan):
self._client.create_network_interface( self._client.create_network_interface(
ip_address, netmask, vlan, node_name, port, vserver_name, ip_address, netmask, vlan, node_name, port, vserver_name,
lif_name, ipspace_name) lif_name, ipspace_name, mtu)
@na_utils.trace @na_utils.trace
def get_network_allocations_number(self): def get_network_allocations_number(self):

@ -869,7 +869,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.PORT, fake.PORT,
fake.VSERVER_NAME, fake.VSERVER_NAME,
fake.LIF_NAME, fake.LIF_NAME,
fake.IPSPACE_NAME) fake.IPSPACE_NAME,
fake.MTU)
if use_vlans: if use_vlans:
self.client._create_vlan.assert_called_with( self.client._create_vlan.assert_called_with(
@ -880,7 +881,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
if broadcast_domains_supported: if broadcast_domains_supported:
self.client._ensure_broadcast_domain_for_port.assert_called_with( self.client._ensure_broadcast_domain_for_port.assert_called_with(
fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT, fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT,
ipspace=fake.IPSPACE_NAME) fake.MTU, ipspace=fake.IPSPACE_NAME)
else: else:
self.assertFalse( self.assertFalse(
self.client._ensure_broadcast_domain_for_port.called) self.client._ensure_broadcast_domain_for_port.called)
@ -993,14 +994,17 @@ class NetAppClientCmodeTestCase(test.TestCase):
'_broadcast_domain_exists', '_broadcast_domain_exists',
mock.Mock(return_value=True)) mock.Mock(return_value=True))
self.mock_object(self.client, '_create_broadcast_domain') self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_modify_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain') self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port( self.client._ensure_broadcast_domain_for_port(
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN, fake.NODE_NAME, fake.PORT, fake.MTU, domain=fake.BROADCAST_DOMAIN,
ipspace=fake.IPSPACE_NAME) ipspace=fake.IPSPACE_NAME)
self.client._get_broadcast_domain_for_port.assert_has_calls([ self.client._get_broadcast_domain_for_port.assert_called_once_with(
mock.call(fake.NODE_NAME, fake.PORT)]) fake.NODE_NAME, fake.PORT)
self.client._modify_broadcast_domain.assert_called_once_with(
fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
self.assertFalse(self.client._broadcast_domain_exists.called) self.assertFalse(self.client._broadcast_domain_exists.called)
self.assertFalse(self.client._create_broadcast_domain.called) self.assertFalse(self.client._create_broadcast_domain.called)
self.assertFalse(self.client._add_port_to_broadcast_domain.called) self.assertFalse(self.client._add_port_to_broadcast_domain.called)
@ -1018,24 +1022,26 @@ class NetAppClientCmodeTestCase(test.TestCase):
'_broadcast_domain_exists', '_broadcast_domain_exists',
mock.Mock(return_value=True)) mock.Mock(return_value=True))
self.mock_object(self.client, '_create_broadcast_domain') self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_modify_broadcast_domain')
self.mock_object(self.client, '_remove_port_from_broadcast_domain') self.mock_object(self.client, '_remove_port_from_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain') self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port( self.client._ensure_broadcast_domain_for_port(
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN, fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN,
ipspace=fake.IPSPACE_NAME) ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
self.client._get_broadcast_domain_for_port.assert_has_calls([ self.client._get_broadcast_domain_for_port.assert_called_once_with(
mock.call(fake.NODE_NAME, fake.PORT)]) fake.NODE_NAME, fake.PORT)
self.client._remove_port_from_broadcast_domain.assert_has_calls([ self.client._remove_port_from_broadcast_domain.assert_called_once_with(
mock.call(fake.NODE_NAME, fake.PORT, 'other_domain', fake.NODE_NAME, fake.PORT, 'other_domain', fake.IPSPACE_NAME)
fake.IPSPACE_NAME)]) self.client._broadcast_domain_exists.assert_called_once_with(
self.client._broadcast_domain_exists.assert_has_calls([ fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)])
self.assertFalse(self.client._create_broadcast_domain.called) self.assertFalse(self.client._create_broadcast_domain.called)
self.client._add_port_to_broadcast_domain.assert_has_calls([ self.client._modify_broadcast_domain.assert_called_once_with(
mock.call(fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
fake.IPSPACE_NAME)]) self.client._add_port_to_broadcast_domain.assert_called_once_with(
fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE_NAME)
def test_ensure_broadcast_domain_for_port_no_domain(self): def test_ensure_broadcast_domain_for_port_no_domain(self):
@ -1050,23 +1056,25 @@ class NetAppClientCmodeTestCase(test.TestCase):
'_broadcast_domain_exists', '_broadcast_domain_exists',
mock.Mock(return_value=False)) mock.Mock(return_value=False))
self.mock_object(self.client, '_create_broadcast_domain') self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_modify_broadcast_domain')
self.mock_object(self.client, '_remove_port_from_broadcast_domain') self.mock_object(self.client, '_remove_port_from_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain') self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port( self.client._ensure_broadcast_domain_for_port(
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN, fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN,
ipspace=fake.IPSPACE_NAME) ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
self.client._get_broadcast_domain_for_port.assert_has_calls([ self.client._get_broadcast_domain_for_port.assert_called_once_with(
mock.call(fake.NODE_NAME, fake.PORT)]) fake.NODE_NAME, fake.PORT)
self.assertFalse(self.client._remove_port_from_broadcast_domain.called) self.assertFalse(self.client._remove_port_from_broadcast_domain.called)
self.client._broadcast_domain_exists.assert_has_calls([ self.client._broadcast_domain_exists.assert_called_once_with(
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)]) fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
self.client._create_broadcast_domain.assert_has_calls([ self.client._create_broadcast_domain.assert_called_once_with(
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)]) fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
self.client._add_port_to_broadcast_domain.assert_has_calls([ self.assertFalse(self.client._modify_broadcast_domain.called)
mock.call(fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN, self.client._add_port_to_broadcast_domain.assert_called_once_with(
fake.IPSPACE_NAME)]) fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE_NAME)
def test_get_broadcast_domain_for_port(self): def test_get_broadcast_domain_for_port(self):
@ -1177,7 +1185,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN, result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
fake.IPSPACE_NAME, fake.IPSPACE_NAME,
mtu=fake.MTU) fake.MTU)
net_port_broadcast_domain_create_args = { net_port_broadcast_domain_create_args = {
'ipspace': fake.IPSPACE_NAME, 'ipspace': fake.IPSPACE_NAME,
@ -1189,6 +1197,24 @@ class NetAppClientCmodeTestCase(test.TestCase):
mock.call('net-port-broadcast-domain-create', mock.call('net-port-broadcast-domain-create',
net_port_broadcast_domain_create_args)]) net_port_broadcast_domain_create_args)])
def test_modify_broadcast_domain(self):
self.mock_object(self.client, 'send_request')
result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN,
fake.IPSPACE_NAME,
fake.MTU)
net_port_broadcast_domain_modify_args = {
'ipspace': fake.IPSPACE_NAME,
'broadcast-domain': fake.BROADCAST_DOMAIN,
'mtu': fake.MTU,
}
self.assertIsNone(result)
self.client.send_request.assert_called_once_with(
'net-port-broadcast-domain-modify',
net_port_broadcast_domain_modify_args)
def test_delete_broadcast_domain(self): def test_delete_broadcast_domain(self):
self.mock_object(self.client, 'send_request') self.mock_object(self.client, 'send_request')

@ -540,7 +540,19 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.assertEqual('os_132dbb10-9a36-46f2-8d89-3d909830c356', result) self.assertEqual('os_132dbb10-9a36-46f2-8d89-3d909830c356', result)
def test_create_lif(self): @ddt.data(fake.MTU, None, 'not-present')
def test_create_lif(self, mtu):
"""Tests cases where MTU is a valid value, None or not present."""
expected_mtu = (mtu if mtu not in (None, 'not-present') else
fake.DEFAULT_MTU)
network_allocations = copy.deepcopy(
fake.NETWORK_INFO['network_allocations'][0])
network_allocations['mtu'] = mtu
if mtu == 'not-present':
network_allocations.pop('mtu')
vserver_client = mock.Mock() vserver_client = mock.Mock()
vserver_client.network_interface_exists = mock.Mock( vserver_client.network_interface_exists = mock.Mock(
@ -554,12 +566,12 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
'fake_ipspace', 'fake_ipspace',
'fake_node', 'fake_node',
'fake_lif', 'fake_lif',
fake.NETWORK_INFO['network_allocations'][0]) network_allocations)
self.library._client.create_network_interface.assert_has_calls([ self.library._client.create_network_interface.assert_has_calls([
mock.call('10.10.10.10', '255.255.255.0', '1000', 'fake_node', mock.call('10.10.10.10', '255.255.255.0', '1000', 'fake_node',
'fake_port', 'fake_vserver', 'fake_lif', 'fake_port', 'fake_vserver', 'fake_lif',
'fake_ipspace')]) 'fake_ipspace', expected_mtu)])
def test_create_lif_if_nonexistent_already_present(self): def test_create_lif_if_nonexistent_already_present(self):

@ -65,6 +65,8 @@ SHARE_TYPE_ID = '26e89a5b-960b-46bb-a8cf-0778e653098f'
SHARE_TYPE_NAME = 'fake_share_type' SHARE_TYPE_NAME = 'fake_share_type'
IPSPACE = 'fake_ipspace' IPSPACE = 'fake_ipspace'
IPSPACE_ID = '27d38c27-3e8b-4d7d-9d91-fcf295e3ac8f' IPSPACE_ID = '27d38c27-3e8b-4d7d-9d91-fcf295e3ac8f'
MTU = 1234
DEFAULT_MTU = 1500
CLIENT_KWARGS = { CLIENT_KWARGS = {
'username': 'admin', 'username': 'admin',
@ -223,6 +225,7 @@ USER_NETWORK_ALLOCATIONS = [
'segmentation_id': '1000', 'segmentation_id': '1000',
'network_type': 'vlan', 'network_type': 'vlan',
'label': 'user', 'label': 'user',
'mtu': MTU,
}, },
{ {
'id': '7eabdeed-bad2-46ea-bd0f-a33884c869e0', 'id': '7eabdeed-bad2-46ea-bd0f-a33884c869e0',
@ -231,6 +234,7 @@ USER_NETWORK_ALLOCATIONS = [
'segmentation_id': '1000', 'segmentation_id': '1000',
'network_type': 'vlan', 'network_type': 'vlan',
'label': 'user', 'label': 'user',
'mtu': MTU,
} }
] ]
@ -242,6 +246,7 @@ ADMIN_NETWORK_ALLOCATIONS = [
'segmentation_id': None, 'segmentation_id': None,
'network_type': 'flat', 'network_type': 'flat',
'label': 'admin', 'label': 'admin',
'mtu': MTU,
}, },
] ]

@ -0,0 +1,6 @@
---
features:
- The NetApp cDOT driver operating in
``driver_handles_share_servers = True`` mode applies the Maximum
Transmission Unit (MTU) from the network provider where available when
creating Logical Interfaces (LIFs) for newly created share servers.