From d7f0c819e376297989773c35f417fb3e0f2cd1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20J=C3=B3zefczyk?= Date: Wed, 24 Jul 2019 09:02:28 +0000 Subject: [PATCH] Validate supported LB algorithm in Amphora provider drivers This patch adds supported LB algorithm validation in Amphora provider drivers. Change-Id: Ifc995ebe6165dbb57b8eb40bcc3c7e2a0eba94dc Story: 2006264 Task: 35971 --- .../api/drivers/amphora_driver/v1/driver.py | 15 ++++++++++ .../api/drivers/amphora_driver/v2/driver.py | 15 ++++++++++ .../amphora_driver/v1/test_amphora_driver.py | 28 ++++++++++++++++++- .../amphora_driver/v2/test_amphora_driver.py | 28 ++++++++++++++++++- 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/octavia/api/drivers/amphora_driver/v1/driver.py b/octavia/api/drivers/amphora_driver/v1/driver.py index b572df576c..7f5992c6c0 100644 --- a/octavia/api/drivers/amphora_driver/v1/driver.py +++ b/octavia/api/drivers/amphora_driver/v1/driver.py @@ -37,6 +37,10 @@ from octavia.network import base as network_base CONF = cfg.CONF CONF.import_group('oslo_messaging', 'octavia.common.config') LOG = logging.getLogger(__name__) +AMPHORA_SUPPORTED_LB_ALGORITHMS = [ + consts.LB_ALGORITHM_ROUND_ROBIN, + consts.LB_ALGORITHM_SOURCE_IP, + consts.LB_ALGORITHM_LEAST_CONNECTIONS] class AmphoraProviderDriver(driver_base.ProviderDriver): @@ -49,6 +53,14 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): self.client = rpc.get_client(self.target) self.repositories = repositories.Repositories() + def _validate_pool_algorithm(self, pool): + if pool.lb_algorithm not in AMPHORA_SUPPORTED_LB_ALGORITHMS: + msg = ('Amphora provider does not support %s algorithm.' + % pool.lb_algorithm) + raise exceptions.UnsupportedOptionError( + user_fault_string=msg, + operator_fault_string=msg) + # Load Balancer def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary): vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary) @@ -132,6 +144,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): # Pool def pool_create(self, pool): + self._validate_pool_algorithm(pool) payload = {consts.POOL_ID: pool.pool_id} self.client.cast({}, 'create_pool', **payload) @@ -141,6 +154,8 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): self.client.cast({}, 'delete_pool', **payload) def pool_update(self, old_pool, new_pool): + if new_pool.lb_algorithm: + self._validate_pool_algorithm(new_pool) pool_dict = new_pool.to_dict() if 'admin_state_up' in pool_dict: pool_dict['enabled'] = pool_dict.pop('admin_state_up') diff --git a/octavia/api/drivers/amphora_driver/v2/driver.py b/octavia/api/drivers/amphora_driver/v2/driver.py index f09b999dde..944bcaa687 100644 --- a/octavia/api/drivers/amphora_driver/v2/driver.py +++ b/octavia/api/drivers/amphora_driver/v2/driver.py @@ -37,6 +37,10 @@ from octavia.network import base as network_base CONF = cfg.CONF CONF.import_group('oslo_messaging', 'octavia.common.config') LOG = logging.getLogger(__name__) +AMPHORA_SUPPORTED_LB_ALGORITHMS = [ + consts.LB_ALGORITHM_ROUND_ROBIN, + consts.LB_ALGORITHM_SOURCE_IP, + consts.LB_ALGORITHM_LEAST_CONNECTIONS] class AmphoraProviderDriver(driver_base.ProviderDriver): @@ -48,6 +52,14 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): self.client = rpc.get_client(self.target) self.repositories = repositories.Repositories() + def _validate_pool_algorithm(self, pool): + if pool.lb_algorithm not in AMPHORA_SUPPORTED_LB_ALGORITHMS: + msg = ('Amphora provider does not support %s algorithm.' + % pool.lb_algorithm) + raise exceptions.UnsupportedOptionError( + user_fault_string=msg, + operator_fault_string=msg) + # Load Balancer def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary): vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary) @@ -131,6 +143,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): # Pool def pool_create(self, pool): + self._validate_pool_algorithm(pool) payload = {consts.POOL_ID: pool.pool_id} self.client.cast({}, 'create_pool', **payload) @@ -140,6 +153,8 @@ class AmphoraProviderDriver(driver_base.ProviderDriver): self.client.cast({}, 'delete_pool', **payload) def pool_update(self, old_pool, new_pool): + if new_pool.lb_algorithm: + self._validate_pool_algorithm(new_pool) pool_dict = new_pool.to_dict() if 'admin_state_up' in pool_dict: pool_dict['enabled'] = pool_dict.pop('admin_state_up') diff --git a/octavia/tests/unit/api/drivers/amphora_driver/v1/test_amphora_driver.py b/octavia/tests/unit/api/drivers/amphora_driver/v1/test_amphora_driver.py index 8988f5a9eb..cbe17c3fc4 100644 --- a/octavia/tests/unit/api/drivers/amphora_driver/v1/test_amphora_driver.py +++ b/octavia/tests/unit/api/drivers/amphora_driver/v1/test_amphora_driver.py @@ -165,11 +165,23 @@ class TestAmphoraDriver(base.TestRpc): @mock.patch('oslo_messaging.RPCClient.cast') def test_pool_create(self, mock_cast): provider_pool = driver_dm.Pool( - pool_id=self.sample_data.pool1_id) + pool_id=self.sample_data.pool1_id, + lb_algorithm=consts.LB_ALGORITHM_ROUND_ROBIN) self.amp_driver.pool_create(provider_pool) payload = {consts.POOL_ID: self.sample_data.pool1_id} mock_cast.assert_called_with({}, 'create_pool', **payload) + @mock.patch('oslo_messaging.RPCClient.cast') + def test_pool_create_unsupported_algorithm(self, mock_cast): + provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool.lb_algorithm = 'foo' + self.assertRaises( + exceptions.UnsupportedOptionError, + self.amp_driver.pool_create, + provider_pool) + mock_cast.assert_not_called() + @mock.patch('oslo_messaging.RPCClient.cast') def test_pool_delete(self, mock_cast): provider_pool = driver_dm.Pool( @@ -205,6 +217,20 @@ class TestAmphoraDriver(base.TestRpc): consts.POOL_UPDATES: pool_dict} mock_cast.assert_called_with({}, 'update_pool', **payload) + @mock.patch('oslo_messaging.RPCClient.cast') + def test_pool_update_unsupported_algorithm(self, mock_cast): + old_provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool.lb_algorithm = 'foo' + self.assertRaises( + exceptions.UnsupportedOptionError, + self.amp_driver.pool_update, + old_provider_pool, + provider_pool) + mock_cast.assert_not_called() + # Member @mock.patch('octavia.db.api.get_session') @mock.patch('octavia.db.repositories.PoolRepository.get') diff --git a/octavia/tests/unit/api/drivers/amphora_driver/v2/test_amphora_driver.py b/octavia/tests/unit/api/drivers/amphora_driver/v2/test_amphora_driver.py index 4cca47c049..026e090065 100644 --- a/octavia/tests/unit/api/drivers/amphora_driver/v2/test_amphora_driver.py +++ b/octavia/tests/unit/api/drivers/amphora_driver/v2/test_amphora_driver.py @@ -165,11 +165,23 @@ class TestAmphoraDriver(base.TestRpc): @mock.patch('oslo_messaging.RPCClient.cast') def test_pool_create(self, mock_cast): provider_pool = driver_dm.Pool( - pool_id=self.sample_data.pool1_id) + pool_id=self.sample_data.pool1_id, + lb_algorithm=consts.LB_ALGORITHM_ROUND_ROBIN) self.amp_driver.pool_create(provider_pool) payload = {consts.POOL_ID: self.sample_data.pool1_id} mock_cast.assert_called_with({}, 'create_pool', **payload) + @mock.patch('oslo_messaging.RPCClient.cast') + def test_pool_create_unsupported_algorithm(self, mock_cast): + provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool.lb_algorithm = 'foo' + self.assertRaises( + exceptions.UnsupportedOptionError, + self.amp_driver.pool_create, + provider_pool) + mock_cast.assert_not_called() + @mock.patch('oslo_messaging.RPCClient.cast') def test_pool_delete(self, mock_cast): provider_pool = driver_dm.Pool( @@ -205,6 +217,20 @@ class TestAmphoraDriver(base.TestRpc): consts.POOL_UPDATES: pool_dict} mock_cast.assert_called_with({}, 'update_pool', **payload) + @mock.patch('oslo_messaging.RPCClient.cast') + def test_pool_update_unsupported_algorithm(self, mock_cast): + old_provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool = driver_dm.Pool( + pool_id=self.sample_data.pool1_id) + provider_pool.lb_algorithm = 'foo' + self.assertRaises( + exceptions.UnsupportedOptionError, + self.amp_driver.pool_update, + old_provider_pool, + provider_pool) + mock_cast.assert_not_called() + # Member @mock.patch('octavia.db.api.get_session') @mock.patch('octavia.db.repositories.PoolRepository.get')