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:
Sławek Kapłoński 2015-11-23 23:14:12 +00:00
parent 21d139d441
commit 2254acef06
10 changed files with 450 additions and 80 deletions

View File

@ -225,9 +225,12 @@ neutron/tests/fullstack/test_connectivity.py.
Full stack testing can simulate multi node testing by starting an agent
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
is connected to its own pair of br-int/br-ex, and those bridges are then
interconnected.
OVS/LinuxBridge/DHCP/L3 agents, all configured with the same "host" value.
Each OVS agent is connected to its own pair of br-int/br-ex, and those bridges
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

View File

@ -21,3 +21,5 @@ VXLAN_MCAST = 'multicast_flooding'
VXLAN_UCAST = 'unicast_flooding'
EXTENSION_DRIVER_TYPE = 'linuxbridge'
RESOURCE_ID_LENGTH = 11

View File

@ -128,11 +128,13 @@ class LinuxBridgeManager(amb.CommonAgentManagerBase):
return None
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:
LOG.warning(_LW("Invalid Network ID, will lead to incorrect "
"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
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)
return subinterface_name
def get_tap_device_name(self, interface_id):
@staticmethod
def get_tap_device_name(interface_id):
if not interface_id:
LOG.warning(_LW("Invalid Interface ID, will lead to incorrect "
"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
def get_vxlan_device_name(self, segmentation_id):

View File

@ -39,6 +39,8 @@ from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils
from neutron.common import constants as n_const
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.common import base as common_base
from neutron.tests import tools
@ -47,11 +49,18 @@ UNDEFINED = object()
NS_PREFIX = 'test-'
BR_PREFIX = 'test-br'
PORT_PREFIX = 'test-port'
PORT_PREFIX = 'port'
VETH0_PREFIX = 'test-veth0'
VETH1_PREFIX = 'test-veth1'
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(
r'^.*\s+\d+\s+.*:(?P<port>\d+)\s+[0-9:].*')
@ -473,7 +482,7 @@ class VethFixture(fixtures.Fixture):
"""Create a veth.
:ivar ports: created veth ports
:type ports: IPDevice 2-uplet
:type ports: tuple of 2 IPDevice
"""
def _setUp(self):
@ -508,6 +517,32 @@ class VethFixture(fixtures.Fixture):
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)
class PortFixture(fixtures.Fixture):
"""Create a port.
@ -541,7 +576,7 @@ class PortFixture(fixtures.Fixture):
if isinstance(bridge, ovs_lib.OVSBridge):
return OVSPortFixture(bridge, namespace, mac, port_id)
if isinstance(bridge, bridge_lib.BridgeDevice):
return LinuxBridgePortFixture(bridge, namespace)
return LinuxBridgePortFixture(bridge, namespace, mac, port_id)
if isinstance(bridge, VethBridge):
return VethPortFixture(bridge, namespace)
tools.fail('Unexpected bridge type: %s' % type(bridge))
@ -578,7 +613,13 @@ class OVSPortFixture(PortFixture):
interface_config.register_opts(interface.OPTS)
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(
None,
self.port_id,
@ -598,22 +639,44 @@ class LinuxBridgeFixture(fixtures.Fixture):
:ivar namespace: created bridge namespace
: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__()
self.prefix = prefix
self.prefix_is_full_name = prefix_is_full_name
self.namespace = namespace
def _setUp(self):
if self.namespace is UNDEFINED:
self.namespace = self.useFixture(NamespaceFixture()).name
self.bridge = common_base.create_resource(
self.prefix,
bridge_lib.BridgeDevice.addbr,
namespace=self.namespace)
self.addCleanup(self.bridge.delbr)
self.bridge = self._create_bridge()
self.addCleanup(self.safe_delete)
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):
@ -625,12 +688,29 @@ class LinuxBridgePortFixture(PortFixture):
: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):
return LinuxBridgeFixture()
def _setUp(self):
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
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)
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):

View File

@ -88,7 +88,7 @@ class NeutronConfigFixture(ConfigFixture):
'oslo_messaging_rabbit': {
'rabbit_userid': rabbitmq_environment.user,
'rabbit_password': rabbitmq_environment.password,
'rabbit_hosts': '127.0.0.1',
'rabbit_hosts': rabbitmq_environment.host,
'rabbit_virtual_host': rabbitmq_environment.vhost,
}
})
@ -114,14 +114,10 @@ class ML2ConfigFixture(ConfigFixture):
super(ML2ConfigFixture, self).__init__(
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({
'ml2': {
'tenant_network_types': tenant_network_types,
'mechanism_drivers': mechanism_drivers,
'mechanism_drivers': self.mechanism_drivers,
},
'ml2_type_vlan': {
'network_vlan_ranges': 'physnet1:1000:2999',
@ -138,6 +134,16 @@ class ML2ConfigFixture(ConfigFixture):
self.config['ml2']['extension_drivers'] =\
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):
@ -205,12 +211,59 @@ class OVSConfigFixture(ConfigFixture):
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):
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__(
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({
'DEFAULT': {
'l3_agent_manager': ('neutron.agent.l3_agent.'
@ -219,9 +272,14 @@ class L3ConfigFixture(ConfigFixture):
'OVSInterfaceDriver'),
'ovs_integration_bridge': integration_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'),
}
})

View File

@ -19,8 +19,12 @@ import netaddr
from neutronclient.common import exceptions as nc_exc
from oslo_config import cfg
from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils
from neutron.common import constants
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.fullstack.resources import config
from neutron.tests.fullstack.resources import process
@ -35,6 +39,7 @@ class EnvironmentDescription(object):
self.network_type = network_type
self.l2_pop = l2_pop
self.qos = qos
self.network_range = None
@property
def tunneling_enabled(self):
@ -47,7 +52,9 @@ class HostDescription(object):
What agents should the host spawn? What mode should each agent operate
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.of_interface = of_interface
@ -75,12 +82,29 @@ class Host(fixtures.Fixture):
self.test_name = test_name
self.neutron_config = neutron_config
# 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_external_bridge = central_external_bridge
self.host_namespace = None
self.agents = {}
# we need to cache already created "per network" bridges if linuxbridge
# agent is used on host:
self.network_bridges = {}
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(
self.env_desc, self.host_desc, self.neutron_config.temp_dir,
self.local_ip)
@ -103,21 +127,62 @@ class Host(fixtures.Fixture):
self.test_name, self.neutron_config, agent_cfg_fixture))
if self.host_desc.l3_agent:
l3_agent_cfg_fixture = self.useFixture(
self.l3_agent_cfg_fixture = self.useFixture(
config.L3ConfigFixture(
self.env_desc, self.host_desc,
self.neutron_config.temp_dir,
self.ovs_agent.agent_cfg_fixture.get_br_int_name()))
br_ex = self.useFixture(
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.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.test_name,
self.neutron_config,
l3_agent_cfg_fixture))
self.neutron_config.temp_dir))
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):
veth_1, veth_2 = self.useFixture(
@ -140,6 +205,30 @@ class Host(fixtures.Fixture):
net_helpers.create_patch_ports(
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
def get_random_ip(low, high):
parent_range = netaddr.IPRange(low, high)
@ -165,6 +254,14 @@ class Host(fixtures.Fixture):
def ovs_agent(self, 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):
"""Represents a deployment topology.
@ -215,12 +312,21 @@ class Environment(fixtures.Fixture):
def _setUp(self):
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(
process.RabbitmqEnvironmentFixture())
process.RabbitmqEnvironmentFixture(host=rabbitmq_ip_address)
)
plugin_cfg_fixture = self.useFixture(
config.ML2ConfigFixture(
self.env_desc, None, self.temp_dir,
self.env_desc, self.hosts_desc, self.temp_dir,
self.env_desc.network_type))
neutron_cfg_fixture = self.useFixture(
config.NeutronConfigFixture(
@ -231,11 +337,34 @@ class Environment(fixtures.Fixture):
self.env_desc, None,
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.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))

View File

@ -20,11 +20,11 @@ from neutron.tests.common import net_helpers
class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
def __init__(self, host, network_id, tenant_id, safe_client,
neutron_port=None):
super(FakeFullstackMachine, self).__init__()
self.bridge = host.ovs_agent.br_int
self.host_binding = host.hostname
self.host = host
self.tenant_id = tenant_id
self.network_id = network_id
self.safe_client = safe_client
@ -33,18 +33,19 @@ class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
def _setUp(self):
super(FakeFullstackMachine, self)._setUp()
self.bridge = self.host.get_bridge(self.network_id)
if not self.neutron_port:
self.neutron_port = self.safe_client.create_port(
network_id=self.network_id,
tenant_id=self.tenant_id,
hostname=self.host_binding)
self.neutron_port_id = self.neutron_port['id']
hostname=self.host.hostname)
mac_address = self.neutron_port['mac_address']
self.port = self.useFixture(
net_helpers.PortFixture.get(
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']
subnet_id = self.neutron_port['fixed_ips'][0]['subnet_id']
@ -69,6 +70,6 @@ class FakeFullstackMachine(machine_fixtures.FakeMachineBase):
def block_until_boot(self):
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'),
sleep=3)

View File

@ -36,7 +36,7 @@ DEFAULT_LOG_DIR = '/tmp/dsvm-fullstack-logs/'
class ProcessFixture(fixtures.Fixture):
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__()
self.test_name = test_name
self.process_name = process_name
@ -44,6 +44,7 @@ class ProcessFixture(fixtures.Fixture):
self.config_filenames = config_filenames
self.process = None
self.kill_signal = kill_signal
self.namespace = namespace
def _setUp(self):
self.start()
@ -62,7 +63,10 @@ class ProcessFixture(fixtures.Fixture):
'--log-file', log_file]
for filename in self.config_filenames:
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)
def stop(self):
@ -71,6 +75,10 @@ class ProcessFixture(fixtures.Fixture):
class RabbitmqEnvironmentFixture(fixtures.Fixture):
def __init__(self, host="127.0.0.1"):
super(RabbitmqEnvironmentFixture, self).__init__()
self.host = host
def _setUp(self):
self.user = base.get_rand_name(prefix='user')
self.password = base.get_rand_name(prefix='pass')
@ -97,6 +105,7 @@ class NeutronServerFixture(fixtures.Fixture):
def __init__(self, env_desc, host_desc,
test_name, neutron_cfg_fixture, plugin_cfg_fixture):
super(NeutronServerFixture, self).__init__()
self.env_desc = env_desc
self.host_desc = host_desc
self.test_name = test_name
@ -136,6 +145,7 @@ class OVSAgentFixture(fixtures.Fixture):
def __init__(self, env_desc, host_desc,
test_name, neutron_cfg_fixture, agent_cfg_fixture):
super(OVSAgentFixture, self).__init__()
self.env_desc = env_desc
self.host_desc = host_desc
self.test_name = test_name
@ -161,31 +171,69 @@ class OVSAgentFixture(fixtures.Fixture):
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):
NEUTRON_L3_AGENT = "neutron-l3-agent"
def __init__(self, env_desc, host_desc,
test_name, neutron_cfg_fixture, l3_agent_cfg_fixture):
def __init__(self, env_desc, host_desc, test_name,
neutron_cfg_fixture, l3_agent_cfg_fixture,
namespace=None):
super(L3AgentFixture, 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.l3_agent_cfg_fixture = l3_agent_cfg_fixture
self.namespace = namespace
def _setUp(self):
self.plugin_config = self.l3_agent_cfg_fixture.config
config_filenames = [self.neutron_cfg_fixture.filename,
self.l3_agent_cfg_fixture.filename]
self.process_fixture = self.useFixture(ProcessFixture(
test_name=self.test_name,
process_name=self.NEUTRON_L3_AGENT,
exec_name=spawn.find_executable(
'l3_agent.py',
path=os.path.join(base.ROOTDIR, 'common', 'agents')),
config_filenames=config_filenames))
self.process_fixture = self.useFixture(
ProcessFixture(
test_name=self.test_name,
process_name=self.NEUTRON_L3_AGENT,
exec_name=spawn.find_executable(
'l3_agent.py',
path=os.path.join(base.ROOTDIR, 'common', 'agents')),
config_filenames=config_filenames,
namespace=self.namespace
)
)
def get_namespace_suffix(self):
return self.plugin_config.DEFAULT.test_namespace_suffix

View File

@ -15,6 +15,7 @@
from oslo_utils import uuidutils
import testscenarios
from neutron.common import constants
from neutron.tests.fullstack import base
from neutron.tests.fullstack.resources import environment
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
class TestConnectivitySameNetwork(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)
class BaseConnectivitySameNetworkTest(base.BaseFullStackTestCase):
def setUp(self):
host_descriptions = [
@ -45,15 +33,16 @@ class TestConnectivitySameNetwork(base.BaseFullStackTestCase):
# agent types present on machines.
environment.HostDescription(
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(
environment.EnvironmentDescription(
network_type=self.network_type,
l2_pop=self.l2_pop),
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()
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[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()

View File

@ -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 {
echo_summary "Configuring host for functional testing"
@ -270,3 +279,7 @@ if [[ "$IS_GATE" != "True" ]]; then
configure_host_for_func_testing
fi
fi
if [[ "$VENV" =~ "dsvm-fullstack" ]]; then
_configure_iptables_rules
fi