Validate listener protocol in amphora driver

Validate that the amphora driver supports the listener protocol when
receving a listener_create request.

It returns an UnsupportedOptionError exception to the user if the
amphora driver doesn't support a protocol that is defined in the API
(ex: SCTP is supported in the API in the Victoria release, but not in
the amphora driver).

Story: 2008545
Task: 41647

Change-Id: I1c5cb987945a7a465bfecfda399dfe93fc1b76bb
(cherry picked from commit fbbc5f9024)
This commit is contained in:
Gregory Thiemonge 2021-01-19 18:16:53 +01:00
parent b5c6c884a4
commit b326d63669
4 changed files with 72 additions and 2 deletions

View File

@ -23,6 +23,7 @@ from stevedore import driver as stevedore_driver
from octavia_lib.api.drivers import data_models as driver_dm
from octavia_lib.api.drivers import exceptions
from octavia_lib.api.drivers import provider_base as driver_base
from octavia_lib.common import constants as lib_consts
from octavia.api.drivers.amphora_driver import availability_zone_schema
from octavia.api.drivers.amphora_driver import flavor_schema
@ -43,6 +44,16 @@ AMPHORA_SUPPORTED_LB_ALGORITHMS = [
consts.LB_ALGORITHM_SOURCE_IP,
consts.LB_ALGORITHM_LEAST_CONNECTIONS]
AMPHORA_SUPPORTED_PROTOCOLS = [
lib_consts.PROTOCOL_TCP,
lib_consts.PROTOCOL_HTTP,
lib_consts.PROTOCOL_HTTPS,
lib_consts.PROTOCOL_TERMINATED_HTTPS,
lib_consts.PROTOCOL_PROXY,
lib_consts.PROTOCOL_PROXYV2,
lib_consts.PROTOCOL_UDP,
]
class AmphoraProviderDriver(driver_base.ProviderDriver):
def __init__(self):
@ -62,6 +73,16 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
user_fault_string=msg,
operator_fault_string=msg)
def _validate_listener_protocol(self, listener):
if listener.protocol not in AMPHORA_SUPPORTED_PROTOCOLS:
msg = ('Amphora provider does not support %s protocol. '
'Supported: %s'
% (listener.protocol,
", ".join(AMPHORA_SUPPORTED_PROTOCOLS)))
raise exceptions.UnsupportedOptionError(
user_fault_string=msg,
operator_fault_string=msg)
def _validate_alpn_protocols(self, listener):
if not listener.alpn_protocols:
return
@ -136,6 +157,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
# Listener
def listener_create(self, listener):
self._validate_listener_protocol(listener)
self._validate_alpn_protocols(listener)
payload = {consts.LISTENER_ID: listener.listener_id}
self.client.cast({}, 'create_listener', **payload)

View File

@ -24,6 +24,7 @@ from stevedore import driver as stevedore_driver
from octavia_lib.api.drivers import data_models as driver_dm
from octavia_lib.api.drivers import exceptions
from octavia_lib.api.drivers import provider_base as driver_base
from octavia_lib.common import constants as lib_consts
from octavia.api.drivers.amphora_driver import availability_zone_schema
from octavia.api.drivers.amphora_driver import flavor_schema
@ -44,6 +45,16 @@ AMPHORA_SUPPORTED_LB_ALGORITHMS = [
consts.LB_ALGORITHM_SOURCE_IP,
consts.LB_ALGORITHM_LEAST_CONNECTIONS]
AMPHORA_SUPPORTED_PROTOCOLS = [
lib_consts.PROTOCOL_TCP,
lib_consts.PROTOCOL_HTTP,
lib_consts.PROTOCOL_HTTPS,
lib_consts.PROTOCOL_TERMINATED_HTTPS,
lib_consts.PROTOCOL_PROXY,
lib_consts.PROTOCOL_PROXYV2,
lib_consts.PROTOCOL_UDP,
]
class AmphoraProviderDriver(driver_base.ProviderDriver):
def __init__(self):
@ -64,6 +75,16 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
user_fault_string=msg,
operator_fault_string=msg)
def _validate_listener_protocol(self, listener):
if listener.protocol not in AMPHORA_SUPPORTED_PROTOCOLS:
msg = ('Amphora provider does not support %s protocol. '
'Supported: %s'
% (listener.protocol,
", ".join(AMPHORA_SUPPORTED_PROTOCOLS)))
raise exceptions.UnsupportedOptionError(
user_fault_string=msg,
operator_fault_string=msg)
def _validate_alpn_protocols(self, listener):
if not listener.alpn_protocols:
return
@ -165,6 +186,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
# Listener
def listener_create(self, listener):
self._validate_listener_protocol(listener)
self._validate_alpn_protocols(listener)
payload = {consts.LISTENER: listener.to_dict()}
self._encrypt_listener_dict(payload[consts.LISTENER])

View File

@ -123,6 +123,7 @@ class TestAmphoraDriver(base.TestRpc):
def test_listener_create(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id,
protocol=consts.PROTOCOL_HTTPS,
alpn_protocols=consts.AMPHORA_SUPPORTED_ALPN_PROTOCOLS)
self.amp_driver.listener_create(provider_listener)
payload = {consts.LISTENER_ID: self.sample_data.listener1_id}
@ -131,7 +132,8 @@ class TestAmphoraDriver(base.TestRpc):
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_create_unsupported_alpn(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id)
listener_id=self.sample_data.listener1_id,
protocol=consts.PROTOCOL_HTTPS)
provider_listener.alpn_protocols = ['http/1.1', 'eureka']
self.assertRaises(
exceptions.UnsupportedOptionError,
@ -139,6 +141,17 @@ class TestAmphoraDriver(base.TestRpc):
provider_listener)
mock_cast.assert_not_called()
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_create_unsupported_protocol(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id,
protocol='UNSUPPORTED_PROTO')
self.assertRaises(
exceptions.UnsupportedOptionError,
self.amp_driver.listener_create,
provider_listener)
mock_cast.assert_not_called()
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_delete(self, mock_cast):
provider_listener = driver_dm.Listener(

View File

@ -123,6 +123,7 @@ class TestAmphoraDriver(base.TestRpc):
def test_listener_create(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id,
protocol=consts.PROTOCOL_HTTPS,
alpn_protocols=consts.AMPHORA_SUPPORTED_ALPN_PROTOCOLS)
self.amp_driver.listener_create(provider_listener)
payload = {consts.LISTENER: provider_listener.to_dict()}
@ -131,7 +132,8 @@ class TestAmphoraDriver(base.TestRpc):
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_create_unsupported_alpn(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id)
listener_id=self.sample_data.listener1_id,
protocol=consts.PROTOCOL_HTTPS)
provider_listener.alpn_protocols = ['http/1.1', 'eureka']
self.assertRaises(
exceptions.UnsupportedOptionError,
@ -139,6 +141,17 @@ class TestAmphoraDriver(base.TestRpc):
provider_listener)
mock_cast.assert_not_called()
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_create_unsupported_protocol(self, mock_cast):
provider_listener = driver_dm.Listener(
listener_id=self.sample_data.listener1_id,
protocol='UNSUPPORTED_PROTO')
self.assertRaises(
exceptions.UnsupportedOptionError,
self.amp_driver.listener_create,
provider_listener)
mock_cast.assert_not_called()
@mock.patch('oslo_messaging.RPCClient.cast')
def test_listener_delete(self, mock_cast):
provider_listener = driver_dm.Listener(