Merge "Fix list of API extensions for dvr and designate jobs"
diff --git a/.zuul.yaml b/.zuul.yaml
index afb95d6..2ac6c8b 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -875,7 +875,6 @@
NETWORKING_BGPVPN_DRIVER: "BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe_v2.BaGPipeBGPVPNDriver:default"
BAGPIPE_DATAPLANE_DRIVER_IPVPN: "ovs"
BAGPIPE_BGP_PEERS: "-"
- USE_PYTHON3: false
NETWORK_API_EXTENSIONS: "{{ (network_api_extensions + network_api_extensions_bgpvpn) | join(',') }}"
devstack_plugins:
networking-bgpvpn: https://git.openstack.org/openstack/networking-bgpvpn
@@ -1005,9 +1004,16 @@
- neutron-tempest-plugin-sfc
- neutron-tempest-plugin-bgpvpn-bagpipe
- neutron-tempest-plugin-fwaas
- - neutron-tempest-plugin-dynamic-routing
+ - neutron-tempest-plugin-dynamic-routing:
+ # TODO(slaweq): switch it to be voting when bug
+ # https://bugs.launchpad.net/neutron/+bug/1850626 will be fixed
+ voting: false
+
gate:
jobs:
+ - neutron-tempest-plugin-sfc
- neutron-tempest-plugin-bgpvpn-bagpipe
- neutron-tempest-plugin-fwaas
- - neutron-tempest-plugin-dynamic-routing
+ # TODO(slaweq): bring it back to gate queue
+ # https://bugs.launchpad.net/neutron/+bug/1850626 will be fixed
+ # - neutron-tempest-plugin-dynamic-routing
diff --git a/neutron_tempest_plugin/api/admin/test_agent_management.py b/neutron_tempest_plugin/api/admin/test_agent_management.py
index ad0368a..4a37904 100644
--- a/neutron_tempest_plugin/api/admin/test_agent_management.py
+++ b/neutron_tempest_plugin/api/admin/test_agent_management.py
@@ -66,10 +66,7 @@
@decorators.idempotent_id('68a94a14-1243-46e6-83bf-157627e31556')
def test_update_agent_description(self):
agents = self.admin_client.list_agents()['agents']
- try:
- dyn_agent = agents[1]
- except IndexError:
- raise self.skipException("This test requires at least two agents.")
+ dyn_agent = self._select_one_agent_for_update(agents)
self.useFixture(tempest_fixtures.LockFixture('agent_description'))
description = 'description for update agent.'
@@ -86,3 +83,10 @@
origin_agent = {'description': description}
self.admin_client.update_agent(agent_id=dyn_agent['id'],
agent_info=origin_agent)
+
+ def _select_one_agent_for_update(self, agents):
+ """Return one agent that is not the one selected at resource_setup"""
+ for agent in agents:
+ if self.agent['id'] != agent['id']:
+ return agent
+ raise self.skipException("This test requires at least two agents.")
diff --git a/neutron_tempest_plugin/api/admin/test_network_segment_range.py b/neutron_tempest_plugin/api/admin/test_network_segment_range.py
index e747fed..eacfbba 100644
--- a/neutron_tempest_plugin/api/admin/test_network_segment_range.py
+++ b/neutron_tempest_plugin/api/admin/test_network_segment_range.py
@@ -193,6 +193,16 @@
for network_id in network_ids:
self.admin_client.delete_network(network_id)
+ def _compare_segment_ranges(self, reference, observed):
+ self.assertEqual(reference['id'], observed['id'])
+ self.assertEqual(reference['name'], observed['name'])
+ self.assertFalse(observed['default'])
+ self.assertFalse(observed['shared'])
+ self.assertEqual(reference['project_id'], observed['project_id'])
+ self.assertEqual(reference['network_type'], observed['network_type'])
+ self.assertEqual(reference['minimum'], observed['minimum'])
+ self.assertEqual(reference['maximum'], observed['maximum'])
+
@decorators.idempotent_id('54fa26c9-37b5-4df4-a934-a705f29920fc')
def test_show_network_segment_range(self):
# Creates a network segment range
@@ -201,18 +211,7 @@
body = self.admin_client.show_network_segment_range(
network_segment_range['id'])
observed_range = body['network_segment_range']
- self.assertEqual(network_segment_range['id'], observed_range['id'])
- self.assertEqual(network_segment_range['name'], observed_range['name'])
- self.assertFalse(observed_range['default'])
- self.assertFalse(observed_range['shared'])
- self.assertEqual(network_segment_range['project_id'],
- observed_range['project_id'])
- self.assertEqual(network_segment_range['network_type'],
- observed_range['network_type'])
- self.assertEqual(network_segment_range['minimum'],
- observed_range['minimum'])
- self.assertEqual(network_segment_range['maximum'],
- observed_range['maximum'])
+ self._compare_segment_ranges(network_segment_range, observed_range)
@decorators.idempotent_id('17139cc1-4826-4bf9-9c39-85b74894d938')
def test_list_network_segment_ranges(self):
@@ -225,8 +224,9 @@
body = self.admin_client.list_network_segment_ranges(
id=network_segment_range['id'])
- list_range_ids = [r['id'] for r in body['network_segment_ranges']]
- self.assertIn(network_segment_range['id'], list_range_ids)
+ self.assertEqual(1, len(body['network_segment_ranges']))
+ observed_range = body['network_segment_ranges'][0]
+ self._compare_segment_ranges(network_segment_range, observed_range)
@decorators.idempotent_id('42959544-9956-4b0c-aec6-d56533323924')
def test_delete_network_segment_range_failed_with_segment_referenced(
diff --git a/neutron_tempest_plugin/api/test_qos.py b/neutron_tempest_plugin/api/test_qos.py
index 4f93577..25d2e81 100644
--- a/neutron_tempest_plugin/api/test_qos.py
+++ b/neutron_tempest_plugin/api/test_qos.py
@@ -13,6 +13,7 @@
# under the License.
from neutron_lib.api.definitions import qos as qos_apidef
+from neutron_lib import constants as n_constants
from neutron_lib.services.qos import constants as qos_consts
from tempest.common import utils
from tempest.lib.common.utils import data_utils
@@ -984,6 +985,71 @@
self.assertIn(rule1['id'], rules_ids)
self.assertNotIn(rule2['id'], rules_ids)
+ @decorators.idempotent_id('19ed2286-ccb1-11e9-87d7-525400d6f522')
+ def test_qos_dscp_create_and_update(self):
+ """This test covers:
+
+ 1.Creating a basic QoS policy with DSCP marking rule.
+ 2.Updating QoS policy:
+ Administrator should have the ability to update existing QoS policy.
+ This test should verify that:
+ It's possible to update the existing DSCP marking rule with all of
+ the valid marks between 0-56, except of the invalid marks:
+ 2-6, 42, 44, and 50-54 (which should be forbidden)
+ """
+
+ def _test_update_dscp_mark_values(self, dscp_policy_id, rule_id):
+ for mark in range(n_constants.VALID_DSCP_MARKS[1],
+ self.VALID_DSCP_MARK1 + 1):
+ if mark in n_constants.VALID_DSCP_MARKS:
+ self.admin_client.update_dscp_marking_rule(
+ dscp_policy_id, rule_id, dscp_mark=mark)
+
+ retrieved_rule = self.admin_client.show_dscp_marking_rule(
+ dscp_policy_id, rule_id)['dscp_marking_rule']
+ self.assertEqual(mark, retrieved_rule['dscp_mark'],
+ """current DSCP mark is incorrect:
+ expected value {0} actual value {1}
+ """.format(mark,
+ retrieved_rule['dscp_mark']))
+
+ else:
+ self.assertRaises(exceptions.BadRequest,
+ self.admin_client.create_dscp_marking_rule,
+ dscp_policy_id,
+ mark)
+ # Setup network
+ self.network = self.create_network()
+
+ # Create QoS policy
+ dscp_policy_id = self.create_qos_policy(
+ name='test-policy',
+ description='test-qos-policy',
+ shared=True)['id']
+
+ # Associate QoS to the network
+ self.admin_client.update_network(
+ self.network['id'], qos_policy_id=dscp_policy_id)
+
+ # Set a new DSCP rule with the first mark in range
+ rule_id = self.admin_client.create_dscp_marking_rule(
+ dscp_policy_id,
+ n_constants.VALID_DSCP_MARKS[0])[
+ 'dscp_marking_rule']['id']
+
+ # Validate that the rule was set up properly
+ retrieved_rule = self.client.show_dscp_marking_rule(
+ dscp_policy_id, rule_id)['dscp_marking_rule']
+ self.assertEqual(n_constants.VALID_DSCP_MARKS[0],
+ retrieved_rule['dscp_mark'],
+ """current DSCP mark is incorrect:
+ expected value {0} actual value {1}
+ """.format(n_constants.VALID_DSCP_MARKS[0],
+ retrieved_rule['dscp_mark']))
+
+ # Try to set marks in range 8:56 (invalid marks should raise an error)
+ _test_update_dscp_mark_values(self, dscp_policy_id, rule_id)
+
class QosMinimumBandwidthRuleTestJSON(base.BaseAdminNetworkTest):
DIRECTION_EGRESS = "egress"
diff --git a/neutron_tempest_plugin/scenario/base.py b/neutron_tempest_plugin/scenario/base.py
index 4b2ddcd..5a29aa1 100644
--- a/neutron_tempest_plugin/scenario/base.py
+++ b/neutron_tempest_plugin/scenario/base.py
@@ -26,6 +26,7 @@
from tempest.lib import exceptions as lib_exc
from neutron_tempest_plugin.api import base as base_api
+from neutron_tempest_plugin.common import shell
from neutron_tempest_plugin.common import ssh
from neutron_tempest_plugin import config
from neutron_tempest_plugin.scenario import constants
@@ -385,7 +386,8 @@
for server in servers:
kwargs = {}
try:
- kwargs['port'] = server['port_forwarding']['external_port']
+ kwargs['port'] = (
+ server['port_forwarding_tcp']['external_port'])
except KeyError:
pass
ssh_client = ssh.Client(
@@ -405,3 +407,34 @@
if log_errors:
self._log_console_output(servers)
raise
+
+ def nc_listen(self, server, ssh_client, port, protocol, echo_msg):
+ """Create nc server listening on the given TCP/UDP port.
+
+ Listener is created always on remote host.
+ """
+ udp = ''
+ if protocol.lower() == neutron_lib_constants.PROTO_NAME_UDP:
+ udp = '-u'
+ cmd = "sudo nc %(udp)s -p %(port)s -lk -e echo %(msg)s &" % {
+ 'udp': udp, 'port': port, 'msg': echo_msg}
+ try:
+ return ssh_client.exec_command(cmd)
+ except lib_exc.SSHTimeout as ssh_e:
+ LOG.debug(ssh_e)
+ self._log_console_output([server])
+ raise
+
+ def nc_client(self, ip_address, port, protocol):
+ """Check connectivity to TCP/UDP port at host via nc.
+
+ Client is always executed locally on host where tests are executed.
+ """
+ udp = ''
+ if protocol.lower() == neutron_lib_constants.PROTO_NAME_UDP:
+ udp = '-u'
+ cmd = 'echo "knock knock" | nc -w 1 %(udp)s %(host)s %(port)s' % {
+ 'udp': udp, 'host': ip_address, 'port': port}
+ result = shell.execute_local_command(cmd)
+ self.assertEqual(0, result.exit_status)
+ return result.stdout
diff --git a/neutron_tempest_plugin/scenario/test_multicast.py b/neutron_tempest_plugin/scenario/test_multicast.py
index 9b79582..d511b3b 100644
--- a/neutron_tempest_plugin/scenario/test_multicast.py
+++ b/neutron_tempest_plugin/scenario/test_multicast.py
@@ -229,6 +229,7 @@
server['ssh_client'].execute_script(
'echo "%s" > ~/multicast_traffic_receiver.py' % check_script)
+ @utils.unstable_test("bug 1850288")
@decorators.idempotent_id('113486fc-24c9-4be4-8361-03b1c9892867')
def test_multicast_between_vms_on_same_network(self):
"""Test multicast messaging between two servers on the same network
diff --git a/neutron_tempest_plugin/scenario/test_port_forwardings.py b/neutron_tempest_plugin/scenario/test_port_forwardings.py
index 3715fad..06f175b 100644
--- a/neutron_tempest_plugin/scenario/test_port_forwardings.py
+++ b/neutron_tempest_plugin/scenario/test_port_forwardings.py
@@ -13,10 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
+from neutron_lib import constants
from oslo_log import log
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
+from neutron_tempest_plugin.common import ssh
+from neutron_tempest_plugin.common import utils
from neutron_tempest_plugin import config
from neutron_tempest_plugin.scenario import base
@@ -42,12 +45,13 @@
cls.create_loginable_secgroup_rule(secgroup_id=cls.secgroup['id'])
cls.keypair = cls.create_keypair()
- @decorators.idempotent_id('ab40fc48-ca8d-41a0-b2a3-f6679c847bfe')
- def test_port_forwarding_to_2_servers(self):
- internal_tcp_port = 22
+ def _prepare_resources(self, num_servers, internal_tcp_port, protocol):
servers = []
- for i in range(1, 3):
- external_tcp_port = 1000 + i
+ external_port_base = 1025
+ for i in range(1, num_servers + 1):
+ internal_udp_port = internal_tcp_port + 10
+ external_tcp_port = external_port_base + i
+ external_udp_port = external_tcp_port + 10
name = data_utils.rand_name("server-%s" % i)
port = self.create_port(
self.network,
@@ -59,13 +63,56 @@
networks=[{'port': port['id']}])['server']
server['name'] = name
self.wait_for_server_active(server)
- server['port_forwarding'] = self.create_port_forwarding(
+ server['port_forwarding_tcp'] = self.create_port_forwarding(
self.fip['id'],
internal_port_id=port['id'],
internal_ip_address=port['fixed_ips'][0]['ip_address'],
internal_port=internal_tcp_port,
external_port=external_tcp_port,
- protocol="tcp")
+ protocol=constants.PROTO_NAME_TCP)
+ server['port_forwarding_udp'] = self.create_port_forwarding(
+ self.fip['id'],
+ internal_port_id=port['id'],
+ internal_ip_address=port['fixed_ips'][0]['ip_address'],
+ internal_port=internal_udp_port,
+ external_port=external_udp_port,
+ protocol=constants.PROTO_NAME_UDP)
servers.append(server)
+ return servers
+ def _test_udp_port_forwarding(self, servers):
+ for server in servers:
+ msg = "%s-UDP-test" % server['name']
+ ssh_client = ssh.Client(
+ self.fip['floating_ip_address'],
+ CONF.validation.image_ssh_user,
+ pkey=self.keypair['private_key'],
+ port=server['port_forwarding_tcp']['external_port'])
+ self.nc_listen(server,
+ ssh_client,
+ server['port_forwarding_udp']['internal_port'],
+ constants.PROTO_NAME_UDP,
+ msg)
+ for server in servers:
+ expected_msg = "%s-UDP-test" % server['name']
+ self.assertIn(
+ expected_msg, self.nc_client(
+ self.fip['floating_ip_address'],
+ server['port_forwarding_udp']['external_port'],
+ constants.PROTO_NAME_UDP))
+
+ @utils.unstable_test("bug 1850800")
+ @decorators.idempotent_id('ab40fc48-ca8d-41a0-b2a3-f6679c847bfe')
+ def test_port_forwarding_to_2_servers(self):
+ udp_sg_rule = {'protocol': constants.PROTO_NAME_UDP,
+ 'direction': constants.INGRESS_DIRECTION,
+ 'remote_ip_prefix': '0.0.0.0/0'}
+ self.create_secgroup_rules(
+ [udp_sg_rule], secgroup_id=self.secgroup['id'])
+ servers = self._prepare_resources(
+ num_servers=2, internal_tcp_port=22,
+ protocol=constants.PROTO_NAME_TCP)
+ # Test TCP port forwarding by SSH to each server
self.check_servers_hostnames(servers)
+ # And now test UDP port forwarding using nc
+ self._test_udp_port_forwarding(servers)
diff --git a/tox.ini b/tox.ini
index bba37bb..95352a2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,7 +14,7 @@
install_command =
pip install {opts} {packages}
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/test-requirements.txt
commands = stestr run --slowest {posargs}