Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable/yoga] Backport #746 #1083

Merged
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ dist/
zaza.openstack.egg-info/
.coverage
.vscode/
*.swp
# Sphinx
doc/build
14 changes: 14 additions & 0 deletions unit_tests/utilities/test_zaza_utilities_openstack.py
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,20 @@ def test_configure_charmed_openstack_on_maas(self):
self.configure_networking_charms.assert_called_once_with(
'fakenetworkingdata', expect, use_juju_wait=False)

def test_update_subnet_dhcp(self):
neutron_client = mock.MagicMock()
openstack_utils.update_subnet_dhcp(
neutron_client, {'id': 'aId'}, True)
neutron_client.update_subnet.assert_called_once_with(
'aId',
{'subnet': {'enable_dhcp': True}})
neutron_client.reset_mock()
openstack_utils.update_subnet_dhcp(
neutron_client, {'id': 'aId'}, False)
neutron_client.update_subnet.assert_called_once_with(
'aId',
{'subnet': {'enable_dhcp': False}})


class TestAsyncOpenstackUtils(ut_utils.AioTestCase):

Expand Down
43 changes: 31 additions & 12 deletions zaza/openstack/charm_tests/neutron/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"prefix_len": "24",
"subnetpool_name": "pooled_subnets",
"subnetpool_prefix": "192.168.0.0/16",
"project_net_name": "private",
"project_subnet_name": "private_subnet",
}

OVERCLOUD_PROVIDER_VLAN_NETWORK_CONFIG = {
Expand All @@ -67,29 +69,19 @@
}


def basic_overcloud_network(limit_gws=None):
"""Run setup for neutron networking.

Configure the following:
The overcloud network using subnet pools
def undercloud_and_charm_setup(limit_gws=None):
"""Perform undercloud and charm setup for network plumbing.

:param limit_gws: Limit the number of gateways that get a port attached
:type limit_gws: int
"""
cli_utils.setup_logging()

# Get network configuration settings
network_config = {}
# Declared overcloud settings
network_config.update(OVERCLOUD_NETWORK_CONFIG)
# Default undercloud settings
network_config.update(DEFAULT_UNDERCLOUD_NETWORK_CONFIG)
# Environment specific settings
network_config.update(generic_utils.get_undercloud_env_vars())

# Get keystone session
keystone_session = openstack_utils.get_overcloud_keystone_session()

# Get optional use_juju_wait for network option
options = (lifecycle_utils
.get_charm_config(fatal=False)
Expand Down Expand Up @@ -118,6 +110,33 @@ def basic_overcloud_network(limit_gws=None):
' charm network configuration.'
.format(provider_type))


def basic_overcloud_network(limit_gws=None):
"""Run setup for neutron networking.

Configure the following:
The overcloud network using subnet pools

