Merge "Fix support of IPv6 only networks in OVN metadata agent" into stable/2024.1

This commit is contained in:
Zuul 2024-08-29 00:55:56 +00:00 committed by Gerrit Code Review
commit 3b95423d99
2 changed files with 41 additions and 17 deletions
neutron
agent/ovn/metadata
tests/unit/agent/ovn/metadata

@ -617,9 +617,10 @@ class MetadataAgent(object):
iptables_mgr.ipv4['mangle'].add_rule('POSTROUTING', rule, wrap=False)
iptables_mgr.apply()
def _get_port_ip4_ips(self, port):
def _get_port_ip4_ips_and_ip6_flag(self, port):
# Retrieve IPv4 addresses from the port mac column which is in form
# ["<port_mac> <ip1> <ip2> ... <ipN>"]
# ["<port_mac> <ip1> <ip2> ... <ipN>"]. Also return True if the port
# has at least one IPv6 address
if not port.mac:
LOG.warning("Port %s MAC column is empty, cannot retrieve IP "
"addresses", port.uuid)
@ -629,10 +630,17 @@ class MetadataAgent(object):
if not ips:
LOG.debug("Port %s IP addresses were not retrieved from the "
"Port_Binding MAC column %s", port.uuid, mac_field_attrs)
return [ip for ip in ips if (
utils.get_ip_version(ip) == n_const.IP_VERSION_4)]
ip4_ips = []
any_ip6 = False
for ip in ips:
if utils.get_ip_version(ip) == n_const.IP_VERSION_4:
ip4_ips.append(ip)
else:
any_ip6 = True
return ip4_ips, any_ip6
def _active_subnets_cidrs(self, datapath_ports_ips, metadata_port_cidrs):
def _active_subnets_cidrs(self, datapath_ports_ip4_ips,
metadata_port_cidrs):
active_subnets_cidrs = set()
# Prepopulate a dictionary where each metadata_port_cidr(string) maps
# to its netaddr.IPNetwork object. This is so we dont have to
@ -642,7 +650,7 @@ class MetadataAgent(object):
for metadata_port_cidr in metadata_port_cidrs if metadata_port_cidr
}
for datapath_port_ip in datapath_ports_ips:
for datapath_port_ip in datapath_ports_ip4_ips:
ip_obj = netaddr.IPAddress(datapath_port_ip)
for metadata_cidr, metadata_cidr_obj in \
metadata_cidrs_to_network_objects.items():
@ -652,9 +660,10 @@ class MetadataAgent(object):
return active_subnets_cidrs
def _process_cidrs(self, current_namespace_cidrs,
datapath_ports_ips, metadata_port_subnet_cidrs, lla):
datapath_ports_ip4_ips,
metadata_port_subnet_cidrs, lla):
active_subnets_cidrs = self._active_subnets_cidrs(
datapath_ports_ips, metadata_port_subnet_cidrs)
datapath_ports_ip4_ips, metadata_port_subnet_cidrs)
cidrs_to_add = active_subnets_cidrs - current_namespace_cidrs
@ -713,18 +722,22 @@ class MetadataAgent(object):
chassis_ports = self.sb_idl.get_ports_on_chassis(
self._chassis, include_additional_chassis=True)
datapath_ports_ips = []
datapath_ports_ip4_ips = []
any_ip6 = False
for chassis_port in self._vif_ports(chassis_ports):
if str(chassis_port.datapath.uuid) == datapath_uuid:
datapath_ports_ips.extend(self._get_port_ip4_ips(chassis_port))
ip4_ips, ip6_flag = self._get_port_ip4_ips_and_ip6_flag(
chassis_port)
datapath_ports_ip4_ips.extend(ip4_ips)
any_ip6 = any_ip6 or ip6_flag
if not datapath_ports_ips:
if not (datapath_ports_ip4_ips or any_ip6):
LOG.debug("No valid VIF ports were found for network %s, "
"tearing the namespace down if needed", net_name)
self.teardown_datapath(net_name)
return
return net_name, datapath_ports_ips, metadata_port_info
return net_name, datapath_ports_ip4_ips, metadata_port_info
def provision_datapath(self, port_binding):
"""Provision the datapath so that it can serve metadata.
@ -744,7 +757,7 @@ class MetadataAgent(object):
provision_params = self._get_provision_params(datapath)
if not provision_params:
return
net_name, datapath_ports_ips, metadata_port_info = provision_params
net_name, datapath_ports_ip4_ips, metadata_port_info = provision_params
LOG.info("Provisioning metadata for network %s", net_name)
# Create the VETH pair if it's not created. Also the add_veth function
@ -780,7 +793,7 @@ class MetadataAgent(object):
cidrs_to_add, cidrs_to_delete = self._process_cidrs(
{dev['cidr'] for dev in ip2.addr.list()},
datapath_ports_ips,
datapath_ports_ip4_ips,
metadata_port_info.ip_addresses,
ip_lib.get_ipv6_lladdr(metadata_port_info.mac)
)

@ -30,6 +30,7 @@ from neutron.agent.linux import utils as linux_utils
from neutron.agent.ovn.metadata import agent
from neutron.agent.ovn.metadata import driver
from neutron.common.ovn import constants as ovn_const
from neutron.common import utils
from neutron.conf.agent.metadata import config as meta_conf
from neutron.conf.agent.ovn.metadata import config as ovn_meta_conf
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
@ -357,12 +358,12 @@ class TestMetadataAgent(base.BaseTestCase):
self.assertIsNone(self.agent._get_provision_params(datapath))
tdp.assert_called_once_with(network_id)
def test__get_provision_params_returns_provision_parameters(self):
def _test__get_provision_params_returns_provision_parameters(self,
port_ip):
"""The happy path when datapath has ports with "external" or ""(blank)
types and metadata port contains MAC and subnet CIDRs.
"""
network_id = '1'
port_ip = '1.2.3.4'
metada_port_mac = "fa:16:3e:22:65:18"
metada_port_subnet_cidr = "10.204.0.10/29"
metada_port_logical_port = "3b66c176-199b-48ec-8331-c1fd3f6e2b44"
@ -388,13 +389,23 @@ class TestMetadataAgent(base.BaseTestCase):
net_name, datapath_port_ips, metadata_port_info = actual_params
self.assertEqual(network_id, net_name)
self.assertListEqual([port_ip], datapath_port_ips)
if utils.get_ip_version(port_ip) == n_const.IP_VERSION_4:
self.assertListEqual([port_ip], datapath_port_ips)
self.assertEqual(metada_port_mac, metadata_port_info.mac)
self.assertSetEqual(set([metada_port_subnet_cidr]),
metadata_port_info.ip_addresses)
self.assertEqual(metada_port_logical_port,
metadata_port_info.logical_port)
def test__get_provision_params_returns_provision_parameters(self):
self._test__get_provision_params_returns_provision_parameters(
'1.2.3.4')
def test__get_provision_params_returns_provision_parameters_ipv6(self):
self._test__get_provision_params_returns_provision_parameters(
'fe80::f816:3eff:feb6:c0c0')
def test_provision_datapath(self):
"""Test datapath provisioning.