From c48d7505855be8d6652fecfbe3734e1980721839 Mon Sep 17 00:00:00 2001 From: Frode Nordahl Date: Fri, 11 Oct 2024 22:52:18 +0200 Subject: [PATCH] undercloud_and_charm_setup: Add support for LXD. This adds basic LXD support that allows adding second NIC to instances hosting networking charms as well as populating said charms configuration with the second NIC MAC address. Signed-off-by: Frode Nordahl --- zaza/openstack/charm_tests/neutron/setup.py | 4 ++ zaza/openstack/utilities/generic.py | 4 +- zaza/openstack/utilities/openstack.py | 65 +++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/zaza/openstack/charm_tests/neutron/setup.py b/zaza/openstack/charm_tests/neutron/setup.py index f81590dfe..2210e1192 100644 --- a/zaza/openstack/charm_tests/neutron/setup.py +++ b/zaza/openstack/charm_tests/neutron/setup.py @@ -66,6 +66,7 @@ "external_dns": "10.5.0.2", "external_net_cidr": "10.5.0.0/16", "default_gateway": "10.5.0.1", + "lxd_network_name": "second", } # For Neutron Dynamic Tests it is useful to avoid relying on the directly @@ -116,6 +117,9 @@ def undercloud_and_charm_setup(limit_gws=None): # Perform charm based OVS configuration openstack_utils.configure_charmed_openstack_on_maas( network_config, limit_gws=limit_gws) + elif provider_type == "lxd": + openstack_utils.configure_charmed_openstack_on_lxd( + network_config, limit_gws=limit_gws) else: logging.warning('Unknown Juju provider type, "{}", will not perform' ' charm network configuration.' diff --git a/zaza/openstack/utilities/generic.py b/zaza/openstack/utilities/generic.py index fa33771bb..515aa0a21 100644 --- a/zaza/openstack/utilities/generic.py +++ b/zaza/openstack/utilities/generic.py @@ -190,6 +190,7 @@ def get_undercloud_env_vars(): _vars['external_dns'] = os.environ.get('TEST_NAME_SERVER') _vars['default_gateway'] = os.environ.get('TEST_GATEWAY') _vars['external_net_cidr'] = os.environ.get('TEST_CIDR_EXT') + _vars['lxd_network_name'] = os.environ.get('TEST_LXD_NETWORK_NAME') # Take FIP_RANGE and create start and end floating ips _fip_range = os.environ.get('TEST_FIP_RANGE') @@ -205,7 +206,8 @@ def get_undercloud_env_vars(): 'start_floating_ip', 'end_floating_ip', 'external_dns', - 'external_net_cidr'] + 'external_net_cidr', + 'lxd_network_name'] for _key in _keys: _val = os.environ.get(_key) if _val: diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index cc0a2ae38..46e8ee738 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -25,6 +25,7 @@ import json import juju_wait import logging +import netaddr import os import paramiko import pathlib @@ -1169,6 +1170,70 @@ def configure_charmed_openstack_on_maas(network_config, limit_gws=None): networking_data, macs, use_juju_wait=False) +def lxd_maybe_add_nic(instance, ifname, network): + """Add NIC to instance. + + :param instance: Name of instance. + :type instance: str + :param ifname: Name of interface inside instance, note that name is only + preserved in containers, interfaces in virtual machines are + subject to udev rules inside the instance. + :type: ifname: str + :param network: Name of network. + :type network: str + """ + try: + subprocess.check_call([ + "lxc", "config", "device", "add", instance, + ifname, "nic", "name={}".format(ifname), + "network={}".format(network)]) + except subprocess.CalledProcessError: + logging.info("Unable to add device {} to {}, already added?" + .format(ifname, instance)) + + +def lxd_get_nic_hwaddr(instance, device_name): + """Add NIC to instance. + + :param instance: Name of instance. + :type instance: str + :param device_name: Name of device config. + :type device_name: str + :rtype: netaddr.EUI + :raises: netaddr.core.AddrFormatError in the event nic does not exist. + """ + # lxc config get succeeds even for non-existing keys. + output = subprocess.check_output([ + "lxc", "config", "get", instance, + "volatile.{}.hwaddr".format(device_name)], + universal_newlines=True) + + mac = netaddr.EUI(output) + mac.dialect = netaddr.mac_unix_expanded + return mac + + +def configure_charmed_openstack_on_lxd(network_config, limit_gws=None): + """Configure networking charms for charm-based OVS config on LXD provider. + + :param network_config: Network configuration as provided in environment. + :type network_config: Dict[str] + :param limit_gws: Limit the number of gateways that get a port attached + :type limit_gws: Optional[int] + """ + networking_data = get_charm_networking_data(limit_gws=limit_gws) + ifname = "eth1" + macs = [] + for instance in networking_data.unit_machine_ids: + lxd_maybe_add_nic(instance, ifname, + network_config.get("lxd_network_name")) + macs.append(str(lxd_get_nic_hwaddr(instance, ifname))) + + if macs: + configure_networking_charms( + networking_data, macs, use_juju_wait=False) + + @tenacity.retry(wait=tenacity.wait_exponential(multiplier=1, max=60), reraise=True, retry=tenacity.retry_if_exception_type(KeyError)) def get_mac_from_port(port, neutronclient):