:param limit_gws: Limit the number of gateways that get a port attached
:type limit_gws: int
"""
cli_utils.setup_logging()

# Get network configuration settings
network_config = {}
# Declared overcloud settings
network_config.update(OVERCLOUD_NETWORK_CONFIG)
# Default undercloud settings
network_config.update(DEFAULT_UNDERCLOUD_NETWORK_CONFIG)
# Environment specific settings
network_config.update(generic_utils.get_undercloud_env_vars())

# Get keystone session
keystone_session = openstack_utils.get_overcloud_keystone_session()

# Perform undercloud and charm setup for network plumbing
undercloud_and_charm_setup(limit_gws=limit_gws)

# Configure the overcloud network
network.setup_sdn(network_config, keystone_session=keystone_session)

Expand Down
130 changes: 112 additions & 18 deletions zaza/openstack/charm_tests/neutron/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@

import yaml
import zaza
import zaza.openstack.charm_tests.neutron.setup as neutron_setup
import zaza.openstack.charm_tests.nova.utils as nova_utils
import zaza.openstack.charm_tests.test_utils as test_utils
import zaza.openstack.configure.guest as guest
import zaza.openstack.utilities.openstack as openstack_utils
import zaza.utilities.machine_os


class NeutronPluginApiSharedTests(test_utils.OpenStackBaseTest):
Expand Down Expand Up @@ -805,6 +807,11 @@ def test_800_ovs_bridges_are_managed_by_us(self):
self.assertEqual(actual_external_id, expected_external_id)


def router_address_from_subnet(subnet):
"""Retrieve router address from subnet."""
return subnet['gateway_ip']


class NeutronNetworkingBase(test_utils.OpenStackBaseTest):
"""Base for checking openstack instances have valid networking."""

Expand All @@ -818,6 +825,21 @@ def setUpClass(cls):
cls.neutron_client = (
openstack_utils.get_neutron_session_client(cls.keystone_session))

cls.project_subnet = cls.neutron_client.find_resource(
'subnet',
neutron_setup.OVERCLOUD_NETWORK_CONFIG['project_subnet_name'])
cls.external_subnet = cls.neutron_client.find_resource(
'subnet',
neutron_setup.OVERCLOUD_NETWORK_CONFIG['external_subnet_name'])

# Override this if you want your test to attach instances directly to
# the external provider network
cls.attach_to_external_network = False

# Override this if you want your test to launch instances with a
# specific flavor
cls.instance_flavor = None

@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60),
reraise=True, stop=tenacity.stop_after_attempt(8))
def validate_instance_can_reach_other(self,
Expand All @@ -840,8 +862,10 @@ def validate_instance_can_reach_other(self,
:param mtu: Check that we can send non-fragmented packets of given size
:type mtu: Optional[int]
"""
floating_1 = floating_ips_from_instance(instance_1)[0]
floating_2 = floating_ips_from_instance(instance_2)[0]
if not self.attach_to_external_network:
floating_1 = floating_ips_from_instance(instance_1)[0]
floating_2 = floating_ips_from_instance(instance_2)[0]
address_1 = fixed_ips_from_instance(instance_1)[0]
address_2 = fixed_ips_from_instance(instance_2)[0]

username = guest.boot_tests['bionic']['username']
Expand All @@ -859,27 +883,28 @@ def validate_instance_can_reach_other(self,
'ping -M do -s {} -c 1'.format(packetsize))

for cmd in cmds:
openstack_utils.ssh_command(
username, floating_1, 'instance-1',
'{} {}'.format(cmd, address_2),
password=password, privkey=privkey, verify=verify)
if self.attach_to_external_network:
openstack_utils.ssh_command(
username, address_1, 'instance-1',
'{} {}'.format(cmd, address_2),
password=password, privkey=privkey, verify=verify)
else:
openstack_utils.ssh_command(
username, floating_1, 'instance-1',
'{} {}'.format(cmd, address_2),
password=password, privkey=privkey, verify=verify)

openstack_utils.ssh_command(
username, floating_1, 'instance-1',
'{} {}'.format(cmd, floating_2),
password=password, privkey=privkey, verify=verify)
openstack_utils.ssh_command(
username, floating_1, 'instance-1',
'{} {}'.format(cmd, floating_2),
password=password, privkey=privkey, verify=verify)

@tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60),
reraise=True, stop=tenacity.stop_after_attempt(8))
def validate_instance_can_reach_router(self, instance, verify, mtu=None):
"""
Validate that an instance can reach it's primary gateway.

We make the assumption that the router's IP is 192.168.0.1
as that's the network that is setup in
neutron.setup.basic_overcloud_network which is used in all
Zaza Neutron validations.

:param instance: The instance to check networking from
:type instance: nova_client.Server

Expand All @@ -889,7 +914,12 @@ def validate_instance_can_reach_router(self, instance, verify, mtu=None):
:param mtu: Check that we can send non-fragmented packets of given size
:type mtu: Optional[int]
"""
address = floating_ips_from_instance(instance)[0]
if self.attach_to_external_network:
router = router_address_from_subnet(self.external_subnet)
address = fixed_ips_from_instance(instance)[0]
else:
router = router_address_from_subnet(self.project_subnet)
address = floating_ips_from_instance(instance)[0]

