neutron-tempest-plugin/neutron_tempest_plugin/scenario/test_vlan_transparency.py
Ihar Hrachyshka 2d66355407 refactor: don't require host= for check_connectivity
When ssh_client is passed, the argument is not used.

Change-Id: Ibf73130fbf82c2ed85e16b3f69aacbc2930efb3d
2024-08-26 12:48:07 -04:00

185 lines
7.9 KiB
Python

# Copyright (c) 2020 Red Hat, Inc.
#
# 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 oslo_log import log as logging
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from neutron_tempest_plugin.common import ip
from neutron_tempest_plugin.common import ssh
from neutron_tempest_plugin import config
from neutron_tempest_plugin.scenario import base
LOG = logging.getLogger(__name__)
CONF = config.CONF
MIN_VLAN_ID = 1
MAX_VLAN_ID = 4094
class VlanTransparencyTest(base.BaseTempestTestCase):
credentials = ['primary', 'admin']
force_tenant_isolation = False
required_extensions = ['vlan-transparent', 'allowed-address-pairs']
@classmethod
def resource_setup(cls):
super(VlanTransparencyTest, cls).resource_setup()
# setup basic topology for servers we can log into
cls.rand_name = data_utils.rand_name(
cls.__name__.rsplit('.', 1)[-1])
cls.network = cls.create_network(name=cls.rand_name,
vlan_transparent=True)
cls.subnet = cls.create_subnet(network=cls.network,
name=cls.rand_name)
cls.router = cls.create_router_by_client()
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
cls.keypair = cls.create_keypair(name=cls.rand_name)
cls.vm_ports = []
cls.security_group = cls.create_security_group(name=cls.rand_name)
cls.create_loginable_secgroup_rule(cls.security_group['id'])
if CONF.neutron_plugin_options.default_image_is_advanced:
cls.flavor_ref = CONF.compute.flavor_ref
cls.image_ref = CONF.compute.image_ref
else:
cls.flavor_ref = \
CONF.neutron_plugin_options.advanced_image_flavor_ref
cls.image_ref = CONF.neutron_plugin_options.advanced_image_ref
@classmethod
def skip_checks(cls):
super(VlanTransparencyTest, cls).skip_checks()
if not (CONF.neutron_plugin_options.advanced_image_ref or
CONF.neutron_plugin_options.default_image_is_advanced):
raise cls.skipException(
'Advanced image is required to run these tests.')
def _create_port_and_server(self, index,
port_security=True,
allowed_address_pairs=None):
server_name = 'server-%s-%d' % (self.rand_name, index)
port_name = 'port-%s-%d' % (self.rand_name, index)
if port_security:
sec_groups = [self.security_group['id']]
else:
sec_groups = None
self.vm_ports.append(
self.create_port(network=self.network, name=port_name,
security_groups=sec_groups,
port_security_enabled=port_security,
allowed_address_pairs=allowed_address_pairs))
return self.create_server(flavor_ref=self.flavor_ref,
image_ref=self.image_ref,
key_name=self.keypair['name'],
networks=[{'port': self.vm_ports[-1]['id']}],
name=server_name)['server']
def _configure_vlan_transparent(self, port, ssh_client,
vlan_tag, vlan_ip):
ip_command = ip.IPCommand(ssh_client=ssh_client)
addresses = ip_command.list_addresses(port=port)
port_iface = ip.get_port_device_name(addresses, port)
subport_iface = ip_command.configure_vlan_transparent(
port=port, vlan_tag=vlan_tag, ip_addresses=[vlan_ip])
for address in ip_command.list_addresses(ip_addresses=vlan_ip):
self.assertEqual(subport_iface, address.device.name)
self.assertEqual(port_iface, address.device.parent)
break
else:
self.fail("Sub-port fixed IP not found on server.")
def _create_ssh_client(self, floating_ip):
if CONF.neutron_plugin_options.default_image_is_advanced:
username = CONF.validation.image_ssh_user
else:
username = CONF.neutron_plugin_options.advanced_image_ssh_user
return ssh.Client(host=floating_ip['floating_ip_address'],
username=username,
pkey=self.keypair['private_key'])
def _test_basic_vlan_transparency_connectivity(
self, port_security=True, use_allowed_address_pairs=False):
vlan_tag = data_utils.rand_int_id(start=MIN_VLAN_ID, end=MAX_VLAN_ID)
vlan_ipmask_template = '192.168.%d.{ip_last_byte}/24' % (vlan_tag %
256)
vms = []
vlan_ipmasks = []
floating_ips = []
ssh_clients = []
for i in range(2):
vlan_ipmasks.append(vlan_ipmask_template.format(
ip_last_byte=(i + 1) * 10))
if use_allowed_address_pairs:
allowed_address_pairs = [{'ip_address': vlan_ipmasks[i]}]
else:
allowed_address_pairs = None
vms.append(self._create_port_and_server(
index=i,
port_security=port_security,
allowed_address_pairs=allowed_address_pairs))
floating_ips.append(self.create_floatingip(port=self.vm_ports[-1]))
ssh_clients.append(
self._create_ssh_client(floating_ip=floating_ips[i]))
self.check_connectivity(ssh_client=ssh_clients[i])
self._configure_vlan_transparent(port=self.vm_ports[-1],
ssh_client=ssh_clients[i],
vlan_tag=vlan_tag,
vlan_ip=vlan_ipmasks[i])
if port_security:
# Ping from vm0 to vm1 via VLAN interface should fail because
# we haven't allowed ICMP
self.check_remote_connectivity(
ssh_clients[0],
vlan_ipmasks[1].split('/')[0],
servers=vms,
should_succeed=False)
# allow intra-security-group traffic
sg_rule = self.create_pingable_secgroup_rule(
self.security_group['id'])
self.addCleanup(
self.os_primary.network_client.delete_security_group_rule,
sg_rule['id'])
# Ping from vm0 to vm1 via VLAN interface should pass because
# either port security is disabled or the ICMP sec group rule has been
# added
self.check_remote_connectivity(
ssh_clients[0],
vlan_ipmasks[1].split('/')[0],
servers=vms)
# Ping from vm1 to vm0 and check untagged packets are not dropped
self.check_remote_connectivity(
ssh_clients[1],
self.vm_ports[-2]['fixed_ips'][0]['ip_address'],
servers=vms)
@decorators.idempotent_id('a2694e3a-6d4d-4a23-9fcc-c3ed3ef37b16')
def test_vlan_transparent_port_sec_disabled(self):
self._test_basic_vlan_transparency_connectivity(
port_security=False, use_allowed_address_pairs=False)
@decorators.idempotent_id('2dd03b4f-9c20-4cda-8c6a-40fa453ec69a')
def test_vlan_transparent_allowed_address_pairs(self):
self._test_basic_vlan_transparency_connectivity(
port_security=True, use_allowed_address_pairs=True)