Merge "Add SCTP support"

This commit is contained in:
Zuul 2021-03-12 16:17:18 +00:00 committed by Gerrit Code Review
commit 1ccbf2988c
7 changed files with 161 additions and 78 deletions

View File

@ -72,9 +72,10 @@ REQ_INFO_MEMBER_DELETED = 'member_deleted'
# Disabled resources have a ':D' at the end
DISABLED_RESOURCE_SUFFIX = 'D'
# This driver only supports TCP and UDP, with a single LB algorithm
# This driver only supports TCP, UDP and SCTP, with a single LB algorithm
OVN_NATIVE_LB_PROTOCOLS = [constants.PROTOCOL_TCP,
constants.PROTOCOL_UDP, ]
constants.PROTOCOL_UDP,
constants.PROTOCOL_SCTP, ]
OVN_NATIVE_LB_ALGORITHMS = [constants.LB_ALGORITHM_SOURCE_IP_PORT, ]
# Prepended to exception log messages

View File

@ -454,7 +454,7 @@ class TestOvnOctaviaBase(base.TestOVNFunctionalBase,
'neutron:vip_port_id': vip_net_info[3],
'enabled': str(lb_data['model'].admin_state_up)}
# NOTE(mjozefcz): By default we don't set protocol. We don't know if
# listener/pool would be TCP or UDP, so do not set it.
# listener/pool would be TCP, UDP or SCTP, so do not set it.
expected_protocols = set()
# Lets fetch list of L4 protocols defined for this LB.

View File