username = guest.boot_tests['bionic']['username']
password = guest.boot_tests['bionic'].get('password')
Expand All @@ -907,7 +937,7 @@ def validate_instance_can_reach_router(self, instance, verify, mtu=None):

for cmd in cmds:
openstack_utils.ssh_command(
username, address, 'instance', '{} 192.168.0.1'.format(cmd),
username, address, 'instance', '{} {}'.format(cmd, router),
password=password, privkey=privkey, verify=verify)

@tenacity.retry(wait=tenacity.wait_exponential(min=5, max=60),
Expand Down Expand Up @@ -1086,13 +1116,77 @@ class name + run_tearDown key under the `tests_options` key in
"""
instance_1, instance_2 = self.retrieve_guests()
if not all([instance_1, instance_2]):
self.launch_guests()
self.launch_guests(
attach_to_external_network=self.attach_to_external_network,
flavor_name=self.instance_flavor)
instance_1, instance_2 = self.retrieve_guests()
self.check_connectivity(instance_1, instance_2)
self.run_resource_cleanup = self.get_my_tests_options(
'run_resource_cleanup', True)


class DPDKNeutronNetworkingTest(NeutronNetworkingTest):
"""Ensure that openstack instances have valid networking with DPDK."""

@classmethod
def setUpClass(cls):
"""Run class setup for running Neutron API Networking tests."""
super(DPDKNeutronNetworkingTest, cls).setUpClass()

# At this point in time the charms do not support configuring overlay
# networks with DPDK. To perform end to end validation we need to
# attach instances directly to the provider network and subsequently
# DHCP needs to be enabled on that network.
#
# Note that for instances wired with DPDK the DHCP request/response is
# handled as private communication between the ovn-controller and the
# instance, and as such there is no risk of rogue DHCP replies escaping
# to the surrounding network.
cls.attach_to_external_network = True
cls.instance_flavor = 'hugepages'
cls.external_subnet = cls.neutron_client.find_resource(
'subnet',
neutron_setup.OVERCLOUD_NETWORK_CONFIG['external_subnet_name'])
if ('dhcp_enabled' not in cls.external_subnet or
not cls.external_subnet['dhcp_enabled']):
logging.info('Enabling DHCP on subnet {}'
.format(cls.external_subnet['name']))
openstack_utils.update_subnet_dhcp(
cls.neutron_client, cls.external_subnet, True)

def test_instances_have_networking(self):
"""Enable DPDK then Validate North/South and East/West networking."""
self.enable_hugepages_vfio_on_hvs_in_vms(4)
with self.config_change(
{
'enable-dpdk': False,
'dpdk-driver': '',
},
{
'enable-dpdk': True,
'dpdk-driver': 'vfio-pci',
},
application_name='ovn-chassis'):
super().test_instances_have_networking()
self.run_resource_cleanup = self.get_my_tests_options(
'run_resource_cleanup', True)

def resource_cleanup(self):
"""Extend to also revert VFIO NOIOMMU mode on units under test."""
super().resource_cleanup()
if not self.run_resource_cleanup:
return

if ('dhcp_enabled' not in self.external_subnet or
not self.external_subnet['dhcp_enabled']):
logging.info('Disabling DHCP on subnet {}'
.format(self.external_subnet['name']))
openstack_utils.update_subnet_dhcp(
self.neutron_client, self.external_subnet, False)

self.disable_hugepages_vfio_on_hvs_in_vms()


class NeutronNetworkingVRRPTests(NeutronNetworkingBase):
"""Check networking when gateways are restarted."""

Expand Down
9 changes: 9 additions & 0 deletions zaza/openstack/charm_tests/nova/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,14 @@
'hw:tpm_model': 'tpm-crb',
},
},
'hugepages': {
'flavorid': 'auto',
'ram': 1024,
'disk': 20,
'vcpus': 1,
'extra-specs': {
'hw:mem_page_size': 'large',
},
},
}
KEYPAIR_NAME = 'zaza'
Loading
Loading