* EnvironmentDescription class now accepts 'network_type'.
It sets the ML2 segmentation type, passes it to the OVS agents
configuration files, and sets up the host configuration. If
tunnelling type is selected, it sets up a veth pair with an IP
address from the 240.0.0.1+ range. The addressed end of
this pair is configured as the local_ip for tunneling purposes
in each of the OVS agents. If network type is not tunnelled, it
sets up provider bridges instead and interconnects them.
* For now we run the basic L3 HA test with VLANs and tunneling just
so we have something to show for.
* I started using scenarios in fullstack tests to run the same test
with VLANs or tunneling, and because test names are used for log
dirs, and testscenarios changes test names to include characters
that are not shell friendly (Space, parenthesis), I 'sanitized'
some of those characters.
Change-Id: Ic45cc27396452111678cf85ab26b07275846ce44
stack testing can help here as the full stack infrastructure can restart an
agent during the test.
+Prerequisites
+-------------
+
+Fullstack test suite assumes 240.0.0.0/3 range in root namespace of the test
+machine is available for its usage.
+
Short Term Goals
----------------
Long Term Goals
---------------
-* Currently we configure the OVS agent with VLANs segmentation (Only because
- it's easier). This allows us to validate most functionality, but we might
- need to support tunneling somehow.
* How will advanced services use the full stack testing infrastructure? Full
stack tests infrastructure classes are expected to change quite a bit over
the next coming months. This means that other repositories may import these
def sanitize_log_path(path):
- # Sanitize the string so that it's log path is shell friendly
+ # Sanitize the string so that its log path is shell friendly
return path.replace(' ', '-').replace('(', '_').replace(')', '_')
class OVSConfigFixture(ConfigFixture):
- def __init__(self, env_desc, host_desc, temp_dir):
+ def __init__(self, env_desc, host_desc, temp_dir, local_ip):
super(OVSConfigFixture, self).__init__(
env_desc, host_desc, temp_dir,
base_filename='openvswitch_agent.ini')
+ self.tunneling_enabled = self.env_desc.tunneling_enabled
self.config.update({
'ovs': {
- 'enable_tunneling': 'False',
- 'local_ip': '127.0.0.1',
- 'bridge_mappings': self._generate_bridge_mappings(),
+ 'enable_tunneling': str(self.tunneling_enabled),
+ 'local_ip': local_ip,
'integration_bridge': self._generate_integration_bridge(),
},
'securitygroup': {
}
})
+ if self.tunneling_enabled:
+ self.config['agent'] = {
+ 'tunnel_types': self.env_desc.network_type}
+ self.config['ovs'].update({
+ 'tunnel_bridge': self._generate_tunnel_bridge(),
+ 'int_peer_patch_port': self._generate_int_peer(),
+ 'tun_peer_patch_port': self._generate_tun_peer()})
+ else:
+ self.config['ovs']['bridge_mappings'] = (
+ self._generate_bridge_mappings())
+
def _generate_bridge_mappings(self):
return 'physnet1:%s' % base.get_rand_device_name(prefix='br-eth')
def _generate_integration_bridge(self):
return base.get_rand_device_name(prefix='br-int')
+ def _generate_tunnel_bridge(self):
+ return base.get_rand_device_name(prefix='br-tun')
+
+ def _generate_int_peer(self):
+ return base.get_rand_device_name(prefix='patch-tun')
+
+ def _generate_tun_peer(self):
+ return base.get_rand_device_name(prefix='patch-int')
+
def get_br_int_name(self):
return self.config.ovs.integration_bridge
def get_br_phys_name(self):
return self.config.ovs.bridge_mappings.split(':')[1]
+ def get_br_tun_name(self):
+ return self.config.ovs.tunnel_bridge
+
class L3ConfigFixture(ConfigFixture):
# License for the specific language governing permissions and limitations
# under the License.
+import random
+
import fixtures
+import netaddr
from neutronclient.common import exceptions as nc_exc
from oslo_config import cfg
from oslo_log import log as logging
from neutron.agent.linux import utils
+from neutron.common import utils as common_utils
from neutron.tests.common import net_helpers
from neutron.tests.fullstack.resources import config
from neutron.tests.fullstack.resources import process
Does the setup, as a whole, support tunneling? How about l2pop?
"""
- pass
+ def __init__(self, network_type='vxlan'):
+ self.network_type = network_type
+
+ @property
+ def tunneling_enabled(self):
+ return self.network_type in ('vxlan', 'gre')
class HostDescription(object):
self.host_desc = host_desc
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.central_data_bridge = central_data_bridge
self.central_external_bridge = central_external_bridge
self.agents = {}
def _setUp(self):
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.useFixture(agent_cfg_fixture)
- br_phys = self.useFixture(
- net_helpers.OVSBridgeFixture(
- agent_cfg_fixture.get_br_phys_name())).bridge
- self.connect_to_internal_network_via_vlans(br_phys)
+ if self.env_desc.tunneling_enabled:
+ self.useFixture(
+ net_helpers.OVSBridgeFixture(
+ agent_cfg_fixture.get_br_tun_name())).bridge
+ self.connect_to_internal_network_via_tunneling()
+ else:
+ br_phys = self.useFixture(
+ net_helpers.OVSBridgeFixture(
+ agent_cfg_fixture.get_br_phys_name())).bridge
+ self.connect_to_internal_network_via_vlans(br_phys)
self.ovs_agent = self.useFixture(
process.OVSAgentFixture(
self.neutron_config,
l3_agent_cfg_fixture))
+ def connect_to_internal_network_via_tunneling(self):
+ veth_1, veth_2 = self.useFixture(
+ net_helpers.VethFixture()).ports
+
+ # NOTE: This sets an IP address on the host's root namespace
+ # which is cleaned up when the device is deleted.
+ veth_1.addr.add(common_utils.ip_to_cidr(self.local_ip, 32))
+
+ veth_1.link.set_up()
+ veth_2.link.set_up()
+
def connect_to_internal_network_via_vlans(self, host_data_bridge):
# If using VLANs as a segmentation device, it's needed to connect
# a provider bridge to a centralized, shared bridge.
net_helpers.create_patch_ports(
self.central_external_bridge, host_external_bridge)
+ @staticmethod
+ def get_random_ip(low, high):
+ parent_range = netaddr.IPRange(low, high)
+ return str(random.choice(parent_range))
+
@property
def hostname(self):
return self.neutron_config.config.DEFAULT.host
plugin_cfg_fixture = self.useFixture(
config.ML2ConfigFixture(
- self.env_desc, None, self.temp_dir, 'vlan'))
+ self.env_desc, None, self.temp_dir,
+ self.env_desc.network_type))
neutron_cfg_fixture = self.useFixture(
config.NeutronConfigFixture(
self.env_desc, None, self.temp_dir,
self.addCleanup(self.stop)
def start(self):
- log_dir = os.path.join(DEFAULT_LOG_DIR, self.test_name)
+ test_name = base.sanitize_log_path(self.test_name)
+
+ log_dir = os.path.join(DEFAULT_LOG_DIR, test_name)
common_utils.ensure_dir(log_dir)
timestamp = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S-%f")
# License for the specific language governing permissions and limitations
# under the License.
+import testscenarios
+
from oslo_utils import uuidutils
from neutron.tests.fullstack import base
from neutron.tests.fullstack.resources import machine
+load_tests = testscenarios.load_tests_apply_scenarios
+
+
class TestConnectivitySameNetwork(base.BaseFullStackTestCase):
+ scenarios = [('VXLAN', {'network_type': 'vxlan'}),
+ ('VLANs', {'network_type': 'vlan'})]
+
def setUp(self):
host_descriptions = [
environment.HostDescription() for _ in range(2)]
- env = environment.Environment(environment.EnvironmentDescription(),
- host_descriptions)
+ env = environment.Environment(
+ environment.EnvironmentDescription(
+ network_type=self.network_type),
+ host_descriptions)
super(TestConnectivitySameNetwork, self).setUp(env)
def test_connectivity(self):
def setUp(self):
host_descriptions = [environment.HostDescription(l3_agent=True)]
- env = environment.Environment(environment.EnvironmentDescription(),
- host_descriptions)
+ env = environment.Environment(
+ environment.EnvironmentDescription(network_type='vlan'),
+ host_descriptions)
super(TestLegacyL3Agent, self).setUp(env)
def _get_namespace(self, router_id):
def setUp(self):
host_descriptions = [
environment.HostDescription(l3_agent=True) for _ in range(2)]
- env = environment.Environment(environment.EnvironmentDescription(),
- host_descriptions)
+ env = environment.Environment(
+ environment.EnvironmentDescription(network_type='vxlan'),
+ host_descriptions)
super(TestHAL3Agent, self).setUp(env)
def _is_ha_router_active_on_one_agent(self, router_id):