]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Add tunneling support to full stack tests
authorAssaf Muller <amuller@redhat.com>
Tue, 16 Jun 2015 12:56:41 +0000 (08:56 -0400)
committerIhar Hrachyshka <ihrachys@redhat.com>
Thu, 10 Sep 2015 14:30:21 +0000 (14:30 +0000)
* 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

doc/source/devref/fullstack_testing.rst
neutron/tests/base.py
neutron/tests/fullstack/resources/config.py
neutron/tests/fullstack/resources/environment.py
neutron/tests/fullstack/resources/process.py
neutron/tests/fullstack/test_connectivity.py
neutron/tests/fullstack/test_l3_agent.py

index f1ff581dc35e12099f78c9d7b60b625e8490b320..5467f74f43e77dc873909ac5ad92a815bfe63249 100644 (file)
@@ -83,6 +83,12 @@ When?
    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
 ----------------
 
@@ -103,9 +109,6 @@ the fact as there will probably be something to copy/paste from.
 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
index 86f08544f9cdd51f54b81154fd4ef6776c4b756b..cd79f3eebbf6bf67e275ca5abb551dca405651dd 100644 (file)
@@ -104,7 +104,7 @@ def get_test_timeout(default=0):
 
 
 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(')', '_')
 
 
index c4efa8197f2c0d3de40f83e3186fd97aeae540d4..215f4909dbdc5598038678d5f8d34682bb42a64d 100644 (file)
@@ -178,16 +178,16 @@ class ML2ConfigFixture(ConfigFixture):
 
 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': {
@@ -196,18 +196,41 @@ class OVSConfigFixture(ConfigFixture):
             }
         })
 
+        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):
 
index 67660f813b72cde81edd15c691902e32874b3781..7a0d67e6a16506413540013393325898a881e69f 100644 (file)
 #    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
@@ -30,7 +34,12 @@ class EnvironmentDescription(object):
 
     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):
@@ -65,19 +74,28 @@ class Host(fixtures.Fixture):
         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(
@@ -101,6 +119,17 @@ class Host(fixtures.Fixture):
                     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.
@@ -111,6 +140,11 @@ class Host(fixtures.Fixture):
         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
@@ -186,7 +220,8 @@ class Environment(fixtures.Fixture):
 
         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,
index 0d6a8bd73f008cc2b71f2883dc3bf90612c57f22..3c1a4db6cbfa2e929b65ea77e56f4b418f64bd88 100644 (file)
@@ -47,7 +47,9 @@ class ProcessFixture(fixtures.Fixture):
         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")
index b0f546a3eb32429a4a7ec20840cca2ecd0fea269..ed72221b5274ef2b9238756496852b9eafd47cde 100644 (file)
@@ -12,6 +12,8 @@
 #    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
@@ -19,13 +21,21 @@ from neutron.tests.fullstack.resources import environment
 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):
index 28f2419b8786d1a91de25156c282406317f7e35e..2a0814fff93d0ff4210d16f5e60abb6aff16e705 100644 (file)
@@ -28,8 +28,9 @@ class TestLegacyL3Agent(base.BaseFullStackTestCase):
 
     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):
@@ -59,8 +60,9 @@ class TestHAL3Agent(base.BaseFullStackTestCase):
     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):