@ -56,23 +56,22 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
lb_data = self._create_load_balancer_and_validate(
{'vip_network': 'vip_network',
'cidr': '10.0.0.0/24'})
self._create_pool_and_validate(lb_data, "p1",
protocol='TCP')
self._update_pool_and_validate(lb_data, "p1")
self._create_pool_and_validate(lb_data, "p2",
protocol='UDP')
self._create_pool_and_validate(lb_data, "p3",
protocol='TCP')
self._update_pool_and_validate(lb_data, "p3",
self._create_pool_and_validate(lb_data, "p_TCP_1", protocol='TCP')
self._update_pool_and_validate(lb_data, "p_TCP_1")
self._create_pool_and_validate(lb_data, "p_UDP_1", protocol='UDP')
self._create_pool_and_validate(lb_data, "p_SCTP_1", protocol='SCTP')
self._create_pool_and_validate(lb_data, "p_TCP_2", protocol='TCP')
self._update_pool_and_validate(lb_data, "p_TCP_2",
admin_state_up=False)
self._update_pool_and_validate(lb_data, "p3",
self._update_pool_and_validate(lb_data, "p_TCP_2",
admin_state_up=True)
self._update_pool_and_validate(lb_data, "p3",
self._update_pool_and_validate(lb_data, "p_TCP_2",
admin_state_up=False)
self._create_pool_and_validate(lb_data, "p4",
protocol='UDP')
self._delete_pool_and_validate(lb_data, "p2")
self._delete_pool_and_validate(lb_data, "p1")
self._create_pool_and_validate(lb_data, "p_UDP_2", protocol='UDP')
self._create_pool_and_validate(lb_data, "p_SCTP_2", protocol='SCTP')
self._delete_pool_and_validate(lb_data, "p_SCTP_1")
self._delete_pool_and_validate(lb_data, "p_UDP_1")
self._delete_pool_and_validate(lb_data, "p_TCP_1")
self._delete_load_balancer_and_validate(lb_data)
def test_member(self):
@ -81,32 +80,43 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
'cidr': '10.0.0.0/24'})
# TCP Pool
self._create_pool_and_validate(lb_data, "p1",
protocol='TCP')
self._create_pool_and_validate(lb_data, "p_TCP", protocol='TCP')
# UDP Pool
self._create_pool_and_validate(lb_data, "p2",
protocol='UDP')
self._create_pool_and_validate(lb_data, "p_UDP", protocol='UDP')
pool_1_id = lb_data['pools'][0].pool_id
pool_2_id = lb_data['pools'][1].pool_id
# SCTP Pool
self._create_pool_and_validate(lb_data, "p_SCTP", protocol='SCTP')
pool_TCP_id = lb_data['pools'][0].pool_id
pool_UDP_id = lb_data['pools'][1].pool_id
pool_SCTP_id = lb_data['pools'][2].pool_id
# Members for TCP Pool
self._create_member_and_validate(
lb_data, pool_1_id, lb_data['vip_net_info'][1],
lb_data, pool_TCP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
self._update_member_and_validate(lb_data, pool_1_id, "10.0.0.10")
self._update_member_and_validate(lb_data, pool_TCP_id, "10.0.0.10")
self._create_member_and_validate(
lb_data, pool_1_id, lb_data['vip_net_info'][1],
lb_data, pool_TCP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.11')
# Members for UDP Pool
self._create_member_and_validate(
lb_data, pool_2_id, lb_data['vip_net_info'][1],
lb_data, pool_UDP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
self._update_member_and_validate(lb_data, pool_1_id, "10.0.0.10")
self._update_member_and_validate(lb_data, pool_UDP_id, "10.0.0.10")
self._create_member_and_validate(
lb_data, pool_2_id, lb_data['vip_net_info'][1],
lb_data, pool_UDP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.11')
# Members for SCTP Pool
self._create_member_and_validate(
lb_data, pool_SCTP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
self._update_member_and_validate(lb_data, pool_SCTP_id, "10.0.0.10")
self._create_member_and_validate(
lb_data, pool_SCTP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.11')
# Disable loadbalancer
@ -117,41 +127,42 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
admin_state_up=True)
# Delete members from TCP Pool
self._delete_member_and_validate(lb_data, pool_1_id,
self._delete_member_and_validate(lb_data, pool_TCP_id,
lb_data['vip_net_info'][0],
'10.0.0.10')
self._delete_member_and_validate(lb_data, pool_1_id,
self._delete_member_and_validate(lb_data, pool_TCP_id,
lb_data['vip_net_info'][0],
'10.0.0.11')
# Add again member to TCP Pool
self._create_member_and_validate(
lb_data, pool_1_id, lb_data['vip_net_info'][1],
lb_data, pool_TCP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
# Create new networks and add member to TCP pool from it.
net20_info = self._create_net('net20', '20.0.0.0/24')
net20 = net20_info[0]
subnet20 = net20_info[1]
self._create_member_and_validate(lb_data, pool_1_id, subnet20, net20,
self._create_member_and_validate(lb_data, pool_TCP_id, subnet20, net20,
'20.0.0.4')
self._create_member_and_validate(lb_data, pool_1_id, subnet20, net20,
self._create_member_and_validate(lb_data, pool_TCP_id, subnet20, net20,
'20.0.0.6')
net30_info = self._create_net('net30', '30.0.0.0/24')
net30 = net30_info[0]
subnet30 = net30_info[1]
self._create_member_and_validate(lb_data, pool_1_id, subnet30, net30,
self._create_member_and_validate(lb_data, pool_TCP_id, subnet30, net30,
'30.0.0.6')
self._delete_member_and_validate(lb_data, pool_1_id, net20, '20.0.0.6')
self._delete_member_and_validate(lb_data, pool_TCP_id, net20,
'20.0.0.6')
# Test creating Member without subnet
m_member = self._create_member_model(pool_1_id,
m_member = self._create_member_model(pool_TCP_id,
None,
'30.0.0.7', 80)
self.assertRaises(o_exceptions.UnsupportedOptionError,
self.ovn_driver.member_create, m_member)
# Deleting the pool should also delete the members.
self._delete_pool_and_validate(lb_data, "p1")
self._delete_pool_and_validate(lb_data, "p_TCP")
# Delete the whole LB.
self._delete_load_balancer_and_validate(lb_data)
@ -160,31 +171,38 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
lb_data = self._create_load_balancer_and_validate(
{'vip_network': 'vip_network',
'cidr': '10.0.0.0/24'})
self._create_pool_and_validate(lb_data, "p1",
protocol='TCP')
self._create_pool_and_validate(lb_data, "p2",
protocol='UDP')
pool_1_id = lb_data['pools'][0].pool_id
pool_2_id = lb_data['pools'][1].pool_id
self._create_pool_and_validate(lb_data, "p_TCP", protocol='TCP')
self._create_pool_and_validate(lb_data, "p_UDP", protocol='UDP')
self._create_pool_and_validate(lb_data, "p_SCTP", protocol='SCTP')
pool_TCP_id = lb_data['pools'][0].pool_id
pool_UDP_id = lb_data['pools'][1].pool_id
pool_SCTP_id = lb_data['pools'][2].pool_id
net_info = self._create_net('net1', '20.0.0.0/24')
# Create member in first pool
# Create member in TCP pool
self._create_member_and_validate(
lb_data, pool_1_id, lb_data['vip_net_info'][1],
lb_data, pool_TCP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.4')
self._create_member_and_validate(lb_data, pool_1_id,
self._create_member_and_validate(lb_data, pool_TCP_id,
net_info[1], net_info[0], '20.0.0.4')
# Create member in second pool
# Create member in UDP pool
self._create_member_and_validate(
lb_data, pool_2_id, lb_data['vip_net_info'][1],
lb_data, pool_UDP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.4')
self._create_member_and_validate(lb_data, pool_2_id,
self._create_member_and_validate(lb_data, pool_UDP_id,
net_info[1], net_info[0], '20.0.0.4')
# Play around first listener linked to first pool.
# Create member in SCTP pool
self._create_member_and_validate(
lb_data, pool_SCTP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.4')
self._create_member_and_validate(lb_data, pool_SCTP_id,
net_info[1], net_info[0], '20.0.0.4')
# Play around first listener linked to TCP pool
self._create_listener_and_validate(
lb_data, pool_1_id, 80, protocol='TCP')
lb_data, pool_TCP_id, 80, protocol='TCP')
self._update_listener_and_validate(lb_data, protocol_port=80)
self._update_listener_and_validate(
lb_data, protocol_port=80, admin_state_up=True)
@ -193,11 +211,11 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
self._update_listener_and_validate(
lb_data, protocol_port=80, admin_state_up=True)
self._create_listener_and_validate(
lb_data, pool_1_id, protocol_port=82, protocol='TCP')
lb_data, pool_TCP_id, protocol_port=82, protocol='TCP')
# Play around second listener linked to second pool.
# Play around second listener linked to UDP pool
self._create_listener_and_validate(
lb_data, pool_2_id, 53, protocol='UDP')
lb_data, pool_UDP_id, 53, protocol='UDP')
self._update_listener_and_validate(lb_data, 53, protocol='UDP')
self._update_listener_and_validate(
lb_data, protocol_port=53, protocol='UDP', admin_state_up=True)
@ -206,21 +224,34 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
self._update_listener_and_validate(
lb_data, protocol_port=53, protocol='UDP', admin_state_up=True)
self._create_listener_and_validate(
lb_data, pool_2_id, protocol_port=21, protocol='UDP')
lb_data, pool_UDP_id, protocol_port=21, protocol='UDP')
# Delete listeners linked to first pool.
# Play around third listener linked to SCTP pool
self._create_listener_and_validate(
lb_data, pool_SCTP_id, 8081, protocol='SCTP')
self._update_listener_and_validate(lb_data, 8081, protocol='SCTP')
self._update_listener_and_validate(
lb_data, protocol_port=8081, protocol='SCTP', admin_state_up=True)
self._update_listener_and_validate(
lb_data, protocol_port=8081, protocol='SCTP', admin_state_up=False)
self._update_listener_and_validate(
lb_data, protocol_port=8081, protocol='SCTP', admin_state_up=True)
self._create_listener_and_validate(
lb_data, pool_SCTP_id, protocol_port=8082, protocol='SCTP')
# Delete listeners linked to TCP pool
self._delete_listener_and_validate(
lb_data, protocol_port=82, protocol='TCP')
self._delete_listener_and_validate(
lb_data, protocol_port=80, protocol='TCP')
# Delete first pool members.
self._delete_member_and_validate(lb_data, pool_1_id,
# Delete TCP pool members
self._delete_member_and_validate(lb_data, pool_TCP_id,
net_info[0], '20.0.0.4')
self._delete_member_and_validate(lb_data, pool_1_id,
self._delete_member_and_validate(lb_data, pool_TCP_id,
lb_data['vip_net_info'][0],
'10.0.0.4')
# Delete empty, first pool
self._delete_pool_and_validate(lb_data, "p1")
# Delete empty, TCP pool
self._delete_pool_and_validate(lb_data, "p_TCP")
# Delete the rest
self._delete_load_balancer_and_validate(lb_data)
@ -229,22 +260,29 @@ class TestOvnOctaviaProviderDriver(ovn_base.TestOvnOctaviaBase):
{'vip_network': 'vip_network',
'cidr': '10.0.0.0/24'})
if pool:
self._create_pool_and_validate(lb_data, "p1", protocol='TCP')
self._create_pool_and_validate(lb_data, "p2", protocol='UDP')
pool_1_id = lb_data['pools'][0].pool_id
pool_2_id = lb_data['pools'][1].pool_id
self._create_pool_and_validate(lb_data, "p_TCP", protocol='TCP')
self._create_pool_and_validate(lb_data, "p_UDP", protocol='UDP')
self._create_pool_and_validate(lb_data, "p_SCTP", protocol='SCTP')
pool_TCP_id = lb_data['pools'][0].pool_id
pool_UDP_id = lb_data['pools'][1].pool_id
pool_SCTP_id = lb_data['pools'][2].pool_id
if member:
self._create_member_and_validate(
lb_data, pool_1_id, lb_data['vip_net_info'][1],
lb_data, pool_TCP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
self._create_member_and_validate(
lb_data, pool_2_id, lb_data['vip_net_info'][1],
lb_data, pool_UDP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
self._create_member_and_validate(
lb_data, pool_SCTP_id, lb_data['vip_net_info'][1],
lb_data['vip_net_info'][0], '10.0.0.10')
if listener:
self._create_listener_and_validate(
lb_data, pool_1_id, protocol_port=80, protocol='TCP')
lb_data, pool_TCP_id, protocol_port=80, protocol='TCP')
self._create_listener_and_validate(
lb_data, pool_2_id, protocol_port=53, protocol='UDP')
lb_data, pool_UDP_id, protocol_port=53, protocol='UDP')
self._create_listener_and_validate(
lb_data, pool_SCTP_id, protocol_port=8081, protocol='SCTP')
self._delete_load_balancer_and_validate(lb_data, cascade=True)

View File

@ -143,6 +143,16 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
name='listener',
protocol='UDP',
protocol_port=42)
self.ref_listener_sctp = data_models.Listener(
admin_state_up=False,
connection_limit=5,
default_pool=self.ref_pool,
default_pool_id=self.pool_id,
listener_id=self.listener_id,
loadbalancer_id=self.loadbalancer_id,
name='listener',
protocol='SCTP',
protocol_port=42)
self.fail_listener = data_models.Listener(
admin_state_up=False,
connection_limit=5,
@ -389,7 +399,7 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
self.driver.listener_create, self.fail_listener)
def test_listener_create_multiple_protocols(self):
self.ovn_lb.protocol = ['tcp']
self.ovn_lb.protocol = ['TCP']
info = {'id': self.ref_listener.listener_id,
'protocol': self.ref_listener.protocol,
'protocol_port': self.ref_listener.protocol_port,
@ -405,6 +415,11 @@ class TestOvnProviderDriver(ovn_base.TestOvnOctaviaBase):
expected_dict = {'type': ovn_const.REQ_TYPE_LISTENER_CREATE,
'info': info}
self.driver.listener_create(self.ref_listener)
self.ovn_lb.protocol = ['SCTP']
info['protocol'] = 'SCTP'
expected_dict = {'type': ovn_const.REQ_TYPE_LISTENER_CREATE,
'info': info}
self.driver.listener_create(self.ref_listener)
def test_listener_update(self):
info = {'id': self.ref_listener.listener_id,

View File

@ -237,13 +237,24 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
self.ovn_lb.id,
protocol='UDP')
# LB with given protocol not found
self.helper.ovn_nbdb_api.db_find_rows.return_value.\
execute.return_value = []
self.assertRaises(
idlutils.RowNotFound,
f,
self.ovn_lb.id,
protocol='SCTP')
# Multiple protocols
udp_lb = copy.copy(self.ovn_lb)
udp_lb.protocol = ['udp']
sctp_lb = copy.copy(self.ovn_lb)
sctp_lb.protocol = ['sctp']
self.helper.ovn_nbdb_api.db_find_rows.return_value.\
execute.return_value = [self.ovn_lb, udp_lb]
execute.return_value = [self.ovn_lb, udp_lb, sctp_lb]
found = f(self.ovn_lb.id)
self.assertListEqual(found, [self.ovn_lb, udp_lb])
self.assertListEqual(found, [self.ovn_lb, udp_lb, sctp_lb])
def test__get_or_create_ovn_lb_no_lb_found(self):
self.mock_find_ovn_lbs.stop()
@ -388,18 +399,18 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
selection_fields=['ip_src', 'ip_dst', 'tp_src', 'tp_dst'])
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
def test_lb_create_on_multi_protocol(self, net_cli):
def _test_lb_create_on_multi_protocol(self, protocol, net_cli):
"""This test situation when new protocol is added
to the same loadbalancer and we need to add
additional OVN lb with the same name.
"""
self.lb['admin_state_up'] = True
self.lb['protocol'] = 'UDP'
self.lb['protocol'] = protocol
self.lb[ovn_const.LB_EXT_IDS_LR_REF_KEY] = 'foo'
self.lb[ovn_const.LB_EXT_IDS_LS_REFS_KEY] = '{\"neutron-foo\": 1}'
net_cli.return_value.list_ports.return_value = self.ports
status = self.helper.lb_create(self.lb, protocol='UDP')
status = self.helper.lb_create(self.lb, protocol=protocol)
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
constants.ACTIVE)
self.assertEqual(status['loadbalancers'][0]['operating_status'],
@ -411,13 +422,19 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
ovn_const.LB_EXT_IDS_LR_REF_KEY: 'foo',
'enabled': 'True'},
name=mock.ANY,
protocol='udp',
protocol=protocol.lower(),
selection_fields=['ip_src', 'ip_dst', 'tp_src', 'tp_dst'])
self.helper._update_lb_to_ls_association.assert_has_calls([
mock.call(self.ovn_lb, associate=True,
network_id=self.lb['vip_network_id']),
mock.call(self.ovn_lb, associate=True, network_id='foo')])
def test_lb_create_on_multi_protocol_UDP(self):
self._test_lb_create_on_multi_protocol('UDP')
def test_lb_create_on_multi_protocol_SCTP(self):
self._test_lb_create_on_multi_protocol('SCTP')
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
@mock.patch.object(ovn_helper.OvnProviderHelper, 'delete_vip_port')
def test_lb_create_exception(self, del_port, net_cli):
@ -2358,6 +2375,11 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
ret = self.helper.check_lb_protocol(self.listener_id, 'UDP')
self.assertFalse(ret)
ret = self.helper.check_lb_protocol(self.listener_id, 'sctp')
self.assertFalse(ret)
ret = self.helper.check_lb_protocol(self.listener_id, 'SCTP')
self.assertFalse(ret)
ret = self.helper.check_lb_protocol(self.listener_id, 'tcp')
self.assertTrue(ret)
ret = self.helper.check_lb_protocol(self.listener_id, 'TCP')

View File

@ -0,0 +1,4 @@
---
features:
- |
Add support for the SCTP protocol in the OVN provider driver.

View File

@ -75,6 +75,7 @@
USE_PYTHON3: True
TEMPEST_PLUGINS: '/opt/stack/octavia-tempest-plugin'
OCTAVIA_NODE: api
OCTAVIA_TEMPEST_PLUGIN_CUSTOMIZE_IMAGE: true
DISABLE_AMP_IMAGE_BUILD: true
OVN_L3_CREATE_PUBLIC_NETWORK: true
Q_USE_PROVIDERNET_FOR_PUBLIC: true
@ -93,6 +94,7 @@
provider: 'ovn'
enable_security_groups: True
enabled_provider_drivers: 'ovn:OVN provider driver'
test_sctp_protocol: True
loadbalancer-feature-enabled:
health_monitor_enabled: False
pool_algorithms_enabled: False
@ -144,7 +146,8 @@
tempest_exclude_regex: "\
(^octavia_tempest_plugin.tests.scenario.v2.test_traffic_ops.TrafficOperationsScenarioTest.test_basic_http_traffic)|\
(^octavia_tempest_plugin.tests.scenario.v2.test_traffic_ops.TrafficOperationsScenarioTest.test_basic_tcp_traffic)|\
(^octavia_tempest_plugin.tests.scenario.v2.test_traffic_ops.TrafficOperationsScenarioTest.test_basic_udp_traffic)"
(^octavia_tempest_plugin.tests.scenario.v2.test_traffic_ops.TrafficOperationsScenarioTest.test_basic_udp_traffic)|\
(^octavia_tempest_plugin.tests.scenario.v2.test_traffic_ops.TrafficOperationsScenarioTest.test_basic_sctp_traffic)"
zuul_copy_output:
'{{ devstack_base_dir }}/data/ovs': 'logs'
'{{ devstack_base_dir }}/data/ovn': 'logs'