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
This commit is contained in:
Maciej Józefczyk 2019-07-24 09:02:28 +00:00
parent d5ffd2ca40
commit d7f0c819e3
4 changed files with 84 additions and 2 deletions

View File

@ -37,6 +37,10 @@ from octavia.network import base as network_base
CONF = cfg.CONF CONF = cfg.CONF
CONF.import_group('oslo_messaging', 'octavia.common.config') CONF.import_group('oslo_messaging', 'octavia.common.config')
LOG = logging.getLogger(__name__) 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): class AmphoraProviderDriver(driver_base.ProviderDriver):
@ -49,6 +53,14 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
self.client = rpc.get_client(self.target) self.client = rpc.get_client(self.target)
self.repositories = repositories.Repositories() 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 # Load Balancer
def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary): def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary):
vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary) vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary)
@ -132,6 +144,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
# Pool # Pool
def pool_create(self, pool): def pool_create(self, pool):
self._validate_pool_algorithm(pool)
payload = {consts.POOL_ID: pool.pool_id} payload = {consts.POOL_ID: pool.pool_id}
self.client.cast({}, 'create_pool', **payload) self.client.cast({}, 'create_pool', **payload)
@ -141,6 +154,8 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
self.client.cast({}, 'delete_pool', **payload) self.client.cast({}, 'delete_pool', **payload)
def pool_update(self, old_pool, new_pool): 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() pool_dict = new_pool.to_dict()
if 'admin_state_up' in pool_dict: if 'admin_state_up' in pool_dict:
pool_dict['enabled'] = pool_dict.pop('admin_state_up') pool_dict['enabled'] = pool_dict.pop('admin_state_up')

View File

@ -37,6 +37,10 @@ from octavia.network import base as network_base
CONF = cfg.CONF CONF = cfg.CONF
CONF.import_group('oslo_messaging', 'octavia.common.config') CONF.import_group('oslo_messaging', 'octavia.common.config')
LOG = logging.getLogger(__name__) 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): class AmphoraProviderDriver(driver_base.ProviderDriver):
@ -48,6 +52,14 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
self.client = rpc.get_client(self.target) self.client = rpc.get_client(self.target)
self.repositories = repositories.Repositories() 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 # Load Balancer
def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary): def create_vip_port(self, loadbalancer_id, project_id, vip_dictionary):
vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary) vip_obj = driver_utils.provider_vip_dict_to_vip_obj(vip_dictionary)
@ -131,6 +143,7 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
# Pool # Pool
def pool_create(self, pool): def pool_create(self, pool):
self._validate_pool_algorithm(pool)
payload = {consts.POOL_ID: pool.pool_id} payload = {consts.POOL_ID: pool.pool_id}
self.client.cast({}, 'create_pool', **payload) self.client.cast({}, 'create_pool', **payload)
@ -140,6 +153,8 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
self.client.cast({}, 'delete_pool', **payload) self.client.cast({}, 'delete_pool', **payload)
def pool_update(self, old_pool, new_pool): 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() pool_dict = new_pool.to_dict()
if 'admin_state_up' in pool_dict: if 'admin_state_up' in pool_dict:
pool_dict['enabled'] = pool_dict.pop('admin_state_up') pool_dict['enabled'] = pool_dict.pop('admin_state_up')

View File

@ -165,11 +165,23 @@ class TestAmphoraDriver(base.TestRpc):
@mock.patch('oslo_messaging.RPCClient.cast') @mock.patch('oslo_messaging.RPCClient.cast')
def test_pool_create(self, mock_cast): def test_pool_create(self, mock_cast):
provider_pool = driver_dm.Pool( 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) self.amp_driver.pool_create(provider_pool)
payload = {consts.POOL_ID: self.sample_data.pool1_id} payload = {consts.POOL_ID: self.sample_data.pool1_id}
mock_cast.assert_called_with({}, 'create_pool', **payload) 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') @mock.patch('oslo_messaging.RPCClient.cast')
def test_pool_delete(self, mock_cast): def test_pool_delete(self, mock_cast):
provider_pool = driver_dm.Pool( provider_pool = driver_dm.Pool(
@ -205,6 +217,20 @@ class TestAmphoraDriver(base.TestRpc):
consts.POOL_UPDATES: pool_dict} consts.POOL_UPDATES: pool_dict}
mock_cast.assert_called_with({}, 'update_pool', **payload) 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 # Member
@mock.patch('octavia.db.api.get_session') @mock.patch('octavia.db.api.get_session')
@mock.patch('octavia.db.repositories.PoolRepository.get') @mock.patch('octavia.db.repositories.PoolRepository.get')

View File

@ -165,11 +165,23 @@ class TestAmphoraDriver(base.TestRpc):
@mock.patch('oslo_messaging.RPCClient.cast') @mock.patch('oslo_messaging.RPCClient.cast')
def test_pool_create(self, mock_cast): def test_pool_create(self, mock_cast):
provider_pool = driver_dm.Pool( 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) self.amp_driver.pool_create(provider_pool)
payload = {consts.POOL_ID: self.sample_data.pool1_id} payload = {consts.POOL_ID: self.sample_data.pool1_id}
mock_cast.assert_called_with({}, 'create_pool', **payload) 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') @mock.patch('oslo_messaging.RPCClient.cast')
def test_pool_delete(self, mock_cast): def test_pool_delete(self, mock_cast):
provider_pool = driver_dm.Pool( provider_pool = driver_dm.Pool(
@ -205,6 +217,20 @@ class TestAmphoraDriver(base.TestRpc):
consts.POOL_UPDATES: pool_dict} consts.POOL_UPDATES: pool_dict}
mock_cast.assert_called_with({}, 'update_pool', **payload) 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 # Member
@mock.patch('octavia.db.api.get_session') @mock.patch('octavia.db.api.get_session')
@mock.patch('octavia.db.repositories.PoolRepository.get') @mock.patch('octavia.db.repositories.PoolRepository.get')