diff --git a/nova/network/neutron.py b/nova/network/neutron.py index e6d47c9a6b39..f37f8a343a6f 100644 --- a/nova/network/neutron.py +++ b/nova/network/neutron.py @@ -3610,6 +3610,7 @@ class API: 'gateway': network_model.IP( address=subnet['gateway_ip'], type='gateway'), + 'enable_dhcp': False, } if subnet.get('ipv6_address_mode'): subnet_dict['ipv6_address_mode'] = subnet['ipv6_address_mode'] @@ -3626,22 +3627,14 @@ class API: subnet_dict['dhcp_server'] = ip_pair['ip_address'] break - # NOTE(arnaudmorin): If enable_dhcp is set on subnet, but, for - # some reason neutron did not have any DHCP port yet, we still - # want the network_info to be populated with a valid dhcp_server - # value. This is mostly useful for the metadata API (which is - # relying on this value to give network_data to the instance). - # - # This will also help some providers which are using external - # DHCP servers not handled by neutron. - # In this case, neutron will never create any DHCP port in the - # subnet. - # - # Also note that we cannot set the value to None because then the - # value would be discarded by the metadata API. - # So the subnet gateway will be used as fallback. - if subnet.get('enable_dhcp') and 'dhcp_server' not in subnet_dict: - subnet_dict['dhcp_server'] = subnet['gateway_ip'] + # NOTE(stblatzheim): If enable_dhcp is set on subnet, but subnet + # has ovn native dhcp and no dhcp-agents. Network owner will be + # network:distributed + # Just rely on enable_dhcp flag given by neutron + # Fix for https://bugs.launchpad.net/nova/+bug/2055245 + + if subnet.get('enable_dhcp'): + subnet_dict['enable_dhcp'] = True subnet_object = network_model.Subnet(**subnet_dict) for dns in subnet.get('dns_nameservers', []): diff --git a/nova/tests/unit/network/test_neutron.py b/nova/tests/unit/network/test_neutron.py index 0789022cfae1..a9aa501a1346 100644 --- a/nova/tests/unit/network/test_neutron.py +++ b/nova/tests/unit/network/test_neutron.py @@ -3615,8 +3615,8 @@ class TestAPI(TestAPIBase): subnets = self.api._get_subnets_from_port(self.context, port_data) - self.assertEqual(subnet_data1[0]['gateway_ip'], - subnets[0]['meta']['dhcp_server']) + self.assertEqual(subnet_data1[0]['enable_dhcp'], + subnets[0]['meta']['enable_dhcp']) @mock.patch.object(neutronapi, 'get_client', return_value=mock.Mock()) def test_get_physnet_tunneled_info_multi_segment(self, mock_get_client): diff --git a/nova/virt/netutils.py b/nova/virt/netutils.py index 0ab3ddc4c112..2bc78134a175 100644 --- a/nova/virt/netutils.py +++ b/nova/virt/netutils.py @@ -289,7 +289,8 @@ def _get_nets(vif, subnet, version, net_num, link_id): net_type = '' if subnet.get_meta('ipv6_address_mode') is not None: net_type = '_%s' % subnet.get_meta('ipv6_address_mode') - elif subnet.get_meta('dhcp_server') is not None: + elif (subnet.get_meta('dhcp_server') is not None or + subnet.get_meta('enable_dhcp')): net_info = { 'id': 'network%d' % net_num, 'type': 'ipv%d_dhcp' % version, diff --git a/releasenotes/notes/bug-2055245-fix-nova-metadata-api-f60b18b1b594bec0.yaml b/releasenotes/notes/bug-2055245-fix-nova-metadata-api-f60b18b1b594bec0.yaml new file mode 100644 index 000000000000..9db969926add --- /dev/null +++ b/releasenotes/notes/bug-2055245-fix-nova-metadata-api-f60b18b1b594bec0.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + With the change from ml2/ovs DHCP agents towards OVN implementation + in neutron there is no port with device_owner ``network:dhcp`` anymore. + Instead DHCP is provided by ``network:distributed`` port. + Fix relies on enable_dhcp provided by neutron-api if no port with + ``network:dhcp`` owner is found. See `bug 2055245 + `__ for details.