# Copyright (c) 2019 AT&T # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from contextlib import contextmanager from oslo_log import log import testtools from tempest.common import utils from tempest import config from tempest.lib.common.utils.linux import remote_client from tempest.lib import decorators from neutron_taas_tempest_plugin.tests.scenario import base CONF = config.CONF LOG = log.getLogger(__name__) class TestTaaSTrafficScenarios(base.TaaSScenarioTest): @classmethod def setup_clients(cls): super(TestTaaSTrafficScenarios, cls).setup_clients() if CONF.image_feature_enabled.api_v1: cls.image_client = cls.os_primary.image_client elif CONF.image_feature_enabled.api_v2: cls.image_client = cls.os_primary.image_client_v2 else: raise cls.skipException( 'Either api_v1 or api_v2 must be True in ' '[image-feature-enabled].') @classmethod @utils.requires_ext(extension="router", service="network") def resource_setup(cls): super(TestTaaSTrafficScenarios, cls).resource_setup() for ext in ['taas']: if not utils.is_extension_enabled(ext, 'network'): msg = "%s Extension not enabled." % ext raise cls.skipException(msg) cls.network, cls.subnet, cls.router = cls.create_networks() cls.provider_network = None cls.keypair = cls.create_keypair() cls.secgroup = cls._create_security_group() @contextmanager def _setup_topology(self, taas=True, use_taas_cloud_image=False, provider_net=False): """Setup topology for the test +------------+ | monitor vm | +-----+------+ | +-----v---+ +--+ network <--+ | +----^----+ | | | | | +----+-+ +---+--+ | | vm 1 | | vm 2 | | +------+ +------+ | | +--------+ +--> router | +-----+--+ | +-----v------+ | public net | +------------+ """ if provider_net: if CONF.taas_plugin_options.provider_physical_network: self.provider_network = self._setup_provider_network() else: msg = "provider_physical_network not provided" raise self.skipException(msg) self.mon_port, mon_fip = self._create_server_with_floatingip( use_taas_cloud_image=use_taas_cloud_image, provider_net=provider_net) self.left_port, left_fip = self._create_server_with_floatingip( provider_net=provider_net) self.right_port, right_fip = self._create_server_with_floatingip( provider_net=provider_net) if taas: LOG.debug("Create TAAS service") tap_service = self.create_tap_service(port_id=self.mon_port['id']) self.create_tap_flow(tap_service_id=tap_service['id'], direction='BOTH', source_port=self.left_port['id']) self.create_tap_flow(tap_service_id=tap_service['id'], direction='BOTH', source_port=self.right_port['id']) user = CONF.validation.image_ssh_user if use_taas_cloud_image: user = CONF.taas_plugin_options.advanced_image_ssh_user self.monitor_client = remote_client.RemoteClient( mon_fip['floating_ip_address'], user, pkey=self.keypair['private_key']) self.left_client = remote_client.RemoteClient( left_fip['floating_ip_address'], CONF.validation.image_ssh_user, pkey=self.keypair['private_key']) self.right_client = remote_client.RemoteClient( right_fip['floating_ip_address'], CONF.validation.image_ssh_user, pkey=self.keypair['private_key']) yield def _check_icmp_traffic(self): log_location = "/tmp/tcpdumplog" right_ip = self.right_port['fixed_ips'][0]['ip_address'] left_ip = self.left_port['fixed_ips'][0]['ip_address'] # Run tcpdump in background self._run_in_background(self.monitor_client, "sudo tcpdump -n -nn > %s" % log_location) # Ensure tcpdump is up and running psax = self.monitor_client.exec_command("ps -ax") self.assertTrue("tcpdump" in psax) # Run traffic from left_vm to right_vm self.left_client.exec_command("ping -c 50 %s" % right_ip) # Collect tcpdump results output = self.monitor_client.exec_command("cat %s" % log_location) self.assertTrue(len(output) > 0) looking_for = ["IP %s > %s: ICMP echo request" % (left_ip, right_ip), "IP %s > %s: ICMP echo reply" % (right_ip, left_ip)] results = [] for tcpdump_line in looking_for: results.append(tcpdump_line in output) return all(results) def _test_taas_connectivity(self, use_provider_net=False): """Ensure TAAS doesn't break connectivity This test creates TAAS service between two servers and checks that it doesn't break basic connectivity between them. """ # Check uninterrupted traffic between VMs with self._setup_topology(provider_net=use_provider_net): # Left to right self._check_remote_connectivity( self.left_client, self.right_port['fixed_ips'][0]['ip_address']) # Right to left self._check_remote_connectivity( self.right_client, self.left_port['fixed_ips'][0]['ip_address']) # TAAS vm to right self._check_remote_connectivity( self.monitor_client, self.right_port['fixed_ips'][0]['ip_address']) # TAAS vm to left self._check_remote_connectivity( self.monitor_client, self.left_port['fixed_ips'][0]['ip_address']) @decorators.idempotent_id('ff414b7d-e81c-47f2-b6c8-53bc2f1e9b00') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_provider_network_connectivity(self): self._test_taas_connectivity(use_provider_net=True) @decorators.idempotent_id('e3c52e91-7abf-4dfd-8687-f7c071cdd333') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_network_connectivity(self): self._test_taas_connectivity(use_provider_net=False) @decorators.idempotent_id('fcb15ca3-ef61-11e9-9792-f45c89c47e11') @testtools.skipUnless(CONF.taas_plugin_options.advanced_image_ref, 'Cloud image not found.') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_forwarded_traffic_positive(self): """Check that TAAS forwards traffic as expected""" with self._setup_topology(use_taas_cloud_image=True): # Check that traffic was forwarded to TAAS service self.assertTrue(self._check_icmp_traffic()) @decorators.idempotent_id('6c54d9c5-075a-4a1f-bbe6-12c3c9abf1e2') @testtools.skipUnless(CONF.taas_plugin_options.advanced_image_ref, 'Cloud image not found.') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_forwarded_traffic_negative(self): """Check that TAAS doesn't forward traffic""" with self._setup_topology(taas=False, use_taas_cloud_image=True): # Check that traffic was NOT forwarded to TAAS service self.assertFalse(self._check_icmp_traffic()) @decorators.idempotent_id('fcb15ca3-ef61-11e9-9792-f45c89c47e12') @testtools.skipUnless(CONF.taas_plugin_options.advanced_image_ref, 'Cloud image not found.') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_forwarded_traffic_provider_net_positive(self): """Check that TAAS forwards traffic as expected in provider network""" with self._setup_topology(use_taas_cloud_image=True, provider_net=True): # Check that traffic was forwarded to TAAS service self.assertTrue(self._check_icmp_traffic()) @decorators.idempotent_id('6c54d9c5-075a-4a1f-bbe6-12c3c9abf1e3') @testtools.skipUnless(CONF.taas_plugin_options.advanced_image_ref, 'Cloud image not found.') @decorators.attr(type='slow') @utils.services('compute', 'network') def test_taas_forwarded_traffic_provider_net_negative(self): """Check that TAAS doesn't forward traffic in provider network""" with self._setup_topology(taas=False, use_taas_cloud_image=True, provider_net=True): # Check that traffic was NOT forwarded to TAAS service self.assertFalse(self._check_icmp_traffic())