Merge "Network driver should generate network configs"

This commit is contained in:
Jenkins 2016-05-28 02:02:42 +00:00 committed by Gerrit Code Review
commit 38f0b5f0b9
7 changed files with 109 additions and 55 deletions

View File

@ -357,28 +357,7 @@ class GetAmphoraeNetworkConfigs(BaseNetworkTask):
def execute(self, loadbalancer): def execute(self, loadbalancer):
LOG.debug("Retrieving vip network details.") LOG.debug("Retrieving vip network details.")
vip_subnet = self.network_driver.get_subnet(loadbalancer.vip.subnet_id) return self.network_driver.get_network_configs(loadbalancer)
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
class FailoverPreparationForAmphora(BaseNetworkTask): class FailoverPreparationForAmphora(BaseNetworkTask):

View File

@ -235,3 +235,25 @@ class AbstractNetworkDriver(object):
:raises: PlugNetworkException, AmphoraNotFound, NetworkNotFound :raises: PlugNetworkException, AmphoraNotFound, NetworkNotFound
""" """
pass 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:
{<amphora.id>: <AmphoraNetworkConfig>}
: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

View File

@ -25,6 +25,7 @@ from octavia.common import constants
from octavia.common import data_models from octavia.common import data_models
from octavia.i18n import _LE, _LI, _LW from octavia.i18n import _LE, _LI, _LW
from octavia.network import base 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 base as neutron_base
from octavia.network.drivers.neutron import utils from octavia.network.drivers.neutron import utils
@ -462,3 +463,28 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
port_id=port.id) port_id=port.id)
LOG.exception(message) LOG.exception(message)
raise base.PlugNetworkException(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

View File

@ -131,6 +131,12 @@ class NoopManager(object):
self.networkconfigconfig[(compute_id, port)] = ( self.networkconfigconfig[(compute_id, port)] = (
compute_id, port, 'plug_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): class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
def __init__(self): def __init__(self):
@ -176,3 +182,6 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
def plug_port(self, compute_id, port): def plug_port(self, compute_id, port):
return self.driver.plug_port(compute_id, port) return self.driver.plug_port(compute_id, port)
def get_network_configs(self, loadbalancer):
return self.driver.get_network_configs(loadbalancer)

View File

@ -394,40 +394,10 @@ class TestNetworkTasks(base.TestCase):
mock_driver.update_vip.assert_called_once_with(lb) mock_driver.update_vip.assert_called_once_with(lb)
def test_get_amphorae_network_configs(self, mock_driver): def test_get_amphorae_network_configs(self, mock_driver):
lb = o_data_models.LoadBalancer()
net_task = network_tasks.GetAmphoraeNetworkConfigs() net_task = network_tasks.GetAmphoraeNetworkConfigs()
net_task.execute(LB) net_task.execute(lb)
mock_driver.get_subnet.assert_called_once_with(SUBNET_ID) mock_driver.get_network_configs.assert_called_once_with(lb)
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))
def test_failover_preparation_for_amphora(self, mock_driver): def test_failover_preparation_for_amphora(self, mock_driver):
failover = network_tasks.FailoverPreparationForAmphora() failover = network_tasks.FailoverPreparationForAmphora()

View File

@ -619,3 +619,44 @@ class TestAllowedAddressPairsDriver(base.TestCase):
self.driver.plug_port, self.driver.plug_port,
amphora, amphora,
port) 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)

View File

@ -127,3 +127,10 @@ class TestNoopNetworkDriver(base.TestCase):
(self.compute_id, self.port, 'plug_port'), (self.compute_id, self.port, 'plug_port'),
self.driver.driver.networkconfigconfig[self.compute_id, self.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]
)