Add fullstack resources for linuxbridge agent
This patch adds resources, fixtures and base test_connectivity tests for host with linuxbridge agent. Model of host with linuxbridge agent is made in separate namespace named "host-XXX". It has got connectivity with rabbit via ovs port. Same port is used also to provide connectivity with different "hosts" Co-Authored-By: Mathieu Rohon <mathieu.rohon@gmail.com> Change-Id: I6230d8d09f77bd20674bf6c3be69fbc1627d66f8 Closes-bug: #1518675
This commit is contained in:
parent
21d139d441
commit
2254acef06
@ -225,9 +225,12 @@ neutron/tests/fullstack/test_connectivity.py.
|
|||||||
|
|
||||||
Full stack testing can simulate multi node testing by starting an agent
|
Full stack testing can simulate multi node testing by starting an agent
|
||||||
multiple times. Specifically, each node would have its own copy of the
|
multiple times. Specifically, each node would have its own copy of the
|
||||||
OVS/DHCP/L3 agents, all configured with the same "host" value. Each OVS agent
|
OVS/LinuxBridge/DHCP/L3 agents, all configured with the same "host" value.
|
||||||
is connected to its own pair of br-int/br-ex, and those bridges are then
|
Each OVS agent is connected to its own pair of br-int/br-ex, and those bridges
|
||||||
interconnected.
|
are then interconnected.
|
||||||
|
For LinuxBridge agent each agent is started in its own namespace, called
|
||||||
|
"host-<some_random_value>". Such namespaces are connected with OVS "central"
|
||||||
|
bridge to eachother.
|
||||||
|
|
||||||
.. image:: images/fullstack_multinode_simulation.png
|
.. image:: images/fullstack_multinode_simulation.png
|
||||||
|
|
||||||
|
@ -21,3 +21,5 @@ VXLAN_MCAST = 'multicast_flooding'
|
|||||||
VXLAN_UCAST = 'unicast_flooding'
|
VXLAN_UCAST = 'unicast_flooding'
|
||||||
|
|
||||||
EXTENSION_DRIVER_TYPE = 'linuxbridge'
|
EXTENSION_DRIVER_TYPE = 'linuxbridge'
|
||||||
|
|
||||||
|
RESOURCE_ID_LENGTH = 11
|
||||||
|
@ -128,11 +128,13 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
|
|||||||
return None
|
return None
|
||||||
return self.bridge_mappings.get(physical_network)
|
return self.bridge_mappings.get(physical_network)
|
||||||
|
|
||||||
def get_bridge_name(self, network_id):
|
@staticmethod
|
||||||
|
def get_bridge_name(network_id):
|
||||||
if not network_id:
|
if not network_id:
|
||||||
LOG.warning(_LW("Invalid Network ID, will lead to incorrect "
|
LOG.warning(_LW("Invalid Network ID, will lead to incorrect "
|
||||||
"bridge name"))
|
"bridge name"))
|
||||||
bridge_name = BRIDGE_NAME_PREFIX + network_id[0:11]
|
bridge_name = BRIDGE_NAME_PREFIX + \
|
||||||
|
network_id[:lconst.RESOURCE_ID_LENGTH]
|
||||||
return bridge_name
|
return bridge_name
|
||||||
|
|
||||||
def get_subinterface_name(self, physical_interface, vlan_id):
|
def get_subinterface_name(self, physical_interface, vlan_id):
|
||||||
@ -142,11 +144,13 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
|
|||||||
subinterface_name = '%s.%s' % (physical_interface, vlan_id)
|
subinterface_name = '%s.%s' % (physical_interface, vlan_id)
|
||||||
return subinterface_name
|
return subinterface_name
|
||||||
|
|
||||||
def get_tap_device_name(self, interface_id):
|
@staticmethod
|
||||||
|
def get_tap_device_name(interface_id):
|
||||||
if not interface_id:
|
if not interface_id:
|
||||||
LOG.warning(_LW("Invalid Interface ID, will lead to incorrect "
|
LOG.warning(_LW("Invalid Interface ID, will lead to incorrect "
|
||||||
"tap device name"))
|
"tap device name"))
|
||||||
tap_device_name = constants.TAP_DEVICE_PREFIX + interface_id[0:11]
|
tap_device_name = constants.TAP_DEVICE_PREFIX + \
|
||||||
|
interface_id[:lconst.RESOURCE_ID_LENGTH]
|
||||||
return tap_device_name
|
return tap_device_name
|
||||||
|
|
||||||
def get_vxlan_device_name(self, segmentation_id):
|
def get_vxlan_device_name(self, segmentation_id):
|
||||||
|
@ -39,6 +39,8 @@ from neutron.agent.linux import ip_lib
|
|||||||
from neutron.agent.linux import utils
|
from neutron.agent.linux import utils
|
||||||
from neutron.common import constants as n_const
|
from neutron.common import constants as n_const
|
||||||
from neutron.db import db_base_plugin_common
|
from neutron.db import db_base_plugin_common
|
||||||
|
from neutron.plugins.ml2.drivers.linuxbridge.agent import \
|
||||||
|
linuxbridge_neutron_agent as linuxbridge_agent
|
||||||
from neutron.tests import base as tests_base
|
from neutron.tests import base as tests_base
|
||||||
from neutron.tests.common import base as common_base
|
from neutron.tests.common import base as common_base
|
||||||
from neutron.tests import tools
|
from neutron.tests import tools
|
||||||
@ -47,11 +49,18 @@ UNDEFINED = object()
|
|||||||
|
|
||||||
NS_PREFIX = 'test-'
|
NS_PREFIX = 'test-'
|
||||||
BR_PREFIX = 'test-br'
|
BR_PREFIX = 'test-br'
|
||||||
PORT_PREFIX = 'test-port'
|
PORT_PREFIX = 'port'
|
||||||
VETH0_PREFIX = 'test-veth0'
|
VETH0_PREFIX = 'test-veth0'
|
||||||
VETH1_PREFIX = 'test-veth1'
|
VETH1_PREFIX = 'test-veth1'
|
||||||
PATCH_PREFIX = 'patch'
|
PATCH_PREFIX = 'patch'
|
||||||
|
|
||||||
|
# port name should be shorter than DEVICE_NAME_MAX_LEN because if this
|
||||||
|
# port is used to provide vlan connection between two linuxbridge
|
||||||
|
# agents then place for vlan ID is also required, Vlan ID can take max 4 digits
|
||||||
|
# and there is also additional "." in device name so it will in overall gives
|
||||||
|
# DEVICE_NAME_MAX_LEN = 15 chars
|
||||||
|
LB_DEVICE_NAME_MAX_LEN = 10
|
||||||
|
|
||||||
SS_SOURCE_PORT_PATTERN = re.compile(
|
SS_SOURCE_PORT_PATTERN = re.compile(
|
||||||
r'^.*\s+\d+\s+.*:(?P<port>\d+)\s+[0-9:].*')
|
r'^.*\s+\d+\s+.*:(?P<port>\d+)\s+[0-9:].*')
|
||||||
|
|
||||||
@ -473,7 +482,7 @@ class VethFixture(fixtures.Fixture):
|
|||||||
"""Create a veth.
|
"""Create a veth.
|
||||||
|
|
||||||
:ivar ports: created veth ports
|
:ivar ports: created veth ports
|
||||||
:type ports: IPDevice 2-uplet
|
:type ports: tuple of 2 IPDevice
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
@ -508,6 +517,32 @@ class VethFixture(fixtures.Fixture):
|
|||||||
tools.fail('%s is not a valid VethFixture veth endpoint' % name)
|
tools.fail('%s is not a valid VethFixture veth endpoint' % name)
|
||||||
|
|
||||||
|
|
||||||
|
class NamedVethFixture(VethFixture):
|
||||||
|
"""Create a veth with at least one specified name of a device
|
||||||
|
|
||||||
|
:ivar ports: created veth ports
|
||||||
|
:type ports: tuple of 2 IPDevice
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, veth0_prefix=VETH0_PREFIX, veth1_prefix=VETH1_PREFIX):
|
||||||
|
super(NamedVethFixture, self).__init__()
|
||||||
|
self.veth0_name = self.get_veth_name(veth0_prefix)
|
||||||
|
self.veth1_name = self.get_veth_name(veth1_prefix)
|
||||||
|
|
||||||
|
def _setUp(self):
|
||||||
|
ip_wrapper = ip_lib.IPWrapper()
|
||||||
|
self.ports = ip_wrapper.add_veth(self.veth0_name, self.veth1_name)
|
||||||
|
self.addCleanup(self.destroy)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_veth_name(name):
|
||||||
|
if name.startswith(VETH0_PREFIX):
|
||||||
|
return tests_base.get_rand_device_name(VETH0_PREFIX)
|
||||||
|
if name.startswith(VETH1_PREFIX):
|
||||||
|
return tests_base.get_rand_device_name(VETH1_PREFIX)
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
class PortFixture(fixtures.Fixture):
|
class PortFixture(fixtures.Fixture):
|
||||||
"""Create a port.
|
"""Create a port.
|
||||||
@ -541,7 +576,7 @@ class PortFixture(fixtures.Fixture):
|
|||||||
if isinstance(bridge, ovs_lib.OVSBridge):
|
if isinstance(bridge, ovs_lib.OVSBridge):
|
||||||
return OVSPortFixture(bridge, namespace, mac, port_id)
|
return OVSPortFixture(bridge, namespace, mac, port_id)
|
||||||
if isinstance(bridge, bridge_lib.BridgeDevice):
|
if isinstance(bridge, bridge_lib.BridgeDevice):
|
||||||
return LinuxBridgePortFixture(bridge, namespace)
|
return LinuxBridgePortFixture(bridge, namespace, mac, port_id)
|
||||||
if isinstance(bridge, VethBridge):
|
if isinstance(bridge, VethBridge):
|
||||||
return VethPortFixture(bridge, namespace)
|
return VethPortFixture(bridge, namespace)
|
||||||
tools.fail('Unexpected bridge type: %s' % type(bridge))
|
tools.fail('Unexpected bridge type: %s' % type(bridge))
|
||||||
@ -578,7 +613,13 @@ class OVSPortFixture(PortFixture):
|
|||||||
interface_config.register_opts(interface.OPTS)
|
interface_config.register_opts(interface.OPTS)
|
||||||
ovs_interface = interface.OVSInterfaceDriver(interface_config)
|
ovs_interface = interface.OVSInterfaceDriver(interface_config)
|
||||||
|
|
||||||
port_name = tests_base.get_rand_device_name(PORT_PREFIX)
|
# because in some tests this port can be used to providing connection
|
||||||
|
# between linuxbridge agents and vlan_id can be also added to this
|
||||||
|
# device name it has to be max LB_DEVICE_NAME_MAX_LEN long
|
||||||
|
port_name = tests_base.get_rand_name(
|
||||||
|
LB_DEVICE_NAME_MAX_LEN,
|
||||||
|
PORT_PREFIX
|
||||||
|
)
|
||||||
ovs_interface.plug_new(
|
ovs_interface.plug_new(
|
||||||
None,
|
None,
|
||||||
self.port_id,
|
self.port_id,
|
||||||
@ -598,22 +639,44 @@ class LinuxBridgeFixture(fixtures.Fixture):
|
|||||||
:ivar namespace: created bridge namespace
|
:ivar namespace: created bridge namespace
|
||||||
:type namespace: str
|
:type namespace: str
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, prefix=BR_PREFIX, namespace=UNDEFINED,
|
||||||
def __init__(self, prefix=BR_PREFIX, namespace=UNDEFINED):
|
prefix_is_full_name=False):
|
||||||
super(LinuxBridgeFixture, self).__init__()
|
super(LinuxBridgeFixture, self).__init__()
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
|
self.prefix_is_full_name = prefix_is_full_name
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
if self.namespace is UNDEFINED:
|
if self.namespace is UNDEFINED:
|
||||||
self.namespace = self.useFixture(NamespaceFixture()).name
|
self.namespace = self.useFixture(NamespaceFixture()).name
|
||||||
self.bridge = common_base.create_resource(
|
self.bridge = self._create_bridge()
|
||||||
self.prefix,
|
self.addCleanup(self.safe_delete)
|
||||||
bridge_lib.BridgeDevice.addbr,
|
|
||||||
namespace=self.namespace)
|
|
||||||
self.addCleanup(self.bridge.delbr)
|
|
||||||
self.bridge.link.set_up()
|
self.bridge.link.set_up()
|
||||||
self.addCleanup(self.bridge.link.set_down)
|
self.addCleanup(self.safe_set_down)
|
||||||
|
|
||||||
|
def safe_set_down(self):
|
||||||
|
try:
|
||||||
|
self.bridge.link.set_down()
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def safe_delete(self):
|
||||||
|
try:
|
||||||
|
self.bridge.delbr()
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _create_bridge(self):
|
||||||
|
if self.prefix_is_full_name:
|
||||||
|
return bridge_lib.BridgeDevice.addbr(
|
||||||
|
name=self.prefix,
|
||||||
|
namespace=self.namespace
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return common_base.create_resource(
|
||||||
|
self.prefix,
|
||||||
|
bridge_lib.BridgeDevice.addbr,
|
||||||
|
namespace=self.namespace)
|
||||||
|
|
||||||
|
|
||||||
class LinuxBridgePortFixture(PortFixture):
|
class LinuxBridgePortFixture(PortFixture):
|
||||||
@ -625,12 +688,29 @@ class LinuxBridgePortFixture(PortFixture):
|
|||||||
:type br_port: IPDevice
|
:type br_port: IPDevice
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bridge, namespace=None, mac=None, port_id=None):
|
||||||
|
super(LinuxBridgePortFixture, self).__init__(
|
||||||
|
bridge, namespace, mac, port_id)
|
||||||
|
# we need to override port_id value here because in Port() class it is
|
||||||
|
# always generated as random. In LinuxBridgePortFixture we need to have
|
||||||
|
# it empty if it was not give because then proper veth_pair will be
|
||||||
|
# created (for example in some functional tests)
|
||||||
|
self.port_id = port_id
|
||||||
|
|
||||||
def _create_bridge_fixture(self):
|
def _create_bridge_fixture(self):
|
||||||
return LinuxBridgeFixture()
|
return LinuxBridgeFixture()
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
super(LinuxBridgePortFixture, self)._setUp()
|
super(LinuxBridgePortFixture, self)._setUp()
|
||||||
self.port, self.br_port = self.useFixture(VethFixture()).ports
|
br_port_name = self._get_port_name()
|
||||||
|
if br_port_name:
|
||||||
|
self.br_port, self.port = self.useFixture(
|
||||||
|
NamedVethFixture(veth0_prefix=br_port_name)).ports
|
||||||
|
else:
|
||||||
|
self.br_port, self.port = self.useFixture(VethFixture()).ports
|
||||||
|
|
||||||
|
if self.mac:
|
||||||
|
self.port.link.set_address(self.mac)
|
||||||
|
|
||||||
# bridge side
|
# bridge side
|
||||||
br_ip_wrapper = ip_lib.IPWrapper(self.bridge.namespace)
|
br_ip_wrapper = ip_lib.IPWrapper(self.bridge.namespace)
|
||||||
@ -643,6 +723,12 @@ class LinuxBridgePortFixture(PortFixture):
|
|||||||
ns_ip_wrapper.add_device_to_namespace(self.port)
|
ns_ip_wrapper.add_device_to_namespace(self.port)
|
||||||
self.port.link.set_up()
|
self.port.link.set_up()
|
||||||
|
|
||||||
|
def _get_port_name(self):
|
||||||
|
if self.port_id:
|
||||||
|
return linuxbridge_agent.LinuxBridgeManager.get_tap_device_name(
|
||||||
|
self.port_id)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class VethBridge(object):
|
class VethBridge(object):
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class NeutronConfigFixture(ConfigFixture):
|
|||||||
'oslo_messaging_rabbit': {
|
'oslo_messaging_rabbit': {
|
||||||
'rabbit_userid': rabbitmq_environment.user,
|
'rabbit_userid': rabbitmq_environment.user,
|
||||||
'rabbit_password': rabbitmq_environment.password,
|
'rabbit_password': rabbitmq_environment.password,
|
||||||
'rabbit_hosts': '127.0.0.1',
|
'rabbit_hosts': rabbitmq_environment.host,
|
||||||
'rabbit_virtual_host': rabbitmq_environment.vhost,
|
'rabbit_virtual_host': rabbitmq_environment.vhost,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -114,14 +114,10 @@ class ML2ConfigFixture(ConfigFixture):
|
|||||||
super(ML2ConfigFixture, self).__init__(
|
super(ML2ConfigFixture, self).__init__(
|
||||||
env_desc, host_desc, temp_dir, base_filename='ml2_conf.ini')
|
env_desc, host_desc, temp_dir, base_filename='ml2_conf.ini')
|
||||||
|
|
||||||
mechanism_drivers = 'openvswitch'
|
|
||||||
if self.env_desc.l2_pop:
|
|
||||||
mechanism_drivers += ',l2population'
|
|
||||||
|
|
||||||
self.config.update({
|
self.config.update({
|
||||||
'ml2': {
|
'ml2': {
|
||||||
'tenant_network_types': tenant_network_types,
|
'tenant_network_types': tenant_network_types,
|
||||||
'mechanism_drivers': mechanism_drivers,
|
'mechanism_drivers': self.mechanism_drivers,
|
||||||
},
|
},
|
||||||
'ml2_type_vlan': {
|
'ml2_type_vlan': {
|
||||||
'network_vlan_ranges': 'physnet1:1000:2999',
|
'network_vlan_ranges': 'physnet1:1000:2999',
|
||||||
@ -138,6 +134,16 @@ class ML2ConfigFixture(ConfigFixture):
|
|||||||
self.config['ml2']['extension_drivers'] =\
|
self.config['ml2']['extension_drivers'] =\
|
||||||
qos_ext.QOS_EXT_DRIVER_ALIAS
|
qos_ext.QOS_EXT_DRIVER_ALIAS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mechanism_drivers(self):
|
||||||
|
mechanism_drivers = set(['openvswitch'])
|
||||||
|
for host in self.host_desc:
|
||||||
|
if host.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
||||||
|
mechanism_drivers.add('linuxbridge')
|
||||||
|
if self.env_desc.l2_pop:
|
||||||
|
mechanism_drivers.add('l2population')
|
||||||
|
return ','.join(mechanism_drivers)
|
||||||
|
|
||||||
|
|
||||||
class OVSConfigFixture(ConfigFixture):
|
class OVSConfigFixture(ConfigFixture):
|
||||||
|
|
||||||
@ -205,12 +211,59 @@ class OVSConfigFixture(ConfigFixture):
|
|||||||
return self.config.ovs.tunnel_bridge
|
return self.config.ovs.tunnel_bridge
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxBridgeConfigFixture(ConfigFixture):
|
||||||
|
|
||||||
|
def __init__(self, env_desc, host_desc, temp_dir, local_ip,
|
||||||
|
physical_device_name):
|
||||||
|
super(LinuxBridgeConfigFixture, self).__init__(
|
||||||
|
env_desc, host_desc, temp_dir,
|
||||||
|
base_filename="linuxbridge_agent.ini"
|
||||||
|
)
|
||||||
|
self.config.update({
|
||||||
|
'VXLAN': {
|
||||||
|
'enable_vxlan': str(self.env_desc.tunneling_enabled),
|
||||||
|
'local_ip': local_ip,
|
||||||
|
'l2_population': str(self.env_desc.l2_pop),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if self.env_desc.tunneling_enabled:
|
||||||
|
self.config.update({
|
||||||
|
'LINUX_BRIDGE': {
|
||||||
|
'bridge_mappings': self._generate_bridge_mappings(
|
||||||
|
physical_device_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
self.config.update({
|
||||||
|
'LINUX_BRIDGE': {
|
||||||
|
'physical_interface_mappings':
|
||||||
|
self._generate_bridge_mappings(
|
||||||
|
physical_device_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
def _generate_bridge_mappings(self, device_name):
|
||||||
|
return 'physnet1:%s' % device_name
|
||||||
|
|
||||||
|
|
||||||
class L3ConfigFixture(ConfigFixture):
|
class L3ConfigFixture(ConfigFixture):
|
||||||
|
|
||||||
def __init__(self, env_desc, host_desc, temp_dir, integration_bridge):
|
def __init__(self, env_desc, host_desc, temp_dir, integration_bridge=None):
|
||||||
super(L3ConfigFixture, self).__init__(
|
super(L3ConfigFixture, self).__init__(
|
||||||
env_desc, host_desc, temp_dir, base_filename='l3_agent.ini')
|
env_desc, host_desc, temp_dir, base_filename='l3_agent.ini')
|
||||||
|
if host_desc.l2_agent_type == constants.AGENT_TYPE_OVS:
|
||||||
|
self._prepare_config_with_ovs_agent(integration_bridge)
|
||||||
|
elif host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
||||||
|
self._prepare_config_with_linuxbridge_agent()
|
||||||
|
self.config['DEFAULT'].update({
|
||||||
|
'debug': 'True',
|
||||||
|
'verbose': 'True',
|
||||||
|
'test_namespace_suffix': self._generate_namespace_suffix(),
|
||||||
|
})
|
||||||
|
|
||||||
|
def _prepare_config_with_ovs_agent(self, integration_bridge):
|
||||||
self.config.update({
|
self.config.update({
|
||||||
'DEFAULT': {
|
'DEFAULT': {
|
||||||
'l3_agent_manager': ('neutron.agent.l3_agent.'
|
'l3_agent_manager': ('neutron.agent.l3_agent.'
|
||||||
@ -219,9 +272,14 @@ class L3ConfigFixture(ConfigFixture):
|
|||||||
'OVSInterfaceDriver'),
|
'OVSInterfaceDriver'),
|
||||||
'ovs_integration_bridge': integration_bridge,
|
'ovs_integration_bridge': integration_bridge,
|
||||||
'external_network_bridge': self._generate_external_bridge(),
|
'external_network_bridge': self._generate_external_bridge(),
|
||||||
'debug': 'True',
|
}
|
||||||
'verbose': 'True',
|
})
|
||||||
'test_namespace_suffix': self._generate_namespace_suffix(),
|
|
||||||
|
def _prepare_config_with_linuxbridge_agent(self):
|
||||||
|
self.config.update({
|
||||||
|
'DEFAULT': {
|
||||||
|
'interface_driver': ('neutron.agent.linux.interface.'
|
||||||
|
'BridgeInterfaceDriver'),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -19,8 +19,12 @@ import netaddr
|
|||||||
from neutronclient.common import exceptions as nc_exc
|
from neutronclient.common import exceptions as nc_exc
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from neutron.agent.linux import ip_lib
|
||||||
from neutron.agent.linux import utils
|
from neutron.agent.linux import utils
|
||||||
|
from neutron.common import constants
|
||||||
from neutron.common import utils as common_utils
|
from neutron.common import utils as common_utils
|
||||||
|
from neutron.plugins.ml2.drivers.linuxbridge.agent import \
|
||||||
|
linuxbridge_neutron_agent as lb_agent
|
||||||
from neutron.tests.common import net_helpers
|
from neutron.tests.common import net_helpers
|
||||||
from neutron.tests.fullstack.resources import config
|
from neutron.tests.fullstack.resources import config
|
||||||
from neutron.tests.fullstack.resources import process
|
from neutron.tests.fullstack.resources import process
|
||||||
@ -35,6 +39,7 @@ class EnvironmentDescription(object):
|
|||||||
self.network_type = network_type
|
self.network_type = network_type
|
||||||
self.l2_pop = l2_pop
|
self.l2_pop = l2_pop
|
||||||
self.qos = qos
|
self.qos = qos
|
||||||
|
self.network_range = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tunneling_enabled(self):
|
def tunneling_enabled(self):
|
||||||
@ -47,7 +52,9 @@ class HostDescription(object):
|
|||||||
What agents should the host spawn? What mode should each agent operate
|
What agents should the host spawn? What mode should each agent operate
|
||||||
under?
|
under?
|
||||||
"""
|
"""
|
||||||
def __init__(self, l3_agent=False, of_interface='ovs-ofctl'):
|
def __init__(self, l3_agent=False, of_interface='ovs-ofctl',
|
||||||
|
l2_agent_type=constants.AGENT_TYPE_OVS):
|
||||||
|
self.l2_agent_type = l2_agent_type
|
||||||
self.l3_agent = l3_agent
|
self.l3_agent = l3_agent
|
||||||
self.of_interface = of_interface
|
self.of_interface = of_interface
|
||||||
|
|
||||||
@ -75,12 +82,29 @@ class Host(fixtures.Fixture):
|
|||||||
self.test_name = test_name
|
self.test_name = test_name
|
||||||
self.neutron_config = neutron_config
|
self.neutron_config = neutron_config
|
||||||
# Use reserved class E addresses
|
# Use reserved class E addresses
|
||||||
self.local_ip = self.get_random_ip('240.0.0.1', '255.255.255.254')
|
self.local_ip = self.allocate_local_ip()
|
||||||
self.central_data_bridge = central_data_bridge
|
self.central_data_bridge = central_data_bridge
|
||||||
self.central_external_bridge = central_external_bridge
|
self.central_external_bridge = central_external_bridge
|
||||||
|
self.host_namespace = None
|
||||||
self.agents = {}
|
self.agents = {}
|
||||||
|
# we need to cache already created "per network" bridges if linuxbridge
|
||||||
|
# agent is used on host:
|
||||||
|
self.network_bridges = {}
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
|
if self.host_desc.l2_agent_type == constants.AGENT_TYPE_OVS:
|
||||||
|
self.setup_host_with_ovs_agent()
|
||||||
|
elif self.host_desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
||||||
|
self.setup_host_with_linuxbridge_agent()
|
||||||
|
if self.host_desc.l3_agent:
|
||||||
|
self.l3_agent = self.useFixture(
|
||||||
|
process.L3AgentFixture(
|
||||||
|
self.env_desc, self.host_desc,
|
||||||
|
self.test_name,
|
||||||
|
self.neutron_config,
|
||||||
|
self.l3_agent_cfg_fixture))
|
||||||
|
|
||||||
|
def setup_host_with_ovs_agent(self):
|
||||||
agent_cfg_fixture = config.OVSConfigFixture(
|
agent_cfg_fixture = config.OVSConfigFixture(
|
||||||
self.env_desc, self.host_desc, self.neutron_config.temp_dir,
|
self.env_desc, self.host_desc, self.neutron_config.temp_dir,
|
||||||
self.local_ip)
|
self.local_ip)
|
||||||
@ -103,21 +127,62 @@ class Host(fixtures.Fixture):
|
|||||||
self.test_name, self.neutron_config, agent_cfg_fixture))
|
self.test_name, self.neutron_config, agent_cfg_fixture))
|
||||||
|
|
||||||
if self.host_desc.l3_agent:
|
if self.host_desc.l3_agent:
|
||||||
l3_agent_cfg_fixture = self.useFixture(
|
self.l3_agent_cfg_fixture = self.useFixture(
|
||||||
config.L3ConfigFixture(
|
config.L3ConfigFixture(
|
||||||
self.env_desc, self.host_desc,
|
self.env_desc, self.host_desc,
|
||||||
self.neutron_config.temp_dir,
|
self.neutron_config.temp_dir,
|
||||||
self.ovs_agent.agent_cfg_fixture.get_br_int_name()))
|
self.ovs_agent.agent_cfg_fixture.get_br_int_name()))
|
||||||
br_ex = self.useFixture(
|
br_ex = self.useFixture(
|
||||||
net_helpers.OVSBridgeFixture(
|
net_helpers.OVSBridgeFixture(
|
||||||
l3_agent_cfg_fixture.get_external_bridge())).bridge
|
self.l3_agent_cfg_fixture.get_external_bridge())).bridge
|
||||||
self.connect_to_external_network(br_ex)
|
self.connect_to_external_network(br_ex)
|
||||||
self.l3_agent = self.useFixture(
|
|
||||||
process.L3AgentFixture(
|
def setup_host_with_linuxbridge_agent(self):
|
||||||
|
#First we need to provide connectivity for agent to prepare proper
|
||||||
|
#bridge mappings in agent's config:
|
||||||
|
self.host_namespace = self.useFixture(
|
||||||
|
net_helpers.NamespaceFixture(prefix="host-")
|
||||||
|
).name
|
||||||
|
|
||||||
|
self.connect_namespace_to_control_network()
|
||||||
|
|
||||||
|
agent_cfg_fixture = config.LinuxBridgeConfigFixture(
|
||||||
|
self.env_desc, self.host_desc,
|
||||||
|
self.neutron_config.temp_dir,
|
||||||
|
self.local_ip,
|
||||||
|
physical_device_name=self.host_port.name
|
||||||
|
)
|
||||||
|
self.useFixture(agent_cfg_fixture)
|
||||||
|
|
||||||
|
self.linuxbridge_agent = self.useFixture(
|
||||||
|
process.LinuxBridgeAgentFixture(
|
||||||
|
self.env_desc, self.host_desc,
|
||||||
|
self.test_name, self.neutron_config, agent_cfg_fixture,
|
||||||
|
namespace=self.host_namespace
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.host_desc.l3_agent:
|
||||||
|
self.l3_agent_cfg_fixture = self.useFixture(
|
||||||
|
config.L3ConfigFixture(
|
||||||
self.env_desc, self.host_desc,
|
self.env_desc, self.host_desc,
|
||||||
self.test_name,
|
self.neutron_config.temp_dir))
|
||||||
self.neutron_config,
|
|
||||||
l3_agent_cfg_fixture))
|
def _connect_ovs_port(self, cidr_address):
|
||||||
|
ovs_device = self.useFixture(
|
||||||
|
net_helpers.OVSPortFixture(
|
||||||
|
bridge=self.central_data_bridge,
|
||||||
|
namespace=self.host_namespace)).port
|
||||||
|
# NOTE: This sets an IP address on the host's root namespace
|
||||||
|
# which is cleaned up when the device is deleted.
|
||||||
|
ovs_device.addr.add(cidr_address)
|
||||||
|
return ovs_device
|
||||||
|
|
||||||
|
def connect_namespace_to_control_network(self):
|
||||||
|
self.host_port = self._connect_ovs_port(
|
||||||
|
common_utils.ip_to_cidr(self.local_ip, 24)
|
||||||
|
)
|
||||||
|
self.host_port.link.set_up()
|
||||||
|
|
||||||
def connect_to_internal_network_via_tunneling(self):
|
def connect_to_internal_network_via_tunneling(self):
|
||||||
veth_1, veth_2 = self.useFixture(
|
veth_1, veth_2 = self.useFixture(
|
||||||
@ -140,6 +205,30 @@ class Host(fixtures.Fixture):
|
|||||||
net_helpers.create_patch_ports(
|
net_helpers.create_patch_ports(
|
||||||
self.central_external_bridge, host_external_bridge)
|
self.central_external_bridge, host_external_bridge)
|
||||||
|
|
||||||
|
def allocate_local_ip(self):
|
||||||
|
if not self.env_desc.network_range:
|
||||||
|
return self.get_random_ip('240.0.0.1', '240.255.255.254')
|
||||||
|
return self.get_random_ip(
|
||||||
|
str(self.env_desc.network_range[2]),
|
||||||
|
str(self.env_desc.network_range[-1])
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_bridge(self, network_id):
|
||||||
|
if "ovs" in self.agents.keys():
|
||||||
|
return self.ovs_agent.br_int
|
||||||
|
elif "linuxbridge" in self.agents.keys():
|
||||||
|
bridge = self.network_bridges.get(network_id, None)
|
||||||
|
if not bridge:
|
||||||
|
br_prefix = lb_agent.LinuxBridgeManager.get_bridge_name(
|
||||||
|
network_id)
|
||||||
|
bridge = self.useFixture(
|
||||||
|
net_helpers.LinuxBridgeFixture(
|
||||||
|
prefix=br_prefix,
|
||||||
|
namespace=self.host_namespace,
|
||||||
|
prefix_is_full_name=True)).bridge
|
||||||
|
self.network_bridges[network_id] = bridge
|
||||||
|
return bridge
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_random_ip(low, high):
|
def get_random_ip(low, high):
|
||||||
parent_range = netaddr.IPRange(low, high)
|
parent_range = netaddr.IPRange(low, high)
|
||||||
@ -165,6 +254,14 @@ class Host(fixtures.Fixture):
|
|||||||
def ovs_agent(self, agent):
|
def ovs_agent(self, agent):
|
||||||
self.agents['ovs'] = agent
|
self.agents['ovs'] = agent
|
||||||
|
|
||||||
|
@property
|
||||||
|
def linuxbridge_agent(self):
|
||||||
|
return self.agents['linuxbridge']
|
||||||
|
|
||||||
|
@linuxbridge_agent.setter
|
||||||
|
def linuxbridge_agent(self, agent):
|
||||||
|
self.agents['linuxbridge'] = agent
|
||||||
|
|
||||||
|
|
||||||
class Environment(fixtures.Fixture):
|
class Environment(fixtures.Fixture):
|
||||||
"""Represents a deployment topology.
|
"""Represents a deployment topology.
|
||||||
@ -215,12 +312,21 @@ class Environment(fixtures.Fixture):
|
|||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
self.temp_dir = self.useFixture(fixtures.TempDir()).path
|
self.temp_dir = self.useFixture(fixtures.TempDir()).path
|
||||||
|
|
||||||
|
#we need this bridge before rabbit and neutron service will start
|
||||||
|
self.central_data_bridge = self.useFixture(
|
||||||
|
net_helpers.OVSBridgeFixture('cnt-data')).bridge
|
||||||
|
self.central_external_bridge = self.useFixture(
|
||||||
|
net_helpers.OVSBridgeFixture('cnt-ex')).bridge
|
||||||
|
|
||||||
|
#Get rabbitmq address (and cnt-data network)
|
||||||
|
rabbitmq_ip_address = self._configure_port_for_rabbitmq()
|
||||||
self.rabbitmq_environment = self.useFixture(
|
self.rabbitmq_environment = self.useFixture(
|
||||||
process.RabbitmqEnvironmentFixture())
|
process.RabbitmqEnvironmentFixture(host=rabbitmq_ip_address)
|
||||||
|
)
|
||||||
|
|
||||||
plugin_cfg_fixture = self.useFixture(
|
plugin_cfg_fixture = self.useFixture(
|
||||||
config.ML2ConfigFixture(
|
config.ML2ConfigFixture(
|
||||||
self.env_desc, None, self.temp_dir,
|
self.env_desc, self.hosts_desc, self.temp_dir,
|
||||||
self.env_desc.network_type))
|
self.env_desc.network_type))
|
||||||
neutron_cfg_fixture = self.useFixture(
|
neutron_cfg_fixture = self.useFixture(
|
||||||
config.NeutronConfigFixture(
|
config.NeutronConfigFixture(
|
||||||
@ -231,11 +337,34 @@ class Environment(fixtures.Fixture):
|
|||||||
self.env_desc, None,
|
self.env_desc, None,
|
||||||
self.test_name, neutron_cfg_fixture, plugin_cfg_fixture))
|
self.test_name, neutron_cfg_fixture, plugin_cfg_fixture))
|
||||||
|
|
||||||
self.central_data_bridge = self.useFixture(
|
|
||||||
net_helpers.OVSBridgeFixture('cnt-data')).bridge
|
|
||||||
self.central_external_bridge = self.useFixture(
|
|
||||||
net_helpers.OVSBridgeFixture('cnt-ex')).bridge
|
|
||||||
|
|
||||||
self.hosts = [self._create_host(desc) for desc in self.hosts_desc]
|
self.hosts = [self._create_host(desc) for desc in self.hosts_desc]
|
||||||
|
|
||||||
self.wait_until_env_is_up()
|
self.wait_until_env_is_up()
|
||||||
|
|
||||||
|
def _configure_port_for_rabbitmq(self):
|
||||||
|
self.env_desc.network_range = self._get_network_range()
|
||||||
|
if not self.env_desc.network_range:
|
||||||
|
return "127.0.0.1"
|
||||||
|
rabbitmq_ip = str(self.env_desc.network_range[1])
|
||||||
|
rabbitmq_port = ip_lib.IPDevice(self.central_data_bridge.br_name)
|
||||||
|
rabbitmq_port.addr.add(common_utils.ip_to_cidr(rabbitmq_ip, 24))
|
||||||
|
rabbitmq_port.link.set_up()
|
||||||
|
|
||||||
|
return rabbitmq_ip
|
||||||
|
|
||||||
|
def _get_network_range(self):
|
||||||
|
#NOTE(slaweq): We need to choose IP address on which rabbitmq will be
|
||||||
|
# available because LinuxBridge agents are spawned in their own
|
||||||
|
# namespaces and need to know where the rabbitmq server is listening.
|
||||||
|
# For ovs agent it is not necessary because agents are spawned in
|
||||||
|
# globalscope together with rabbitmq server so default localhost
|
||||||
|
# address is fine for them
|
||||||
|
for desc in self.hosts_desc:
|
||||||
|
if desc.l2_agent_type == constants.AGENT_TYPE_LINUXBRIDGE:
|
||||||
|
return self.get_random_network(
|
||||||
|
"240.0.0.0", "240.255.255.255", "24")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_random_network(low, high, netmask):
|
||||||
|
ip = Host.get_random_ip(low, high)
|
||||||
|
return netaddr.IPNetwork("%s/%s" % (ip, netmask))
|
||||||
|
@ -20,11 +20,11 @@ from neutron.tests.common import net_helpers
|
|||||||
|
|
||||||
|
|
||||||
class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
|
class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
|
||||||
|
|
||||||
def __init__(self, host, network_id, tenant_id, safe_client,
|
def __init__(self, host, network_id, tenant_id, safe_client,
|
||||||
neutron_port=None):
|
neutron_port=None):
|
||||||
super(FakeFullstackMachine, self).__init__()
|
super(FakeFullstackMachine, self).__init__()
|
||||||
self.bridge = host.ovs_agent.br_int
|
self.host = host
|
||||||
self.host_binding = host.hostname
|
|
||||||
self.tenant_id = tenant_id
|
self.tenant_id = tenant_id
|
||||||
self.network_id = network_id
|
self.network_id = network_id
|
||||||
self.safe_client = safe_client
|
self.safe_client = safe_client
|
||||||
@ -33,18 +33,19 @@ class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
|
|||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
super(FakeFullstackMachine, self)._setUp()
|
super(FakeFullstackMachine, self)._setUp()
|
||||||
|
|
||||||
|
self.bridge = self.host.get_bridge(self.network_id)
|
||||||
|
|
||||||
if not self.neutron_port:
|
if not self.neutron_port:
|
||||||
self.neutron_port = self.safe_client.create_port(
|
self.neutron_port = self.safe_client.create_port(
|
||||||
network_id=self.network_id,
|
network_id=self.network_id,
|
||||||
tenant_id=self.tenant_id,
|
tenant_id=self.tenant_id,
|
||||||
hostname=self.host_binding)
|
hostname=self.host.hostname)
|
||||||
self.neutron_port_id = self.neutron_port['id']
|
|
||||||
mac_address = self.neutron_port['mac_address']
|
mac_address = self.neutron_port['mac_address']
|
||||||
|
|
||||||
self.port = self.useFixture(
|
self.port = self.useFixture(
|
||||||
net_helpers.PortFixture.get(
|
net_helpers.PortFixture.get(
|
||||||
self.bridge, self.namespace, mac_address,
|
self.bridge, self.namespace, mac_address,
|
||||||
self.neutron_port_id)).port
|
self.neutron_port['id'])).port
|
||||||
|
|
||||||
self._ip = self.neutron_port['fixed_ips'][0]['ip_address']
|
self._ip = self.neutron_port['fixed_ips'][0]['ip_address']
|
||||||
subnet_id = self.neutron_port['fixed_ips'][0]['subnet_id']
|
subnet_id = self.neutron_port['fixed_ips'][0]['subnet_id']
|
||||||
@ -69,6 +70,6 @@ class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
|
|||||||
|
|
||||||
def block_until_boot(self):
|
def block_until_boot(self):
|
||||||
utils.wait_until_true(
|
utils.wait_until_true(
|
||||||
lambda: (self.safe_client.client.show_port(self.neutron_port_id)
|
lambda: (self.safe_client.client.show_port(self.neutron_port['id'])
|
||||||
['port']['status'] == 'ACTIVE'),
|
['port']['status'] == 'ACTIVE'),
|
||||||
sleep=3)
|
sleep=3)
|
||||||
|
@ -36,7 +36,7 @@ DEFAULT_LOG_DIR = '/tmp/dsvm-fullstack-logs/'
|
|||||||
|
|
||||||
class ProcessFixture(fixtures.Fixture):
|
class ProcessFixture(fixtures.Fixture):
|
||||||
def __init__(self, test_name, process_name, exec_name, config_filenames,
|
def __init__(self, test_name, process_name, exec_name, config_filenames,
|
||||||
kill_signal=signal.SIGKILL):
|
namespace=None, kill_signal=signal.SIGKILL):
|
||||||
super(ProcessFixture, self).__init__()
|
super(ProcessFixture, self).__init__()
|
||||||
self.test_name = test_name
|
self.test_name = test_name
|
||||||
self.process_name = process_name
|
self.process_name = process_name
|
||||||
@ -44,6 +44,7 @@ class ProcessFixture(fixtures.Fixture):
|
|||||||
self.config_filenames = config_filenames
|
self.config_filenames = config_filenames
|
||||||
self.process = None
|
self.process = None
|
||||||
self.kill_signal = kill_signal
|
self.kill_signal = kill_signal
|
||||||
|
self.namespace = namespace
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
self.start()
|
self.start()
|
||||||
@ -62,7 +63,10 @@ class ProcessFixture(fixtures.Fixture):
|
|||||||
'--log-file', log_file]
|
'--log-file', log_file]
|
||||||
for filename in self.config_filenames:
|
for filename in self.config_filenames:
|
||||||
cmd += ['--config-file', filename]
|
cmd += ['--config-file', filename]
|
||||||
self.process = async_process.AsyncProcess(cmd)
|
run_as_root = bool(self.namespace)
|
||||||
|
self.process = async_process.AsyncProcess(
|
||||||
|
cmd, run_as_root=run_as_root, namespace=self.namespace
|
||||||
|
)
|
||||||
self.process.start(block=True)
|
self.process.start(block=True)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -71,6 +75,10 @@ class ProcessFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
class RabbitmqEnvironmentFixture(fixtures.Fixture):
|
class RabbitmqEnvironmentFixture(fixtures.Fixture):
|
||||||
|
|
||||||
|
def __init__(self, host="127.0.0.1"):
|
||||||
|
super(RabbitmqEnvironmentFixture, self).__init__()
|
||||||
|
self.host = host
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
self.user = base.get_rand_name(prefix='user')
|
self.user = base.get_rand_name(prefix='user')
|
||||||
self.password = base.get_rand_name(prefix='pass')
|
self.password = base.get_rand_name(prefix='pass')
|
||||||
@ -97,6 +105,7 @@ class NeutronServerFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
def __init__(self, env_desc, host_desc,
|
def __init__(self, env_desc, host_desc,
|
||||||
test_name, neutron_cfg_fixture, plugin_cfg_fixture):
|
test_name, neutron_cfg_fixture, plugin_cfg_fixture):
|
||||||
|
super(NeutronServerFixture, self).__init__()
|
||||||
self.env_desc = env_desc
|
self.env_desc = env_desc
|
||||||
self.host_desc = host_desc
|
self.host_desc = host_desc
|
||||||
self.test_name = test_name
|
self.test_name = test_name
|
||||||
@ -136,6 +145,7 @@ class OVSAgentFixture(fixtures.Fixture):
|
|||||||
|
|
||||||
def __init__(self, env_desc, host_desc,
|
def __init__(self, env_desc, host_desc,
|
||||||
test_name, neutron_cfg_fixture, agent_cfg_fixture):
|
test_name, neutron_cfg_fixture, agent_cfg_fixture):
|
||||||
|
super(OVSAgentFixture, self).__init__()
|
||||||
self.env_desc = env_desc
|
self.env_desc = env_desc
|
||||||
self.host_desc = host_desc
|
self.host_desc = host_desc
|
||||||
self.test_name = test_name
|
self.test_name = test_name
|
||||||
@ -161,31 +171,69 @@ class OVSAgentFixture(fixtures.Fixture):
|
|||||||
config_filenames=config_filenames))
|
config_filenames=config_filenames))
|
||||||
|
|
||||||
|
|
||||||
|
class LinuxBridgeAgentFixture(fixtures.Fixture):
|
||||||
|
|
||||||
|
NEUTRON_LINUXBRIDGE_AGENT = "neutron-linuxbridge-agent"
|
||||||
|
|
||||||
|
def __init__(self, env_desc, host_desc, test_name,
|
||||||
|
neutron_cfg_fixture, agent_cfg_fixture,
|
||||||
|
namespace=None):
|
||||||
|
super(LinuxBridgeAgentFixture, self).__init__()
|
||||||
|
self.env_desc = env_desc
|
||||||
|
self.host_desc = host_desc
|
||||||
|
self.test_name = test_name
|
||||||
|
self.neutron_cfg_fixture = neutron_cfg_fixture
|
||||||
|
self.neutron_config = self.neutron_cfg_fixture.config
|
||||||
|
self.agent_cfg_fixture = agent_cfg_fixture
|
||||||
|
self.agent_config = agent_cfg_fixture.config
|
||||||
|
self.namespace = namespace
|
||||||
|
|
||||||
|
def _setUp(self):
|
||||||
|
config_filenames = [self.neutron_cfg_fixture.filename,
|
||||||
|
self.agent_cfg_fixture.filename]
|
||||||
|
|
||||||
|
self.process_fixture = self.useFixture(
|
||||||
|
ProcessFixture(
|
||||||
|
test_name=self.test_name,
|
||||||
|
process_name=self.NEUTRON_LINUXBRIDGE_AGENT,
|
||||||
|
exec_name=self.NEUTRON_LINUXBRIDGE_AGENT,
|
||||||
|
config_filenames=config_filenames,
|
||||||
|
namespace=self.namespace
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class L3AgentFixture(fixtures.Fixture):
|
class L3AgentFixture(fixtures.Fixture):
|
||||||
|
|
||||||
NEUTRON_L3_AGENT = "neutron-l3-agent"
|
NEUTRON_L3_AGENT = "neutron-l3-agent"
|
||||||
|
|
||||||
def __init__(self, env_desc, host_desc,
|
def __init__(self, env_desc, host_desc, test_name,
|
||||||
test_name, neutron_cfg_fixture, l3_agent_cfg_fixture):
|
neutron_cfg_fixture, l3_agent_cfg_fixture,
|
||||||
|
namespace=None):
|
||||||
super(L3AgentFixture, self).__init__()
|
super(L3AgentFixture, self).__init__()
|
||||||
self.env_desc = env_desc
|
self.env_desc = env_desc
|
||||||
self.host_desc = host_desc
|
self.host_desc = host_desc
|
||||||
self.test_name = test_name
|
self.test_name = test_name
|
||||||
self.neutron_cfg_fixture = neutron_cfg_fixture
|
self.neutron_cfg_fixture = neutron_cfg_fixture
|
||||||
self.l3_agent_cfg_fixture = l3_agent_cfg_fixture
|
self.l3_agent_cfg_fixture = l3_agent_cfg_fixture
|
||||||
|
self.namespace = namespace
|
||||||
|
|
||||||
def _setUp(self):
|
def _setUp(self):
|
||||||
self.plugin_config = self.l3_agent_cfg_fixture.config
|
self.plugin_config = self.l3_agent_cfg_fixture.config
|
||||||
|
|
||||||
config_filenames = [self.neutron_cfg_fixture.filename,
|
config_filenames = [self.neutron_cfg_fixture.filename,
|
||||||
self.l3_agent_cfg_fixture.filename]
|
self.l3_agent_cfg_fixture.filename]
|
||||||
self.process_fixture = self.useFixture(ProcessFixture(
|
self.process_fixture = self.useFixture(
|
||||||
test_name=self.test_name,
|
ProcessFixture(
|
||||||
process_name=self.NEUTRON_L3_AGENT,
|
test_name=self.test_name,
|
||||||
exec_name=spawn.find_executable(
|
process_name=self.NEUTRON_L3_AGENT,
|
||||||
'l3_agent.py',
|
exec_name=spawn.find_executable(
|
||||||
path=os.path.join(base.ROOTDIR, 'common', 'agents')),
|
'l3_agent.py',
|
||||||
config_filenames=config_filenames))
|
path=os.path.join(base.ROOTDIR, 'common', 'agents')),
|
||||||
|
config_filenames=config_filenames,
|
||||||
|
namespace=self.namespace
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def get_namespace_suffix(self):
|
def get_namespace_suffix(self):
|
||||||
return self.plugin_config.DEFAULT.test_namespace_suffix
|
return self.plugin_config.DEFAULT.test_namespace_suffix
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import testscenarios
|
import testscenarios
|
||||||
|
|
||||||
|
from neutron.common import constants
|
||||||
from neutron.tests.fullstack import base
|
from neutron.tests.fullstack import base
|
||||||
from neutron.tests.fullstack.resources import environment
|
from neutron.tests.fullstack.resources import environment
|
||||||
from neutron.tests.fullstack.resources import machine
|
from neutron.tests.fullstack.resources import machine
|
||||||
@ -23,20 +24,7 @@ from neutron.tests.fullstack.resources import machine
|
|||||||
load_tests = testscenarios.load_tests_apply_scenarios
|
load_tests = testscenarios.load_tests_apply_scenarios
|
||||||
|
|
||||||
|
|
||||||
class TestConnectivitySameNetwork(base.BaseFullStackTestCase):
|
class BaseConnectivitySameNetworkTest(base.BaseFullStackTestCase):
|
||||||
|
|
||||||
network_scenarios = [
|
|
||||||
('VXLAN', {'network_type': 'vxlan',
|
|
||||||
'l2_pop': False}),
|
|
||||||
('GRE and l2pop', {'network_type': 'gre',
|
|
||||||
'l2_pop': True}),
|
|
||||||
('VLANs', {'network_type': 'vlan',
|
|
||||||
'l2_pop': False})]
|
|
||||||
interface_scenarios = [
|
|
||||||
('Ofctl', {'of_interface': 'ovs-ofctl'}),
|
|
||||||
('Native', {'of_interface': 'native'})]
|
|
||||||
scenarios = testscenarios.multiply_scenarios(
|
|
||||||
network_scenarios, interface_scenarios)
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
host_descriptions = [
|
host_descriptions = [
|
||||||
@ -45,15 +33,16 @@ class TestConnectivitySameNetwork(base.BaseFullStackTestCase):
|
|||||||
# agent types present on machines.
|
# agent types present on machines.
|
||||||
environment.HostDescription(
|
environment.HostDescription(
|
||||||
l3_agent=self.l2_pop,
|
l3_agent=self.l2_pop,
|
||||||
of_interface=self.of_interface) for _ in range(3)]
|
of_interface=self.of_interface,
|
||||||
|
l2_agent_type=self.l2_agent_type) for _ in range(3)]
|
||||||
env = environment.Environment(
|
env = environment.Environment(
|
||||||
environment.EnvironmentDescription(
|
environment.EnvironmentDescription(
|
||||||
network_type=self.network_type,
|
network_type=self.network_type,
|
||||||
l2_pop=self.l2_pop),
|
l2_pop=self.l2_pop),
|
||||||
host_descriptions)
|
host_descriptions)
|
||||||
super(TestConnectivitySameNetwork, self).setUp(env)
|
super(BaseConnectivitySameNetworkTest, self).setUp(env)
|
||||||
|
|
||||||
def test_connectivity(self):
|
def _test_connectivity(self):
|
||||||
tenant_uuid = uuidutils.generate_uuid()
|
tenant_uuid = uuidutils.generate_uuid()
|
||||||
|
|
||||||
network = self.safe_client.create_network(tenant_uuid)
|
network = self.safe_client.create_network(tenant_uuid)
|
||||||
@ -75,3 +64,40 @@ class TestConnectivitySameNetwork(base.BaseFullStackTestCase):
|
|||||||
vms[0].block_until_ping(vms[1].ip)
|
vms[0].block_until_ping(vms[1].ip)
|
||||||
vms[0].block_until_ping(vms[2].ip)
|
vms[0].block_until_ping(vms[2].ip)
|
||||||
vms[1].block_until_ping(vms[2].ip)
|
vms[1].block_until_ping(vms[2].ip)
|
||||||
|
|
||||||
|
|
||||||
|
class TestOvsConnectivitySameNetwork(BaseConnectivitySameNetworkTest):
|
||||||
|
|
||||||
|
l2_agent_type = constants.AGENT_TYPE_OVS
|
||||||
|
network_scenarios = [
|
||||||
|
('VXLAN', {'network_type': 'vxlan',
|
||||||
|
'l2_pop': False}),
|
||||||
|
('GRE and l2pop', {'network_type': 'gre',
|
||||||
|
'l2_pop': True}),
|
||||||
|
('VLANs', {'network_type': 'vlan',
|
||||||
|
'l2_pop': False})]
|
||||||
|
interface_scenarios = [
|
||||||
|
('Ofctl', {'of_interface': 'ovs-ofctl'}),
|
||||||
|
('Native', {'of_interface': 'native'})]
|
||||||
|
scenarios = testscenarios.multiply_scenarios(
|
||||||
|
network_scenarios, interface_scenarios)
|
||||||
|
|
||||||
|
def test_connectivity(self):
|
||||||
|
self._test_connectivity()
|
||||||
|
|
||||||
|
|
||||||
|
class TestLinuxBridgeConnectivitySameNetwork(BaseConnectivitySameNetworkTest):
|
||||||
|
|
||||||
|
l2_agent_type = constants.AGENT_TYPE_LINUXBRIDGE
|
||||||
|
scenarios = [
|
||||||
|
('VXLAN', {'network_type': 'vxlan',
|
||||||
|
'l2_pop': False}),
|
||||||
|
('VLANs', {'network_type': 'vlan',
|
||||||
|
'l2_pop': False}),
|
||||||
|
('VXLAN and l2pop', {'network_type': 'vxlan',
|
||||||
|
'l2_pop': True})
|
||||||
|
]
|
||||||
|
of_interface = None
|
||||||
|
|
||||||
|
def test_connectivity(self):
|
||||||
|
self._test_connectivity()
|
||||||
|
@ -245,6 +245,15 @@ function _install_post_devstack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function _configure_iptables_rules {
|
||||||
|
# For linuxbridge agent fullstack tests we need to add special rules to
|
||||||
|
# iptables for connection of agents to rabbitmq:
|
||||||
|
CHAIN_NAME="openstack-INPUT"
|
||||||
|
sudo iptables -n --list $CHAIN_NAME 1> /dev/null 2>&1 || CHAIN_NAME="INPUT"
|
||||||
|
sudo iptables -I $CHAIN_NAME -s 240.0.0.0/8 -p tcp -m tcp -d 240.0.0.0/8 --dport 5672 -j ACCEPT
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function configure_host_for_func_testing {
|
function configure_host_for_func_testing {
|
||||||
echo_summary "Configuring host for functional testing"
|
echo_summary "Configuring host for functional testing"
|
||||||
|
|
||||||
@ -270,3 +279,7 @@ if [[ "$IS_GATE" != "True" ]]; then
|
|||||||
configure_host_for_func_testing
|
configure_host_for_func_testing
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$VENV" =~ "dsvm-fullstack" ]]; then
|
||||||
|
_configure_iptables_rules
|
||||||
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user