Merge pull request #1277 from fnordahl/add-lxd-support

Add basic support for LXD as substrate.
This commit is contained in:
James Page
2024-10-14 17:09:21 +01:00
committed by GitHub
3 changed files with 75 additions and 1 deletions

View File

@@ -66,6 +66,7 @@ DEFAULT_UNDERCLOUD_NETWORK_CONFIG = {
"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,12 @@ 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" or provider_type is None:
# NOTE(fnordahl): When juju is bootstrapped towards the special
# `localhost` LXD cloud, get_provider_type() has no `clouds.yaml` to
# inspect and returns None.
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.'

View File

@@ -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:

View File

@@ -25,6 +25,7 @@ import itertools
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):