diff --git a/octavia/controller/worker/tasks/network_tasks.py b/octavia/controller/worker/tasks/network_tasks.py index 69644098f2..462fdce747 100644 --- a/octavia/controller/worker/tasks/network_tasks.py +++ b/octavia/controller/worker/tasks/network_tasks.py @@ -357,28 +357,7 @@ class GetAmphoraeNetworkConfigs(BaseNetworkTask): def execute(self, loadbalancer): LOG.debug("Retrieving vip network details.") - vip_subnet = self.network_driver.get_subnet(loadbalancer.vip.subnet_id) - vip_port = self.network_driver.get_port(loadbalancer.vip.port_id) - amp_net_configs = {} - for amp in loadbalancer.amphorae: - if amp.status != constants.DELETED: - LOG.debug("Retrieving network details for amphora %s", amp.id) - vrrp_port = self.network_driver.get_port(amp.vrrp_port_id) - vrrp_subnet = self.network_driver.get_subnet( - vrrp_port.get_subnet_id(amp.vrrp_ip)) - ha_port = self.network_driver.get_port(amp.ha_port_id) - ha_subnet = self.network_driver.get_subnet( - ha_port.get_subnet_id(amp.ha_ip)) - amp_net_configs[amp.id] = n_data_models.AmphoraNetworkConfig( - amphora=amp, - vip_subnet=vip_subnet, - vip_port=vip_port, - vrrp_subnet=vrrp_subnet, - vrrp_port=vrrp_port, - ha_subnet=ha_subnet, - ha_port=ha_port - ) - return amp_net_configs + return self.network_driver.get_network_configs(loadbalancer) class FailoverPreparationForAmphora(BaseNetworkTask): diff --git a/octavia/network/base.py b/octavia/network/base.py index e0907ae62c..77aee34e04 100644 --- a/octavia/network/base.py +++ b/octavia/network/base.py @@ -235,3 +235,25 @@ class AbstractNetworkDriver(object): :raises: PlugNetworkException, AmphoraNotFound, NetworkNotFound """ pass + + @abc.abstractmethod + def get_network_configs(self, load_balancer): + """Retrieve network configurations + + This method assumes that a dictionary of AmphoraNetworkConfigs keyed + off of the related amphora id are returned. + The configs contain data pertaining to each amphora that is later + used for finalization of the entire load balancer configuration. + The data provided to these configs is left up to the driver, this + means the driver is responsible for providing data that is appropriate + for the amphora network configurations. + + Example return: + {: } + + :param load_balancer: The load_balancer configuration + :return: dict of octavia.network.data_models.AmphoraNetworkConfig + keyed off of the amphora id the config is associated with. + :raises: NotFound, NetworkNotFound, SubnetNotFound, PortNotFound + """ + pass diff --git a/octavia/network/drivers/neutron/allowed_address_pairs.py b/octavia/network/drivers/neutron/allowed_address_pairs.py index d999293cb5..71db462ca1 100644 --- a/octavia/network/drivers/neutron/allowed_address_pairs.py +++ b/octavia/network/drivers/neutron/allowed_address_pairs.py @@ -25,6 +25,7 @@ from octavia.common import constants from octavia.common import data_models from octavia.i18n import _LE, _LI, _LW from octavia.network import base +from octavia.network import data_models as n_data_models from octavia.network.drivers.neutron import base as neutron_base from octavia.network.drivers.neutron import utils @@ -462,3 +463,28 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver): port_id=port.id) LOG.exception(message) raise base.PlugNetworkException(message) + + def get_network_configs(self, loadbalancer): + vip_subnet = self.get_subnet(loadbalancer.vip.subnet_id) + vip_port = self.get_port(loadbalancer.vip.port_id) + amp_configs = {} + for amp in loadbalancer.amphorae: + if amp.status != constants.DELETED: + LOG.debug("Retrieving network details for amphora %s", amp.id) + vrrp_port = self.get_port(amp.vrrp_port_id) + vrrp_subnet = self.get_subnet( + vrrp_port.get_subnet_id(amp.vrrp_ip)) + ha_port = self.get_port(amp.ha_port_id) + ha_subnet = self.get_subnet( + ha_port.get_subnet_id(amp.ha_ip)) + + amp_configs[amp.id] = n_data_models.AmphoraNetworkConfig( + amphora=amp, + vip_subnet=vip_subnet, + vip_port=vip_port, + vrrp_subnet=vrrp_subnet, + vrrp_port=vrrp_port, + ha_subnet=ha_subnet, + ha_port=ha_port + ) + return amp_configs diff --git a/octavia/network/drivers/noop_driver/driver.py b/octavia/network/drivers/noop_driver/driver.py index e4f012a716..339d6fd5b1 100644 --- a/octavia/network/drivers/noop_driver/driver.py +++ b/octavia/network/drivers/noop_driver/driver.py @@ -131,6 +131,12 @@ class NoopManager(object): self.networkconfigconfig[(compute_id, port)] = ( compute_id, port, 'plug_port') + def get_network_configs(self, loadbalancer): + LOG.debug("Network %s no-op, get_network_configs loadbalancer id %s ", + self.__class__.__name__, loadbalancer.id) + self.networkconfigconfig[(loadbalancer)] = ( + loadbalancer, 'get_network_configs') + class NoopNetworkDriver(driver_base.AbstractNetworkDriver): def __init__(self): @@ -176,3 +182,6 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver): def plug_port(self, compute_id, port): return self.driver.plug_port(compute_id, port) + + def get_network_configs(self, loadbalancer): + return self.driver.get_network_configs(loadbalancer) diff --git a/octavia/tests/unit/controller/worker/tasks/test_network_tasks.py b/octavia/tests/unit/controller/worker/tasks/test_network_tasks.py index 48ef1175a7..fa95ef9634 100644 --- a/octavia/tests/unit/controller/worker/tasks/test_network_tasks.py +++ b/octavia/tests/unit/controller/worker/tasks/test_network_tasks.py @@ -394,40 +394,10 @@ class TestNetworkTasks(base.TestCase): mock_driver.update_vip.assert_called_once_with(lb) def test_get_amphorae_network_configs(self, mock_driver): - + lb = o_data_models.LoadBalancer() net_task = network_tasks.GetAmphoraeNetworkConfigs() - net_task.execute(LB) - mock_driver.get_subnet.assert_called_once_with(SUBNET_ID) - mock_driver.get_port.assert_called_once_with(PORT_ID) - - mock_driver.reset_mock() - self.amphora_mock.status = constants.DELETED - self.load_balancer_mock.amphorae = [self.amphora_mock] - net_task = network_tasks.GetAmphoraeNetworkConfigs() - configs = net_task.execute(self.load_balancer_mock) - self.assertEqual({}, configs) - - mock_driver.reset_mock() - self.vip_mock.port_id = 1 - self.amphora_mock.status = constants.ACTIVE - self.amphora_mock.vrrp_port_id = 2 - self.amphora_mock.vrrp_ip = "10.0.0.1" - self.amphora_mock.ha_port_id = 3 - self.amphora_mock.ha_ip = "10.0.0.2" - self.load_balancer_mock.amphorae = [self.amphora_mock] - net_task = network_tasks.GetAmphoraeNetworkConfigs() - configs = net_task.execute(self.load_balancer_mock) - vip_port_id = mock.call(1) - vrrp_port_id_call = mock.call(2) - ha_port_id_call = mock.call(3) - vrrp_port_subnet_call = mock.call().get_subnet_id('10.0.0.1') - ha_port_subnet_call = mock.call().get_subnet_id('10.0.0.2') - mock_driver.get_port.assert_has_calls([vip_port_id, - vrrp_port_id_call, - vrrp_port_subnet_call, - ha_port_id_call, - ha_port_subnet_call]) - self.assertEqual(1, len(configs)) + net_task.execute(lb) + mock_driver.get_network_configs.assert_called_once_with(lb) def test_failover_preparation_for_amphora(self, mock_driver): failover = network_tasks.FailoverPreparationForAmphora() diff --git a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py index 7241d2d2f6..a31438292b 100644 --- a/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py +++ b/octavia/tests/unit/network/drivers/neutron/test_allowed_address_pairs.py @@ -619,3 +619,44 @@ class TestAllowedAddressPairsDriver(base.TestCase): self.driver.plug_port, amphora, port) + + def test_get_network_configs(self): + amphora_mock = mock.MagicMock() + load_balancer_mock = mock.MagicMock() + vip_mock = mock.MagicMock() + amphora_mock.status = constants.DELETED + load_balancer_mock.amphorae = [amphora_mock] + show_port = self.driver.neutron_client.show_port + show_port.return_value = n_constants.MOCK_NEUTRON_PORT + fake_subnet = {'subnet': { + 'id': n_constants.MOCK_SUBNET_ID, + 'gateway_ip': n_constants.MOCK_IP_ADDRESS, + 'cidr': n_constants.MOCK_CIDR}} + show_subnet = self.driver.neutron_client.show_subnet + show_subnet.return_value = fake_subnet + configs = self.driver.get_network_configs(load_balancer_mock) + self.assertEqual({}, configs) + + vip_mock.port_id = 1 + amphora_mock.id = 222 + amphora_mock.status = constants.ACTIVE + amphora_mock.vrrp_port_id = 2 + amphora_mock.vrrp_ip = "10.0.0.1" + amphora_mock.ha_port_id = 3 + amphora_mock.ha_ip = "10.0.0.2" + load_balancer_mock.amphorae = [amphora_mock] + + configs = self.driver.get_network_configs(load_balancer_mock) + self.assertEqual(1, len(configs)) + config = configs[222] + # TODO(ptoohill): find a way to return different items for multiple + # calls to the same method, right now each call to show subnet + # will return the same values if a method happens to call it + # multiple times for different subnets. We should be able to verify + # different requests get different expected data. + expected_port_id = n_constants.MOCK_NEUTRON_PORT['port']['id'] + self.assertEqual(expected_port_id, config.ha_port.id) + self.assertEqual(expected_port_id, config.vrrp_port.id) + expected_subnet_id = fake_subnet['subnet']['id'] + self.assertEqual(expected_subnet_id, config.ha_subnet.id) + self.assertEqual(expected_subnet_id, config.vrrp_subnet.id) diff --git a/octavia/tests/unit/network/drivers/test_network_noop_driver.py b/octavia/tests/unit/network/drivers/test_network_noop_driver.py index deb6c9a909..55394dc8d1 100644 --- a/octavia/tests/unit/network/drivers/test_network_noop_driver.py +++ b/octavia/tests/unit/network/drivers/test_network_noop_driver.py @@ -127,3 +127,10 @@ class TestNoopNetworkDriver(base.TestCase): (self.compute_id, self.port, 'plug_port'), self.driver.driver.networkconfigconfig[self.compute_id, self.port] ) + + def test_get_network_configs(self): + self.driver.get_network_configs(self.load_balancer) + self.assertEqual( + (self.load_balancer, 'get_network_configs'), + self.driver.driver.networkconfigconfig[self.load_balancer] + )