Merge "Add both IPv4 and IPv6 DHCP options if interface has both"

This commit is contained in:
Zuul 2021-02-28 02:54:46 +00:00 committed by Gerrit Code Review
commit 17cf7807a5
3 changed files with 85 additions and 20 deletions

@ -64,28 +64,28 @@ class NeutronDHCPApi(base.BaseDHCP):
try:
neutron_client = neutron.get_client(token=token, context=context)
fip = None
fips = []
port = neutron_client.get_port(port_id)
try:
if port:
# TODO(TheJulia): We need to retool this down the
# road so that we handle ports and allow preferences
# for multi-address ports with different IP versions
# and enable operators to possibly select preferences
# for provisionioning operations.
# This is compounded by v6 mainly only being available
# with UEFI machines, so the support matrix also gets
# a little "weird".
# Ideally, we should work on this in Victoria.
fip = port.get('fixed_ips')[0]
except (TypeError, IndexError):
fip = None
if port:
# TODO(TheJulia): We need to retool this down the
# road so that we handle ports and allow preferences
# for multi-address ports with different IP versions
# and enable operators to possibly select preferences
# for provisionioning operations.
# This is compounded by v6 mainly only being available
# with UEFI machines, so the support matrix also gets
# a little "weird".
# Ideally, we should work on this in Victoria.
fips = port.get('fixed_ips')
update_opts = []
if fip:
ip_version = ipaddress.ip_address(fip['ip_address']).version
for option in dhcp_options:
if option.get('ip_version', 4) == ip_version:
update_opts.append(option)
if len(fips) != 0:
for fip in fips:
ip_version = \
ipaddress.ip_address(fip['ip_address']).version
for option in dhcp_options:
if option.get('ip_version', 4) == ip_version:
update_opts.append(option)
else:
LOG.error('Requested to update port for port %s, '
'however port lacks an IP address.', port_id)

@ -119,6 +119,66 @@ class TestNeutron(db_base.DbTestCase):
update_mock.assert_called_once_with(
task.context, port_id, expected)
@mock.patch('ironic.common.neutron.get_client', autospec=True)
@mock.patch('ironic.common.neutron.update_neutron_port', autospec=True)
def test_update_port_dhcp_opts_v4_and_v6(self, update_mock, client_mock):
opts = [{'opt_name': 'bootfile-name',
'opt_value': 'pxelinux.0',
'ip_version': 4},
{'opt_name': 'tftp-server',
'opt_value': '1.1.1.1',
'ip_version': 4},
{'opt_name': 'server-ip-address',
'opt_value': '1.1.1.1',
'ip_version': 4},
{'opt_name': 'bootfile-url',
'opt_value': 'tftp://::1/file.name',
'ip_version': 6}]
port_id = 'fake-port-id'
expected = {
'extra_dhcp_opts': [
{
'opt_name': 'bootfile-name',
'opt_value': 'pxelinux.0',
'ip_version': 4
},
{
'opt_name': 'tftp-server',
'opt_value': '1.1.1.1',
'ip_version': 4
},
{
'opt_name': 'server-ip-address',
'opt_value': '1.1.1.1',
'ip_version': 4
},
{
'opt_name': 'bootfile-url',
'opt_value': 'tftp://::1/file.name',
'ip_version': 6
}
]
}
port_data = {
"id": port_id,
"fixed_ips": [
{
"ip_address": "192.168.1.3",
},
{
"ip_address": "2001:db8::201",
}
],
}
client_mock.return_value.get_port.return_value = port_data
api = dhcp_factory.DHCPFactory()
with task_manager.acquire(self.context, self.node.uuid) as task:
api.provider.update_port_dhcp_opts(port_id, opts,
context=task.context)
update_mock.assert_called_once_with(
task.context, port_id, expected)
@mock.patch('ironic.common.neutron.get_client', autospec=True)
@mock.patch('ironic.common.neutron.update_neutron_port', autospec=True)
def test_update_port_dhcp_opts_with_exception(self, update_mock,

@ -0,0 +1,5 @@
---
fixes:
- When using the Neutron DHCP driver, Ironic would only use the first fixed
IP address to determine what IP versions are use on the port. Now, it
checks for all the IP addresses and adds DHCP options for all IP versions.