Adding methods to network driver to get more info
The network driver needs the ability to retrieve specific information about subnets and ports and pass that information to other components. Having info about the subnet gives us cidr and gateway data that is valuable when setting up the amphora's routes for the separation of tenant data and management data. Because of this need, methods to retrieve network, subnet, and port details has been added. This also adds a another data model AmphoraNetworkConfig that contains subnet and port information for the vip, vrrp, and ha networks on an amphora. A network task has been added that builds this data structure by calling the new methods added to the network driver. Change-Id: Ica912337c7d52659a9733096878664f734f27b00
This commit is contained in:
parent
ec206a3cca
commit
f074222842
@ -252,7 +252,9 @@ class UpdateAmphoraVIPData(BaseDatabaseTask):
|
||||
for amp_data in amps_data:
|
||||
self.repos.amphora.update(db_apis.get_session(), amp_data.id,
|
||||
vrrp_ip=amp_data.vrrp_ip,
|
||||
ha_ip=amp_data.ha_ip)
|
||||
ha_ip=amp_data.ha_ip,
|
||||
vrrp_port_id=amp_data.vrrp_port_id,
|
||||
ha_port_id=amp_data.ha_port_id)
|
||||
|
||||
|
||||
class MapLoadbalancerToAmphora(BaseDatabaseTask):
|
||||
|
@ -16,6 +16,7 @@
|
||||
import logging
|
||||
|
||||
from oslo_config import cfg
|
||||
import six
|
||||
from stevedore import driver as stevedore_driver
|
||||
from taskflow import task
|
||||
from taskflow.types import failure
|
||||
@ -63,7 +64,7 @@ class CalculateDelta(BaseNetworkTask):
|
||||
:returns the delta
|
||||
"""
|
||||
|
||||
deltas = []
|
||||
deltas = {}
|
||||
for amphora in loadbalancer.amphorae:
|
||||
|
||||
LOG.debug("Calculating network delta for amphora id: %s"
|
||||
@ -71,11 +72,12 @@ class CalculateDelta(BaseNetworkTask):
|
||||
|
||||
# Figure out what networks we want
|
||||
# seed with lb network(s)
|
||||
subnet = self.network_driver.get_subnet(loadbalancer.vip.subnet_id)
|
||||
desired_network_ids = {CONF.controller_worker.amp_network,
|
||||
loadbalancer.vip.network_id}
|
||||
subnet.network_id}
|
||||
|
||||
if not loadbalancer.listeners:
|
||||
return []
|
||||
return {}
|
||||
|
||||
for listener in loadbalancer.listeners:
|
||||
if (not listener.default_pool) or (
|
||||
@ -101,10 +103,9 @@ class CalculateDelta(BaseNetworkTask):
|
||||
add_ids = desired_network_ids - set(actual_network_nics)
|
||||
add_nics = list(data_models.Interface(
|
||||
network_id=net_id) for net_id in add_ids)
|
||||
deltas.append(data_models.Delta(amphora_id=amphora.id,
|
||||
compute_id=amphora.compute_id,
|
||||
add_nics=add_nics,
|
||||
delete_nics=delete_nics))
|
||||
deltas[amphora.id] = data_models.Delta(
|
||||
amphora_id=amphora.id, compute_id=amphora.compute_id,
|
||||
add_nics=add_nics, delete_nics=delete_nics)
|
||||
|
||||
return deltas
|
||||
|
||||
@ -200,28 +201,26 @@ class HandleNetworkDeltas(BaseNetworkTask):
|
||||
def execute(self, deltas):
|
||||
"""Handle network plugging based off deltas."""
|
||||
|
||||
for delta in deltas:
|
||||
for amp_id, delta in six.iteritems(deltas):
|
||||
for nic in delta.add_nics:
|
||||
self.network_driver.plug_network(delta.compute_id,
|
||||
nic.network_id)
|
||||
|
||||
for nic in delta.delete_nics:
|
||||
try:
|
||||
self.network_driver.unplug_network(delta.compute_id,
|
||||
nic.network_id)
|
||||
except base.NetworkNotFound as e:
|
||||
except base.NetworkNotFound:
|
||||
LOG.debug("Network %d not found ", nic.network_id)
|
||||
pass
|
||||
except Exception as e:
|
||||
LOG.error(
|
||||
_LE("Unable to unplug network - exception: %s"),
|
||||
str(e))
|
||||
pass
|
||||
_LE("Unable to unplug network - exception: %s"), e)
|
||||
|
||||
def revert(self, deltas):
|
||||
def revert(self, result, deltas):
|
||||
"""Handle a network plug or unplug failures."""
|
||||
|
||||
for delta in deltas:
|
||||
if isinstance(result, failure.Failure):
|
||||
return
|
||||
for amp_id, delta in six.iteritems(deltas):
|
||||
LOG.warn(_LW("Unable to plug networks for amp id %s"),
|
||||
delta.amphora_id)
|
||||
if not delta:
|
||||
@ -316,3 +315,32 @@ class UpdateVIP(BaseNetworkTask):
|
||||
LOG.debug("Updating VIP of load_balancer %s." % loadbalancer.id)
|
||||
|
||||
self.network_driver.update_vip(loadbalancer)
|
||||
|
||||
|
||||
class GetAmphoraeNetworkConfigs(BaseNetworkTask):
|
||||
"""Task to retrieve amphorae network details."""
|
||||
|
||||
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:
|
||||
LOG.debug("Retrieving network details for "
|
||||
"amphora {0}".format(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] = 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
|
@ -59,6 +59,10 @@ class NetworkNotFound(NetworkException):
|
||||
pass
|
||||
|
||||
|
||||
class SubnetNotFound(NetworkException):
|
||||
pass
|
||||
|
||||
|
||||
class VIPConfigurationNotFound(NetworkException):
|
||||
pass
|
||||
|
||||
@ -182,11 +186,31 @@ class AbstractNetworkDriver(object):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_network(self, network_id=None, subnet_id=None):
|
||||
"""Retrieves network from network id or subnet id .
|
||||
def get_network(self, network_id):
|
||||
"""Retrieves network from network id.
|
||||
|
||||
:param network_id: id of an network to retrieve
|
||||
:param subnet_id: id of an subnet to retrieve network
|
||||
:return: octavia.network.data_models.Network
|
||||
:raises: NetworkException, NetworkNotFound
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_subnet(self, subnet_id):
|
||||
"""Retrieves subnet from subnet id.
|
||||
|
||||
:param subnet_id: id of a subnet to retrieve
|
||||
:return: octavia.network.data_models.Subnet
|
||||
:raises: NetworkException, SubnetNotFound
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_port(self, port_id):
|
||||
"""Retrieves port from port id.
|
||||
|
||||
:param port_id: id of a port to retrieve
|
||||
:return: octavia.network.data_models.Port
|
||||
:raises: NetworkException, PortNotFound
|
||||
"""
|
||||
pass
|
||||
|
@ -53,3 +53,60 @@ class Network(data_models.BaseDataModel):
|
||||
self.provider_physical_network = provider_physical_network
|
||||
self.provider_segmentation_id = provider_segmentation_id
|
||||
self.router_external = router_external
|
||||
self.mtu = mtu
|
||||
|
||||
|
||||
class Subnet(data_models.BaseDataModel):
|
||||
|
||||
def __init__(self, id=None, name=None, network_id=None, tenant_id=None,
|
||||
gateway_ip=None, cidr=None, ip_version=None):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.network_id = network_id
|
||||
self.tenant_id = tenant_id
|
||||
self.gateway_ip = gateway_ip
|
||||
self.cidr = cidr
|
||||
self.ip_version = ip_version
|
||||
|
||||
|
||||
class Port(data_models.BaseDataModel):
|
||||
|
||||
def __init__(self, id=None, name=None, device_id=None, device_owner=None,
|
||||
mac_address=None, network_id=None, status=None,
|
||||
tenant_id=None, admin_state_up=None, fixed_ips=None):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.device_id = device_id
|
||||
self.device_owner = device_owner
|
||||
self.mac_address = mac_address
|
||||
self.network_id = network_id
|
||||
self.status = status
|
||||
self.tenant_id = tenant_id
|
||||
self.admin_state_up = admin_state_up
|
||||
self.fixed_ips = fixed_ips or []
|
||||
|
||||
def get_subnet_id(self, fixed_ip_address):
|
||||
for fixed_ip in self.fixed_ips:
|
||||
if fixed_ip.ip_address == fixed_ip_address:
|
||||
return fixed_ip.subnet_id
|
||||
|
||||
|
||||
class FixedIP(data_models.BaseDataModel):
|
||||
|
||||
def __init__(self, subnet_id=None, ip_address=None):
|
||||
self.subnet_id = subnet_id
|
||||
self.ip_address = ip_address
|
||||
|
||||
|
||||
class AmphoraNetworkConfig(data_models.BaseDataModel):
|
||||
|
||||
def __init__(self, amphora=None, vip_subnet=None, vip_port=None,
|
||||
vrrp_subnet=None, vrrp_port=None, ha_subnet=None,
|
||||
ha_port=None):
|
||||
self.amphora = amphora
|
||||
self.vip_subnet = vip_subnet
|
||||
self.vip_port = vip_port
|
||||
self.vrrp_subnet = vrrp_subnet
|
||||
self.vrrp_port = vrrp_port
|
||||
self.ha_subnet = ha_subnet
|
||||
self.ha_port = ha_port
|
||||
|
@ -24,6 +24,7 @@ from octavia.common import keystone
|
||||
from octavia.i18n import _LE, _LI
|
||||
from octavia.network import base
|
||||
from octavia.network import data_models as network_models
|
||||
from octavia.network.drivers.neutron import utils
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -58,15 +59,18 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
'will not manage any security groups.'))
|
||||
self.sec_grp_enabled = False
|
||||
|
||||
def _port_to_vip(self, port, load_balancer_id=None):
|
||||
def _port_to_vip(self, port, load_balancer):
|
||||
port = port['port']
|
||||
ip_address = port['fixed_ips'][0]['ip_address']
|
||||
subnet_id = port['fixed_ips'][0]['subnet_id']
|
||||
fixed_ip = {}
|
||||
for port_fixed_ip in port['fixed_ips']:
|
||||
if port_fixed_ip['subnet_id'] == load_balancer.vip.subnet_id:
|
||||
fixed_ip = port_fixed_ip
|
||||
break
|
||||
port_id = port['id']
|
||||
return data_models.Vip(ip_address=ip_address,
|
||||
subnet_id=subnet_id,
|
||||
return data_models.Vip(ip_address=fixed_ip.get('ip_address'),
|
||||
subnet_id=fixed_ip.get('subnet_id'),
|
||||
port_id=port_id,
|
||||
load_balancer_id=load_balancer_id)
|
||||
load_balancer_id=load_balancer.id)
|
||||
|
||||
def _nova_interface_to_octavia_interface(self, amphora_id, nova_interface):
|
||||
ip_address = nova_interface.fixed_ips[0]['ip_address']
|
||||
@ -181,17 +185,6 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
self.nova_client.servers.add_security_group(
|
||||
amphora.compute_id, sec_grp.get('id'))
|
||||
|
||||
def _map_network_to_data_model(self, network):
|
||||
nw = network.get('network')
|
||||
return network_models.Network(
|
||||
id=nw.get('id'), name=nw.get('name'), subnets=nw.get('subnets'),
|
||||
tenant_id=nw.get('tenant_id'),
|
||||
admin_state_up=nw.get('admin_state_up'), mtu=nw.get('mtu'),
|
||||
provider_network_type=nw.get('provider:network_type'),
|
||||
provider_physical_network=nw.get('provider:physical_network'),
|
||||
provider_segmentation_id=nw.get('provider:segmentation_id'),
|
||||
router_external=nw.get('router:external'))
|
||||
|
||||
def deallocate_vip(self, vip):
|
||||
port = self.neutron_client.show_port(vip.port_id)
|
||||
admin_tenant_id = keystone.get_session().get_project_id()
|
||||
@ -235,7 +228,9 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
id=amphora.id,
|
||||
compute_id=amphora.compute_id,
|
||||
vrrp_ip=interface.ip_address,
|
||||
ha_ip=vip.ip_address))
|
||||
ha_ip=vip.ip_address,
|
||||
vrrp_port_id=interface.port_id,
|
||||
ha_port_id=vip.port_id))
|
||||
return plugged_amphorae
|
||||
|
||||
def allocate_vip(self, load_balancer):
|
||||
@ -256,7 +251,7 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
port_id=load_balancer.vip.port_id)
|
||||
LOG.exception(message)
|
||||
raise base.AllocateVIPException(message)
|
||||
return self._port_to_vip(port)
|
||||
return self._port_to_vip(port, load_balancer)
|
||||
|
||||
# Must retrieve the network_id from the subnet
|
||||
try:
|
||||
@ -285,7 +280,7 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
network_id=subnet['network_id'])
|
||||
LOG.exception(message)
|
||||
raise base.AllocateVIPException(message)
|
||||
return self._port_to_vip(new_port)
|
||||
return self._port_to_vip(new_port, load_balancer)
|
||||
|
||||
def unplug_vip(self, load_balancer, vip):
|
||||
try:
|
||||
@ -397,30 +392,53 @@ class AllowedAddressPairsDriver(base.AbstractNetworkDriver):
|
||||
sec_grp = self._get_lb_security_group(load_balancer.id)
|
||||
self._update_security_group_rules(load_balancer, sec_grp.get('id'))
|
||||
|
||||
def get_network(self, network_id=None, subnet_id=None):
|
||||
network = None
|
||||
def get_network(self, network_id):
|
||||
try:
|
||||
if network_id:
|
||||
network = self.neutron_client.show_network(network_id)
|
||||
elif subnet_id:
|
||||
subnet = (self.neutron_client.show_subnet(subnet_id)
|
||||
.get('subnet').get('network_id'))
|
||||
network = self.neutron_client.show_network(subnet)
|
||||
except base.NetworkNotFound:
|
||||
network = self.neutron_client.show_network(network_id)
|
||||
return utils.convert_network_dict_to_model(network)
|
||||
except neutron_client_exceptions.NotFound:
|
||||
message = _LE('Network not found '
|
||||
'(network id: {network_id} '
|
||||
'and subnet id: {subnet_id}.').format(
|
||||
network_id=network_id,
|
||||
subnet_id=subnet_id)
|
||||
'(network id: {network_id}.').format(
|
||||
network_id=network_id)
|
||||
LOG.exception(message)
|
||||
raise base.NetworkNotFound(message)
|
||||
except Exception:
|
||||
message = _LE('Error retrieving network '
|
||||
'(network id: {network_id} '
|
||||
'and subnet id: {subnet_id}.').format(
|
||||
network_id=network_id,
|
||||
'(network id: {network_id}.').format(
|
||||
network_id=network_id)
|
||||
LOG.exception(message)
|
||||
raise base.NetworkException(message)
|
||||
|
||||
def get_subnet(self, subnet_id):
|
||||
try:
|
||||
subnet = self.neutron_client.show_subnet(subnet_id)
|
||||
return utils.convert_subnet_dict_to_model(subnet)
|
||||
except neutron_client_exceptions.NotFound:
|
||||
message = _LE('Subnet not found '
|
||||
'(subnet id: {subnet_id}.').format(
|
||||
subnet_id=subnet_id)
|
||||
LOG.exception(message)
|
||||
raise base.SubnetNotFound(message)
|
||||
except Exception:
|
||||
message = _LE('Error retrieving subnet '
|
||||
'(subnet id: {subnet_id}.').format(
|
||||
subnet_id=subnet_id)
|
||||
LOG.exception(message)
|
||||
raise base.NetworkException(message)
|
||||
|
||||
return self._map_network_to_data_model(network)
|
||||
def get_port(self, port_id):
|
||||
try:
|
||||
port = self.neutron_client.show_port(port_id)
|
||||
return utils.convert_port_dict_to_model(port)
|
||||
except neutron_client_exceptions.NotFound:
|
||||
message = _LE('Port not found '
|
||||
'(port id: {port_id}.').format(
|
||||
port_id=port_id)
|
||||
LOG.exception(message)
|
||||
raise base.PortNotFound(message)
|
||||
except Exception:
|
||||
message = _LE('Error retrieving port '
|
||||
'(port id: {port_id}.').format(
|
||||
port_id=port_id)
|
||||
LOG.exception(message)
|
||||
raise base.NetworkException(message)
|
||||
|
66
octavia/network/drivers/neutron/utils.py
Normal file
66
octavia/network/drivers/neutron/utils.py
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright 2015 Rackspace
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from octavia.network import data_models as network_models
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def convert_subnet_dict_to_model(subnet_dict):
|
||||
subnet = subnet_dict.get('subnet') or subnet_dict
|
||||
return network_models.Subnet(id=subnet.get('id'), name=subnet.get('name'),
|
||||
network_id=subnet.get('network_id'),
|
||||
tenant_id=subnet.get('tenant_id'),
|
||||
gateway_ip=subnet.get('gateway_ip'),
|
||||
cidr=subnet.get('cidr'),
|
||||
ip_version=subnet.get('ip_version')
|
||||
)
|
||||
|
||||
|
||||
def convert_port_dict_to_model(port_dict):
|
||||
port = port_dict.get('port') or port_dict
|
||||
fixed_ips = [network_models.FixedIP(subnet_id=fixed_ip.get('subnet_id'),
|
||||
ip_address=fixed_ip.get('ip_address'))
|
||||
for fixed_ip in port.get('fixed_ips', [])]
|
||||
return network_models.Port(
|
||||
id=port.get('id'),
|
||||
name=port.get('name'),
|
||||
device_id=port.get('device_id'),
|
||||
device_owner=port.get('device_owner'),
|
||||
mac_address=port.get('mac_address'),
|
||||
network_id=port.get('network_id'),
|
||||
status=port.get('status'),
|
||||
tenant_id=port.get('tenant_id'),
|
||||
admin_state_up=port.get('admin_state_up'),
|
||||
fixed_ips=fixed_ips
|
||||
)
|
||||
|
||||
|
||||
def convert_network_dict_to_model(network_dict):
|
||||
nw = network_dict.get('network') or network_dict
|
||||
return network_models.Network(
|
||||
id=nw.get('id'),
|
||||
name=nw.get('name'),
|
||||
subnets=nw.get('subnets'),
|
||||
tenant_id=nw.get('tenant_id'),
|
||||
admin_state_up=nw.get('admin_state_up'),
|
||||
mtu=nw.get('mtu'),
|
||||
provider_network_type=nw.get('provider:network_type'),
|
||||
provider_physical_network=nw.get('provider:physical_network'),
|
||||
provider_segmentation_id=nw.get('provider:segmentation_id'),
|
||||
router_external=nw.get('router:external')
|
||||
)
|
@ -59,12 +59,12 @@ class NoopManager(object):
|
||||
self.networkconfigconfig[(amphora_id, network_id, ip_address)] = (
|
||||
amphora_id, network_id, ip_address, 'plug_network')
|
||||
|
||||
def unplug_network(self, amphora_id, network_id):
|
||||
def unplug_network(self, amphora_id, network_id, ip_address=None):
|
||||
LOG.debug("Network %s no-op, unplug_network amphora_id %s, "
|
||||
"network_id %s",
|
||||
self.__class__.__name__, amphora_id, network_id)
|
||||
self.networkconfigconfig[(amphora_id, network_id)] = (
|
||||
amphora_id, network_id, 'unplug_network')
|
||||
self.networkconfigconfig[(amphora_id, network_id, ip_address)] = (
|
||||
amphora_id, network_id, ip_address, 'unplug_network')
|
||||
|
||||
def get_plugged_networks(self, amphora_id):
|
||||
LOG.debug("Network %s no-op, get_plugged_networks amphora_id %s",
|
||||
@ -77,11 +77,20 @@ class NoopManager(object):
|
||||
self.__class__.__name__, load_balancer)
|
||||
self.networkconfigconfig[load_balancer] = (load_balancer, 'update_vip')
|
||||
|
||||
def get_network(self, network_id=None, subnet_id=None):
|
||||
def get_network(self, network_id):
|
||||
LOG.debug("Network %s no-op, get_network network_id %s",
|
||||
self.__class__.__name__, network_id)
|
||||
self.networkconfigconfig[network_id, subnet_id] = (
|
||||
network_id, subnet_id, 'get_network')
|
||||
self.networkconfigconfig[network_id] = (network_id, 'get_network')
|
||||
|
||||
def get_subnet(self, subnet_id):
|
||||
LOG.debug("Subnet %s no-op, get_subnet subnet_id %s",
|
||||
self.__class__.__name__, subnet_id)
|
||||
self.networkconfigconfig[subnet_id] = (subnet_id, 'get_subnet')
|
||||
|
||||
def get_port(self, port_id):
|
||||
LOG.debug("Port %s no-op, get_port port_id %s",
|
||||
self.__class__.__name__, port_id)
|
||||
self.networkconfigconfig[port_id] = (port_id, 'get_port')
|
||||
|
||||
|
||||
class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
||||
@ -104,8 +113,9 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
||||
def plug_network(self, amphora_id, network_id, ip_address=None):
|
||||
self.driver.plug_network(amphora_id, network_id, ip_address)
|
||||
|
||||
def unplug_network(self, amphora_id, network_id):
|
||||
self.driver.unplug_network(amphora_id, network_id)
|
||||
def unplug_network(self, amphora_id, network_id, ip_address=None):
|
||||
self.driver.unplug_network(amphora_id, network_id,
|
||||
ip_address=ip_address)
|
||||
|
||||
def get_plugged_networks(self, amphora_id):
|
||||
self.driver.get_plugged_networks(amphora_id)
|
||||
@ -113,5 +123,11 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
||||
def update_vip(self, load_balancer):
|
||||
self.driver.update_vip(load_balancer)
|
||||
|
||||
def get_network(self, network_id=None, subnet_id=None):
|
||||
self.driver.get_network(network_id, subnet_id)
|
||||
def get_network(self, network_id):
|
||||
self.driver.get_network(network_id)
|
||||
|
||||
def get_subnet(self, subnet_id):
|
||||
self.driver.get_subnet(subnet_id)
|
||||
|
||||
def get_port(self, port_id):
|
||||
self.driver.get_port(port_id)
|
@ -65,12 +65,12 @@ class TestNetworkTasks(base.TestCase):
|
||||
|
||||
def test_calculate_delta(self,
|
||||
mock_driver):
|
||||
EMPTY = []
|
||||
empty_deltas = [data_models.Delta(
|
||||
EMPTY = {}
|
||||
empty_deltas = {self.amphora_mock.id: data_models.Delta(
|
||||
amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=[])]
|
||||
delete_nics=[])}
|
||||
|
||||
def _interface(network_id):
|
||||
return [data_models.Interface(network_id=network_id)]
|
||||
@ -105,7 +105,8 @@ class TestNetworkTasks(base.TestCase):
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=_interface(2),
|
||||
delete_nics=[])
|
||||
self.assertEqual([ndm], net.execute(self.load_balancer_mock))
|
||||
self.assertEqual({self.amphora_mock.id: ndm},
|
||||
net.execute(self.load_balancer_mock))
|
||||
|
||||
mock_driver.get_network.assert_called_once_with(subnet_id=1)
|
||||
|
||||
@ -117,7 +118,8 @@ class TestNetworkTasks(base.TestCase):
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=_interface(2),
|
||||
delete_nics=_interface(3))
|
||||
self.assertEqual([ndm], net.execute(self.load_balancer_mock))
|
||||
self.assertEqual({self.amphora_mock.id: ndm},
|
||||
net.execute(self.load_balancer_mock))
|
||||
|
||||
pool_mock.members = []
|
||||
mock_driver.get_plugged_networks.return_value = _interface(2)
|
||||
@ -125,7 +127,8 @@ class TestNetworkTasks(base.TestCase):
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=_interface(2))
|
||||
self.assertEqual([ndm], net.execute(self.load_balancer_mock))
|
||||
self.assertEqual({self.amphora_mock.id: ndm},
|
||||
net.execute(self.load_balancer_mock))
|
||||
|
||||
def test_get_plumbed_networks(self,
|
||||
mock_driver):
|
||||
@ -232,32 +235,32 @@ class TestNetworkTasks(base.TestCase):
|
||||
|
||||
net = network_tasks.HandleNetworkDeltas()
|
||||
|
||||
net.execute([])
|
||||
net.execute({})
|
||||
self.assertFalse(mock_driver.plug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=[])
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
self.assertFalse(mock_driver.plug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=_interface(1),
|
||||
delete_nics=[])
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
mock_driver.plug_network.assert_called_once_with(COMPUTE_ID, 1)
|
||||
|
||||
# revert
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
self.assertFalse(mock_driver.unplug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=[])
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
self.assertFalse(mock_driver.unplug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
@ -270,36 +273,37 @@ class TestNetworkTasks(base.TestCase):
|
||||
|
||||
mock_driver.reset_mock()
|
||||
mock_driver.unplug_network.side_effect = TestException('test')
|
||||
self.assertRaises(TestException, net.revert, [delta])
|
||||
self.assertRaises(TestException, net.revert, mock.ANY,
|
||||
{self.amphora_mock.id: delta})
|
||||
mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
|
||||
|
||||
mock_driver.reset_mock()
|
||||
net.execute([])
|
||||
net.execute({})
|
||||
self.assertFalse(mock_driver.unplug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=[])
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
self.assertFalse(mock_driver.unplug_network.called)
|
||||
|
||||
delta = data_models.Delta(amphora_id=self.amphora_mock.id,
|
||||
compute_id=self.amphora_mock.compute_id,
|
||||
add_nics=[],
|
||||
delete_nics=_interface(1))
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
|
||||
|
||||
mock_driver.reset_mock()
|
||||
mock_driver.unplug_network.side_effect = net_base.NetworkNotFound
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
|
||||
|
||||
# Do a test with a general exception in case behavior changes
|
||||
mock_driver.reset_mock()
|
||||
mock_driver.unplug_network.side_effect = Exception()
|
||||
net.execute([delta])
|
||||
net.execute({self.amphora_mock.id: delta})
|
||||
mock_driver.unplug_network.assert_called_once_with(COMPUTE_ID, 1)
|
||||
|
||||
def test_plug_vip(self,
|
||||
|
@ -19,6 +19,7 @@ from novaclient.client import exceptions as nova_exceptions
|
||||
from octavia.common import constants
|
||||
from octavia.common import data_models
|
||||
from octavia.network import base as network_base
|
||||
from octavia.network import data_models as network_models
|
||||
from octavia.network.drivers.neutron import allowed_address_pairs
|
||||
from octavia.tests.common import data_model_helpers as dmh
|
||||
from octavia.tests.unit import base
|
||||
@ -29,17 +30,23 @@ class MockNovaInterface(object):
|
||||
port_id = None
|
||||
fixed_ips = []
|
||||
|
||||
|
||||
MOCK_NETWORK_ID = '1'
|
||||
MOCK_SUBNET_ID = '2'
|
||||
MOCK_PORT_ID = '3'
|
||||
MOCK_COMPUTE_ID = '4'
|
||||
MOCK_IP_ADDRESS = '10.0.0.1'
|
||||
MOCK_CIDR = '10.0.0.0/24'
|
||||
MOCK_MAC_ADDR = 'fe:16:3e:00:95:5c'
|
||||
MOCK_NOVA_INTERFACE = MockNovaInterface()
|
||||
MOCK_NOVA_INTERFACE.net_id = '1'
|
||||
MOCK_NOVA_INTERFACE.port_id = '2'
|
||||
MOCK_NOVA_INTERFACE.fixed_ips = [{'ip_address': '10.0.0.1', 'subnet_id': '10'}]
|
||||
MOCK_SUBNET = {'subnet': {'id': '10', 'network_id': '1'}}
|
||||
MOCK_SUBNET = {'subnet': {'id': MOCK_SUBNET_ID, 'network_id': MOCK_NETWORK_ID}}
|
||||
MOCK_NOVA_INTERFACE.net_id = MOCK_NETWORK_ID
|
||||
MOCK_NOVA_INTERFACE.port_id = MOCK_PORT_ID
|
||||
MOCK_NOVA_INTERFACE.fixed_ips = [{'ip_address': MOCK_IP_ADDRESS}]
|
||||
|
||||
MOCK_NEUTRON_PORT = {'port': {'network_id': '1',
|
||||
'id': '2',
|
||||
'fixed_ips': [{'ip_address': '10.0.0.1',
|
||||
'subnet_id': '10'}]}}
|
||||
MOCK_NEUTRON_PORT = {'port': {'network_id': MOCK_NETWORK_ID,
|
||||
'id': MOCK_PORT_ID,
|
||||
'fixed_ips': [{'ip_address': MOCK_IP_ADDRESS,
|
||||
'subnet_id': MOCK_SUBNET_ID}]}}
|
||||
|
||||
|
||||
class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
@ -70,8 +77,9 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
self.driver._check_extensions_loaded)
|
||||
|
||||
def test_port_to_vip(self):
|
||||
fake_lb_id = '4'
|
||||
vip = self.driver._port_to_vip(MOCK_NEUTRON_PORT, fake_lb_id)
|
||||
lb = dmh.generate_load_balancer_tree()
|
||||
lb.vip.subnet_id = MOCK_SUBNET_ID
|
||||
vip = self.driver._port_to_vip(MOCK_NEUTRON_PORT, lb)
|
||||
self.assertIsInstance(vip, data_models.Vip)
|
||||
self.assertEqual(
|
||||
MOCK_NEUTRON_PORT['port']['fixed_ips'][0]['ip_address'],
|
||||
@ -80,7 +88,7 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
MOCK_NEUTRON_PORT['port']['fixed_ips'][0]['subnet_id'],
|
||||
vip.subnet_id)
|
||||
self.assertEqual(MOCK_NEUTRON_PORT['port']['id'], vip.port_id)
|
||||
self.assertEqual(fake_lb_id, vip.load_balancer_id)
|
||||
self.assertEqual(lb.id, vip.load_balancer_id)
|
||||
|
||||
def test_nova_interface_to_octavia_interface(self):
|
||||
nova_interface = MockNovaInterface()
|
||||
@ -192,7 +200,8 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
self.driver.allocate_vip, fake_lb)
|
||||
show_port = self.driver.neutron_client.show_port
|
||||
show_port.return_value = MOCK_NEUTRON_PORT
|
||||
fake_lb_vip = data_models.Vip(port_id=MOCK_NEUTRON_PORT['port']['id'])
|
||||
fake_lb_vip = data_models.Vip(port_id=MOCK_NEUTRON_PORT['port']['id'],
|
||||
subnet_id=MOCK_SUBNET_ID)
|
||||
fake_lb = data_models.LoadBalancer(id='1', vip=fake_lb_vip)
|
||||
vip = self.driver.allocate_vip(fake_lb)
|
||||
self.assertIsInstance(vip, data_models.Vip)
|
||||
@ -203,7 +212,7 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
MOCK_NEUTRON_PORT['port']['fixed_ips'][0]['subnet_id'],
|
||||
vip.subnet_id)
|
||||
self.assertEqual(MOCK_NEUTRON_PORT['port']['id'], vip.port_id)
|
||||
self.assertIsNone(vip.load_balancer_id)
|
||||
self.assertEqual(fake_lb.id, vip.load_balancer_id)
|
||||
|
||||
create_port = self.driver.neutron_client.create_port
|
||||
create_port.return_value = MOCK_NEUTRON_PORT
|
||||
@ -219,7 +228,7 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
MOCK_NEUTRON_PORT['port']['fixed_ips'][0]['subnet_id'],
|
||||
vip.subnet_id)
|
||||
self.assertEqual(MOCK_NEUTRON_PORT['port']['id'], vip.port_id)
|
||||
self.assertIsNone(vip.load_balancer_id)
|
||||
self.assertEqual(fake_lb.id, vip.load_balancer_id)
|
||||
|
||||
def test_unplug_vip(self):
|
||||
lb = dmh.generate_load_balancer_tree()
|
||||
@ -372,3 +381,43 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||
self.driver.update_vip(lb)
|
||||
delete_rule.assert_called_once_with('rule-22')
|
||||
self.assertFalse(create_rule.called)
|
||||
|
||||
def test_get_network(self):
|
||||
show_network = self.driver.neutron_client.show_network
|
||||
show_network.return_value = {'network': {'id': MOCK_NETWORK_ID,
|
||||
'subnets': [MOCK_SUBNET_ID]}}
|
||||
network = self.driver.get_network(MOCK_NETWORK_ID)
|
||||
self.assertIsInstance(network, network_models.Network)
|
||||
self.assertEqual(MOCK_NETWORK_ID, network.id)
|
||||
self.assertEqual(1, len(network.subnets))
|
||||
self.assertEqual(MOCK_SUBNET_ID, network.subnets[0])
|
||||
|
||||
def test_get_subnet(self):
|
||||
show_subnet = self.driver.neutron_client.show_subnet
|
||||
show_subnet.return_value = {'subnet': {'id': MOCK_SUBNET_ID,
|
||||
'gateway_ip': MOCK_IP_ADDRESS,
|
||||
'cidr': MOCK_CIDR}}
|
||||
subnet = self.driver.get_subnet(MOCK_SUBNET_ID)
|
||||
self.assertIsInstance(subnet, network_models.Subnet)
|
||||
self.assertEqual(MOCK_SUBNET_ID, subnet.id)
|
||||
self.assertEqual(MOCK_IP_ADDRESS, subnet.gateway_ip)
|
||||
self.assertEqual(MOCK_CIDR, subnet.cidr)
|
||||
|
||||
def test_get_port(self):
|
||||
show_port = self.driver.neutron_client.show_port
|
||||
show_port.return_value = {'port': {'id': MOCK_PORT_ID,
|
||||
'mac_address': MOCK_MAC_ADDR,
|
||||
'network_id': MOCK_NETWORK_ID,
|
||||
'fixed_ips': [{
|
||||
'subnet_id': MOCK_SUBNET_ID,
|
||||
'ip_address': MOCK_IP_ADDRESS
|
||||
}]}}
|
||||
port = self.driver.get_port(MOCK_PORT_ID)
|
||||
self.assertIsInstance(port, network_models.Port)
|
||||
self.assertEqual(MOCK_PORT_ID, port.id)
|
||||
self.assertEqual(MOCK_MAC_ADDR, port.mac_address)
|
||||
self.assertEqual(MOCK_NETWORK_ID, port.network_id)
|
||||
self.assertEqual(1, len(port.fixed_ips))
|
||||
self.assertIsInstance(port.fixed_ips[0], network_models.FixedIP)
|
||||
self.assertEqual(MOCK_SUBNET_ID, port.fixed_ips[0].subnet_id)
|
||||
self.assertEqual(MOCK_IP_ADDRESS, port.fixed_ips[0].ip_address)
|
@ -40,6 +40,8 @@ class TestNoopNetworkDriver(base.TestCase):
|
||||
self.vip = models.Vip()
|
||||
self.vip.ip_address = "10.0.0.1"
|
||||
self.amphora_id = self.FAKE_UUID_1
|
||||
self.compute_id = self.FAKE_UUID_2
|
||||
self.subnet_id = self.FAKE_UUID_3
|
||||
|
||||
def test_allocate_vip(self):
|
||||
self.driver.allocate_vip(self.load_balancer)
|
||||
@ -78,11 +80,13 @@ class TestNoopNetworkDriver(base.TestCase):
|
||||
self.ip_address)])
|
||||
|
||||
def test_unplug_network(self):
|
||||
self.driver.unplug_network(self.amphora_id, self.network_id)
|
||||
self.assertEqual((self.amphora_id, self.network_id,
|
||||
self.driver.unplug_network(self.amphora_id, self.network_id,
|
||||
ip_address=self.ip_address)
|
||||
self.assertEqual((self.amphora_id, self.network_id, self.ip_address,
|
||||
'unplug_network'),
|
||||
self.driver.driver.networkconfigconfig[(
|
||||
self.amphora_id, self.network_id)])
|
||||
self.amphora_id, self.network_id,
|
||||
self.ip_address)])
|
||||
|
||||
def test_get_plugged_networks(self):
|
||||
self.driver.get_plugged_networks(self.amphora_id)
|
||||
@ -95,4 +99,25 @@ class TestNoopNetworkDriver(base.TestCase):
|
||||
self.assertEqual((self.load_balancer, 'update_vip'),
|
||||
self.driver.driver.networkconfigconfig[(
|
||||
self.load_balancer
|
||||
)])
|
||||
)])
|
||||
|
||||
def test_get_network(self):
|
||||
self.driver.get_network(self.network_id)
|
||||
self.assertEqual(
|
||||
(self.network_id, 'get_network'),
|
||||
self.driver.driver.networkconfigconfig[self.network_id]
|
||||
)
|
||||
|
||||
def test_get_subnet(self):
|
||||
self.driver.get_subnet(self.subnet_id)
|
||||
self.assertEqual(
|
||||
(self.subnet_id, 'get_subnet'),
|
||||
self.driver.driver.networkconfigconfig[self.subnet_id]
|
||||
)
|
||||
|
||||
def test_get_port(self):
|
||||
self.driver.get_port(self.port_id)
|
||||
self.assertEqual(
|
||||
(self.port_id, 'get_port'),
|
||||
self.driver.driver.networkconfigconfig[self.port_id]
|
||||
)
|
@ -84,6 +84,41 @@ New data models:
|
||||
* provider_physical_network
|
||||
* provider_segmentation_id
|
||||
* router_external
|
||||
* mtu
|
||||
|
||||
* class Subnet
|
||||
* id
|
||||
* name
|
||||
* network_id
|
||||
* tenant_id
|
||||
* gateway_ip
|
||||
* cidr
|
||||
* ip_version
|
||||
|
||||
* class Port
|
||||
* id
|
||||
* name
|
||||
* device_id
|
||||
* device_owner
|
||||
* mac_address
|
||||
* network_id
|
||||
* status
|
||||
* tenant_id
|
||||
* admin_state_up
|
||||
* fixed_ips - list of FixedIP objects
|
||||
|
||||
* FixedIP
|
||||
* subnet_id
|
||||
* ip_address
|
||||
|
||||
* AmphoraNetworkConfig
|
||||
* amphora - Amphora object
|
||||
* vip_subnet - Subnet object
|
||||
* vip_port - Port object
|
||||
* vrrp_subnet - Subnet object
|
||||
* vrrp_port - Port object
|
||||
* ha_subnet - Subnet object
|
||||
* ha_port - Port object
|
||||
|
||||
New Exceptions defined in the octavia.network package:
|
||||
|
||||
@ -97,6 +132,7 @@ New Exceptions defined in the octavia.network package:
|
||||
* UnplugNetworkException
|
||||
* VIPInUse
|
||||
* PortNotFound
|
||||
* SubnetNotFound
|
||||
* NetworkNotFound
|
||||
* VIPConfigurationNotFound
|
||||
* AmphoraNotFound
|
||||
@ -179,14 +215,27 @@ class AbstractNetworkDriver
|
||||
of the passed in loadbalancer
|
||||
* loadbalancer: instance of a data_models.LoadBalancer
|
||||
|
||||
* get_network(network_id=None, subnet_id=None):
|
||||
* get_network(network_id):
|
||||
|
||||
* Retrieves the network from network_id or subnet_id
|
||||
* Retrieves the network from network_id
|
||||
* network_id = id of an network to retrieve
|
||||
* subnet_id = id of an subnet to retrieve network
|
||||
* returns = Network data model
|
||||
* raises NetworkException, NetworkNotFound
|
||||
|
||||
* get_subnet(subnet_id):
|
||||
|
||||
* Retrieves the subnet from subnet_id
|
||||
* subnet_id = id of a subnet to retrieve
|
||||
* returns = Subnet data model
|
||||
* raises NetworkException, SubnetNotFound
|
||||
|
||||
* get_port(port_id):
|
||||
|
||||
* Retrieves the port from port_id
|
||||
* port_id = id of a port to retrieve
|
||||
* returns = Port data model
|
||||
* raises NetworkException, PortNotFound
|
||||
|
||||
Alternatives
|
||||
------------
|
||||
|
||||
@ -199,16 +248,11 @@ Data model impact
|
||||
* The Interface data model defined above will just be a class. We may later
|
||||
decide that it needs to be stored in the database, but we can optimize on
|
||||
that in a later review if needed.
|
||||
* Remove floating_ip_id from VIP model and migration
|
||||
* Remove floating_ip_network_id from VIP model and migration
|
||||
* Rename net_port_id to just port_id in VIP model and migration
|
||||
* Rename subnet_id to network_id in VIP model and migration
|
||||
|
||||
REST API impact
|
||||
---------------
|
||||
|
||||
* Remove floating_ip_id from WSME VIP type
|
||||
* Remove floating_ip_network_id from WSME VIP type
|
||||
None
|
||||
|
||||
Security impact
|
||||
---------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user