Merge "Tap Mirror API and scenario tests"

This commit is contained in:
Zuul
2025-08-06 08:36:28 +00:00
committed by Gerrit Code Review
15 changed files with 573 additions and 49 deletions

View File

@@ -0,0 +1,218 @@
# 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 oslo_utils import uuidutils
from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from neutron_tempest_plugin.tap_as_a_service import base
class TapMirrorTestJSON(base.BaseTaasTest):
@classmethod
@utils.requires_ext(extension='tap-mirror', service='network')
def skip_checks(cls):
super().skip_checks()
@classmethod
def resource_setup(cls):
super().resource_setup()
cls.network = cls.create_network()
cls.tap_mirror_port = cls.create_port(cls.network)
cls.in_direction = {'IN': 101}
cls.out_direction = {'OUT': 102}
cls.both_direction = cls.in_direction | cls.out_direction
cls.remote_ip = '192.101.0.42'
cls.remote_ip2 = '192.101.3.43'
cls.gre = 'gre'
cls.erspan = 'erspanv1'
@decorators.idempotent_id('628f202c-ed0a-4eb1-8547-4954f67a84b7')
def test_create_tap_mirror(self):
tap_mirror = self.create_tap_mirror(
port_id=self.tap_mirror_port['id'],
directions=self.in_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
self.assertEqual(self.tap_mirror_port['id'], tap_mirror['port_id'])
self.assertEqual('gre', tap_mirror['mirror_type'])
self.assertEqual(self.in_direction, tap_mirror['directions'])
self.tap_mirrors_client.delete_tap_mirror(tap_mirror['id'])
tap_mirror = self.create_tap_mirror(
port_id=self.tap_mirror_port['id'],
directions=self.both_direction,
remote_ip=self.remote_ip,
mirror_type=self.erspan
)
self.assertEqual(self.tap_mirror_port['id'], tap_mirror['port_id'])
self.assertEqual(self.erspan, tap_mirror['mirror_type'])
self.assertEqual(self.both_direction, tap_mirror['directions'])
@decorators.idempotent_id('299c251b-e0bc-4449-98db-959a5d8038c2')
def test_list_show_tap_mirror(self):
tap_mirror = self.create_tap_mirror(
port_id=self.tap_mirror_port['id'],
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
tap_mirrors = self.tap_mirrors_client.list_tap_mirrors()
is_t_m_found = False
for t_m in tap_mirrors['tap_mirrors']:
if t_m['id'] == tap_mirror['id']:
is_t_m_found = True
break
self.assertTrue(is_t_m_found)
tap_mirror_show_res = self.tap_mirrors_client.show_tap_mirror(
tap_mirror['id'])['tap_mirror']
self.assertEqual(tap_mirror['id'], tap_mirror_show_res['id'])
self.assertEqual(self.gre, tap_mirror_show_res['mirror_type'])
self.assertEqual(self.remote_ip,
tap_mirror_show_res['remote_ip'])
self.assertEqual(self.out_direction,
tap_mirror_show_res['directions'])
@decorators.idempotent_id('19c40379-bda5-48c9-8873-fc990739d1b5')
def test_update_tap_mirror(self):
tap_mirror = self.create_tap_mirror(
port_id=self.tap_mirror_port['id'],
directions=self.in_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
self.tap_mirrors_client.update_tap_mirror(
tap_mirror_id=tap_mirror['id'],
name='new_name',
description='My fancy Tap Mirror'
)
tap_mirror_show_res = self.tap_mirrors_client.show_tap_mirror(
tap_mirror['id'])['tap_mirror']
self.assertEqual('new_name', tap_mirror_show_res['name'])
self.assertEqual('My fancy Tap Mirror',
tap_mirror_show_res['description'])
@decorators.idempotent_id('9ed165af-7c54-43ac-b14f-077e8f9601f6')
def test_delete_mirror_port_deletes_tap_mirror(self):
port1 = self.create_port(self.network)
tap_mirror = self.create_tap_mirror(
port_id=port1['id'],
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
# Delete port will result in deteltion of the tap_mirror
self.ports_client.delete_port(port1['id'])
self.assertRaises(lib_exc.NotFound,
self.tap_mirrors_client.show_tap_mirror,
tap_mirror['id'])
@decorators.idempotent_id('abdd4451-bd9d-4f1e-ab7f-e949b9246714')
def test_delete_tap_mirror_port_remains(self):
port1 = self.create_port(self.network)
tap_mirror = self.create_tap_mirror(
port_id=port1['id'],
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
# Delete tap_mirror will keep the port
self.tap_mirrors_client.delete_tap_mirror(tap_mirror['id'])
port_res = self.ports_client.show_port(port1['id'])['port']
self.assertEqual(port1['name'], port_res['name'])
@decorators.idempotent_id('1d8b68fc-a600-4b9e-bd17-9469c3a6c95b')
def test_create_tap_mirror_negative(self):
# directions keys' valid values are IN and OUT
self.assertRaises(lib_exc.BadRequest,
self.create_tap_mirror,
port_id=self.tap_mirror_port['id'],
directions={'something': 101},
remote_ip=self.remote_ip,
mirror_type=self.gre)
# mirror_type valid values are erspanv1 and gre
self.assertRaises(lib_exc.BadRequest,
self.create_tap_mirror,
port_id=self.tap_mirror_port['id'],
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type='erspanv2')
# remote_ip must be a valid IP
self.assertRaises(lib_exc.BadRequest,
self.create_tap_mirror,
port_id=self.tap_mirror_port['id'],
directions=self.in_direction,
remote_ip='192.101.0.420',
mirror_type=self.gre)
@decorators.idempotent_id('2b7850b3-3920-4f16-96b7-05e2efd96877')
def test_create_tap_service_tunnel_id_conflict(self):
self.create_tap_mirror(
port_id=self.tap_mirror_port['id'],
directions=self.in_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
port2 = self.create_port(self.network)
self.addCleanup(self.ports_client.delete_port, port2['id'])
self.assertRaises(lib_exc.Conflict,
self.create_tap_mirror,
port_id=port2['id'],
directions=self.in_direction,
remote_ip='192.101.0.4',
mirror_type=self.gre)
@decorators.idempotent_id('95ef1cc1-cd57-4193-a88e-716795e39ebf')
def test_create_tap_mirror_non_existing_port(self):
not_exists = uuidutils.generate_uuid()
self.assertRaises(lib_exc.NotFound,
self.create_tap_mirror,
port_id=not_exists,
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre)
@decorators.idempotent_id('123202cd-d810-4c15-bae7-26d69b24a1a4')
def test_multiple_mirrors_for_port(self):
port1 = self.create_port(self.network)
tap_mirror = self.create_tap_mirror(
port_id=port1['id'],
directions=self.out_direction,
remote_ip=self.remote_ip,
mirror_type=self.gre
)
self.addCleanup(self.tap_mirrors_client.delete_tap_mirror,
tap_mirror['id'])
# Creation of the 2nd mirror in case the direction: tunnel_id dict
# is different.
tap_mirror2 = self.create_tap_mirror(
port_id=port1['id'],
directions={'OUT': 103},
remote_ip=self.remote_ip2,
mirror_type=self.gre
)
# We have a conflict if the direction: tunnel_id dict is the
# same
self.tap_mirrors_client.delete_tap_mirror(tap_mirror2['id'])
self.assertRaises(lib_exc.Conflict,
self.create_tap_mirror,
port_id=port1['id'],
directions=self.out_direction,
remote_ip='192.101.0.4',
mirror_type=self.gre)

View File

@@ -42,6 +42,14 @@ class BaseTaasTest(test.BaseAdminNetworkTest):
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**os_primary.default_params)
cls.tap_mirrors_client = taas_client.TapMirrorsClient(
os_primary.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**os_primary.default_params)
def create_tap_service(self, **kwargs):
body = self.tap_services_client.create_tap_service(
@@ -80,3 +88,22 @@ class BaseTaasTest(test.BaseAdminNetworkTest):
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.tap_flows_client.delete_tap_flow,
tap_flow['id'])
def create_tap_mirror(self, **kwargs):
body = self.tap_mirrors_client.create_tap_mirror(
name=data_utils.rand_name("tap_mirror"),
**kwargs)
tap_mirror = body['tap_mirror']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.tap_mirrors_client.delete_tap_mirror,
tap_mirror['id'])
return tap_mirror
def update_tap_mirror(self, tap_mirror_id, **kwargs):
body = self.tap_mirrors_client.update_tap_mirror(
tap_mirror_id,
**kwargs)
tap_mirror = body['tap_mirror']
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.tap_mirrors_client.delete_tap_mirror,
tap_mirror['id'])

View File

@@ -59,6 +59,14 @@ class BaseTaasScenarioTests(base.BaseTempestTestCase):
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**cls.os_primary.default_params)
cls.tap_mirrors_client = taas_client.TapMirrorsClient(
cls.os_primary.auth_provider,
CONF.network.catalog_type,
CONF.network.region or CONF.identity.region,
endpoint_type=CONF.network.endpoint_type,
build_interval=CONF.network.build_interval,
build_timeout=CONF.network.build_timeout,
**cls.os_primary.default_params)
def _create_subnet(self, network, subnets_client=None,
namestart='subnet-smoke', **kwargs):
@@ -214,8 +222,10 @@ class BaseTaasScenarioTests(base.BaseTempestTestCase):
return network, subnet, router
def _create_server_with_floatingip(self, use_taas_cloud_image=False,
provider_net=False, **kwargs):
network = self.network
provider_net=False, network=None,
**kwargs):
if not network:
network = self.network
if use_taas_cloud_image:
image = CONF.neutron_plugin_options.advanced_image_ref
flavor = CONF.neutron_plugin_options.advanced_image_flavor_ref
@@ -226,17 +236,26 @@ class BaseTaasScenarioTests(base.BaseTempestTestCase):
if provider_net:
network = self.provider_network
port = self.create_port(
network=network, security_groups=[self.secgroup['id']], **kwargs)
server_params = {
'flavor_ref': flavor,
'image_ref': image,
'key_name': self.keypair['name'],
}
if 'security_group' in kwargs:
server_params['security_groups'] = [
{'name': kwargs.pop('security_group')}]
if kwargs.get('port_security_enabled', None) is False:
port = self.create_port(network=network, **kwargs)
else:
port = self.create_port(
network=network, security_groups=[self.secgroup['id']],
**kwargs)
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.client.delete_port, port['id'])
params = {
'flavor_ref': flavor,
'image_ref': image,
'key_name': self.keypair['name']
}
vm = self.create_server(networks=[{'port': port['id']}], **params)
vm = self.create_server(networks=[{'port': port['id']}],
**server_params)
self.wait_for_server_active(vm['server'])
self.wait_for_guest_os_ready(vm['server'])
@@ -291,3 +310,40 @@ class BaseTaasScenarioTests(base.BaseTempestTestCase):
test_utils.call_and_ignore_notfound_exc,
self.admin_network_client.remove_router_interface_with_subnet_id,
self.router['id'], subnet_id=result['subnet']['id'])
def _check_icmp_traffic(self, monitor_client, left_client,
left_port, right_port,
tcpdump_cmd=None):
log_location = "/tmp/tcpdumplog"
right_ip = right_port['fixed_ips'][0]['ip_address']
left_ip = left_port['fixed_ips'][0]['ip_address']
# Run tcpdump in background
if tcpdump_cmd:
self._run_in_background(monitor_client, tcpdump_cmd % log_location)
else:
self._run_in_background(monitor_client,
"sudo tcpdump -n -nn > %s" % log_location)
# Ensure tcpdump is up and running
psax = monitor_client.exec_command("ps -ax")
self.assertIn("tcpdump", psax)
# Run traffic from left_vm to right_vm
LOG.debug('Check ICMP traffic: ping %s ', right_ip)
self.check_remote_connectivity(left_client, right_ip,
ping_count=50)
# Collect tcpdump results
output = self.monitor_client.exec_command("cat %s" % log_location)
self.assertLess(0, len(output))
looking_for = ["%s > %s: ICMP echo request" % (left_ip, right_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), output

View File

@@ -0,0 +1,141 @@
# 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 tempest.common import utils
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils.linux import remote_client
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from neutron_tempest_plugin.tap_as_a_service.scenario import manager
CONF = config.CONF
class TestTapMirror(manager.BaseTaasScenarioTests):
@classmethod
@utils.requires_ext(extension='security-group', service='network')
@utils.requires_ext(extension='tap-mirror', service='network')
def skip_checks(cls):
super().skip_checks()
@classmethod
def resource_setup(cls):
super().resource_setup()
cls.keypair = cls.create_keypair()
cls.secgroup = cls.create_security_group(
name=data_utils.rand_name('secgroup'))
cls.create_loginable_secgroup_rule(secgroup_id=cls.secgroup['id'])
cls.create_pingable_secgroup_rule(secgroup_id=cls.secgroup['id'])
@decorators.idempotent_id('d9cfca96-fa83-417a-b111-1c02f6fe2796')
def test_tap_mirror_connectivity(self):
"""Test that traffic between 2 VMs mirrored to a FIP
.. code-block:: HTML
+------------+
| Monitor VM |
| FIP |
+-----+------+
|
|
+-----+------+
| NetMon |
+------------+
+---------------+
| Net0 |
+---+---------+-+
| |
| |
+---+-+ +-+---+
| VM0 | | VM1 |
+-----+ +-----+
This is a simplified scenario adapted to the CI machinery.
The mirroring destination should be outside of the cloud.
"""
# Create the topology for the 2 VMs of which the traffic
# will be mirrored
self.network, self.subnet, self.router = self.create_networks()
vm0_port, vm0_fip = self._create_server_with_floatingip(
security_group=self.secgroup['name']
)
vm1_port, vm1_fip = self._create_server_with_floatingip(
security_group=self.secgroup['name']
)
vm1_ip = vm1_port['fixed_ips'][0]['ip_address']
vm0_client = remote_client.RemoteClient(
vm0_fip['floating_ip_address'],
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'],
ssh_key_type=CONF.validation.ssh_key_type)
vm0_client.validate_authentication()
vm1_client = remote_client.RemoteClient(
vm1_fip['floating_ip_address'],
CONF.validation.image_ssh_user,
pkey=self.keypair['private_key'],
ssh_key_type=CONF.validation.ssh_key_type)
vm1_client.validate_authentication()
self.check_remote_connectivity(vm0_client, vm1_ip, ping_count=5)
# Create the VM which will be the destination of the mirror
netmon, _, _ = self.create_networks()
_, vm_mon_fip = self._create_server_with_floatingip(
use_taas_cloud_image=True, network=netmon,
security_group=self.secgroup['name'],
port_security_enabled=False,
)
user = CONF.neutron_plugin_options.advanced_image_ssh_user
self.monitor_client = remote_client.RemoteClient(
vm_mon_fip['floating_ip_address'], user,
pkey=self.keypair['private_key'],
ssh_key_type=CONF.validation.ssh_key_type)
self.monitor_client.validate_authentication()
r_ip = vm_mon_fip['floating_ip_address']
# Create GRE mirror, as tcpdump cant extract ERSPAN
# it is just visible as a type of GRE traffic.
# direction IN and that the test pings from vm0 to vm1
# means that ICMP echo request will be in the dump.
# 101 as tunnel id means that we will see 0x65 as key
tap_mirror = self.tap_mirrors_client.create_tap_mirror(
name=data_utils.rand_name("tap_mirror"),
port_id=vm1_port['id'],
directions={'IN': '101', 'OUT': '102'},
remote_ip=r_ip,
mirror_type='gre',
)
self.addCleanup(
test_utils.call_and_ignore_notfound_exc,
self.tap_mirrors_client.delete_tap_mirror,
tap_mirror['tap_mirror']['id']
)
res, output = self._check_icmp_traffic(
self.monitor_client,
vm0_client, vm0_port, vm1_port,
tcpdump_cmd="sudo tcpdump -vvv -n -nn proto GRE > %s")
self.assertTrue(res)
# GRE Key for Direction IN:101
self.assertIn('key=0x65', output)
# GRE Key for Direction OUT:102
self.assertIn('key=0x66', output)

View File

@@ -138,40 +138,6 @@ class TestTaaSTrafficScenarios(manager.BaseTaasScenarioTests):
self.right_client.validate_authentication()
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.assertIn("tcpdump", psax)
# Run traffic from left_vm to right_vm
LOG.debug('Check ICMP traffic: ping %s ', right_ip)
# self.left_client.exec_command(
# "ping -c 50 %s" % self.right_fip['floating_ip_address'])
self.check_remote_connectivity(self.left_client, right_ip,
ping_count=50)
# Collect tcpdump results
output = self.monitor_client.exec_command("cat %s" % log_location)
self.assertLess(0, len(output))
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
@@ -222,7 +188,9 @@ class TestTaaSTrafficScenarios(manager.BaseTaasScenarioTests):
with self._setup_topology(use_taas_cloud_image=True):
# Check that traffic was forwarded to TAAS service
self.assertTrue(self._check_icmp_traffic())
self.assertTrue(self._check_icmp_traffic(
self.monitor_client, self.left_client,
self.left_port, self.right_port)[0])
@decorators.idempotent_id('6c54d9c5-075a-4a1f-bbe6-12c3c9abf1e2')
@testtools.skipUnless(CONF.neutron_plugin_options.advanced_image_ref,
@@ -234,7 +202,9 @@ class TestTaaSTrafficScenarios(manager.BaseTaasScenarioTests):
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())
self.assertFalse(self._check_icmp_traffic(
self.monitor_client, self.left_client,
self.left_port, self.right_port)[0])
@decorators.idempotent_id('fcb15ca3-ef61-11e9-9792-f45c89c47e12')
@testtools.skipUnless(CONF.neutron_plugin_options.advanced_image_ref,
@@ -247,7 +217,9 @@ class TestTaaSTrafficScenarios(manager.BaseTaasScenarioTests):
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())
self.assertTrue(self._check_icmp_traffic(
self.monitor_client, self.left_client,
self.left_port, self.right_port)[0])
@decorators.idempotent_id('6c54d9c5-075a-4a1f-bbe6-12c3c9abf1e3')
@testtools.skipUnless(CONF.neutron_plugin_options.advanced_image_ref,
@@ -260,4 +232,6 @@ class TestTaaSTrafficScenarios(manager.BaseTaasScenarioTests):
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())
self.assertFalse(self._check_icmp_traffic(
self.monitor_client, self.left_client,
self.left_port, self.right_port)[0])

View File

@@ -61,3 +61,27 @@ class TapFlowsClient(base.BaseNetworkClient):
def list_tap_flows(self, **filters):
uri = '/taas/tap_flows'
return self.list_resources(uri, **filters)
class TapMirrorsClient(base.BaseNetworkClient):
def create_tap_mirror(self, **kwargs):
uri = '/taas/tap_mirrors'
post_data = {'tap_mirror': kwargs}
return self.create_resource(uri, post_data)
def update_tap_mirror(self, tap_mirror_id, **kwargs):
uri = '/taas/tap_mirrors/%s' % tap_mirror_id
post_data = {'tap_mirror': kwargs}
return self.update_resource(uri, post_data)
def show_tap_mirror(self, tap_mirror_id, **fields):
uri = '/taas/tap_mirrors/%s' % tap_mirror_id
return self.show_resource(uri, **fields)
def delete_tap_mirror(self, tap_mirror_id):
uri = '/taas/tap_mirrors/%s' % tap_mirror_id
return self.delete_resource(uri)
def list_tap_mirrors(self, **filters):
uri = '/taas/tap_mirrors'
return self.list_resources(uri, **filters)

View File

@@ -326,5 +326,9 @@
nodeset: openstack-single-node-jammy
required-projects: *required-projects-2023-1
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false

View File

@@ -301,5 +301,9 @@
nodeset: openstack-single-node-jammy
override-checkout: stable/2024.1
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false

View File

@@ -287,3 +287,10 @@
parent: neutron-tempest-plugin-tap-as-a-service
nodeset: openstack-single-node-jammy
override-checkout: stable/2024.2
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false

View File

@@ -252,3 +252,9 @@
parent: neutron-tempest-plugin-tap-as-a-service
nodeset: openstack-single-node-noble
override-checkout: stable/2025.1
- job:
name: neutron-tempest-plugin-tap-as-a-service-ovn-2025-1
parent: neutron-tempest-plugin-tap-as-a-service-ovn
nodeset: openstack-single-node-noble
override-checkout: stable/2025.1

View File

@@ -1512,12 +1512,14 @@
network_api_extensions_tempest:
- taas
- taas-vlan-filter
- tap-mirror
devstack_localrc:
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
BUILD_TIMEOUT: 784
Q_AGENT: openvswitch
Q_ML2_TENANT_NETWORK_TYPE: vxlan,vlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch
OVS_BRANCH: "branch-3.3"
devstack_local_conf:
post-config:
/$NEUTRON_CORE_PLUGIN_CONF:
@@ -1569,10 +1571,11 @@
q-svc: true
neutron: true
taas: true
tap_mirror: true
taas_openvswitch_agent: true
tempest: true
dstat: true
irrelevant-files:
irrelevant-files: &taas_irrelevant_files
- ^\.pylintrc$
- ^(test-|)requirements.txt$
- ^lower-constraints.txt$
@@ -1604,3 +1607,52 @@
# Ignore everything except for zuul.d/project.yaml
- ^zuul.d/.*_jobs\.yaml$
- ^zuul.d/base-nested-switch.yaml
- job:
name: neutron-tempest-plugin-tap-as-a-service-ovn
parent: neutron-tempest-plugin-base
description: |
Test tap-mirrors with OVN
roles:
- zuul: openstack/devstack
required-projects:
- openstack/neutron
- openstack/neutron-tempest-plugin
- openstack/tap-as-a-service
- openstack/tempest
vars:
tempest_concurrency: 4
tempest_test_regex: ^neutron_tempest_plugin\.tap_as_a_service
tox_envlist: all
network_api_extensions_tempest:
- taas
- tap-mirror
devstack_localrc:
Q_AGENT: ovn
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions_common + network_api_extensions_tempest) | join(',') }}"
BUILD_TIMEOUT: 784
TAAS_SERVICE_DRIVER: "TAAS:TAAS:neutron_taas.services.taas.service_drivers.ovn.taas_ovn.TaasOvnDriver:default"
# mirroring is available from OVN 22.12.0 and use OVS 3.2.1 that also have this
# feature and builds with the above OVN
OVN_BRANCH: "branch-24.03"
OVS_BRANCH: "branch-3.3"
devstack_local_conf:
test-config:
$TEMPEST_CONFIG:
neutron_plugin_options:
image_is_advanced: true
advanced_image_flavor_ref: d1
taas:
provider_physical_network: public
provider_segmentation_id: 100
image_feature_enabled:
api_v2: true
devstack_plugins:
neutron: git://opendev.org/openstack/neutron.git
neutron-tempest-plugin: https://opendev.org/openstack/neutron-tempest-plugin.git
tap-as-a-service: git://opendev.org/openstack/tap-as-a-service.git
devstack_services:
tap_mirror: true
taas: true
tempest: true
irrelevant-files: *taas_irrelevant_files

View File

@@ -235,9 +235,11 @@
- neutron-tempest-plugin-vpnaas-2024-2
- neutron-tempest-plugin-vpnaas-2025-1
- neutron-tempest-plugin-tap-as-a-service
- neutron-tempest-plugin-tap-as-a-service-ovn
- neutron-tempest-plugin-tap-as-a-service-2024-1
- neutron-tempest-plugin-tap-as-a-service-2024-2
- neutron-tempest-plugin-tap-as-a-service-2025-1
- neutron-tempest-plugin-tap-as-a-service-ovn-2025-1
gate:
jobs:

View File

@@ -284,5 +284,8 @@
required-projects: *required-projects-xena
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false

View File

@@ -306,5 +306,8 @@
required-projects: *required-projects-yoga
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false

View File

@@ -327,5 +327,8 @@
required-projects: *required-projects-zed
vars:
network_api_extensions_common: *api_extensions
network_api_extensions_tempest:
- taas
- taas-vlan-filter
devstack_localrc:
NEUTRON_DEPLOY_MOD_WSGI: false