[OVN] Explicitly define the fixed IPs for the metadata port

The metadata port fixed IPs depend on the subnets "enabled_dhcp" flag.
If the subnet has this flag disabled, the metadata port doesn't receive
an IP on the subnet CIDR.

The method ``create_metadata_port`` should explicitly define what fixed
IPs should request the metadata port during the creating depending on
the subnets "enabled_dhcp" flag.

Closes-Bug: #2011724
Change-Id: If362fab20ac03f8b62471b60c031f9349171ce93
(cherry picked from commit 9704dca84e)
This commit is contained in:
Rodolfo Alonso Hernandez 2023-03-15 06:29:39 +01:00
parent 37abad3e40
commit f822742af0
2 changed files with 86 additions and 9 deletions

View File

@ -2395,17 +2395,26 @@ class OVNClient(object):
return fixed_ip['ip_address']
def create_metadata_port(self, context, network):
if ovn_conf.is_ovn_metadata_enabled():
metadata_port = self._find_metadata_port(context, network['id'])
if not metadata_port:
# Create a neutron port for DHCP/metadata services
port = {'port':
{'network_id': network['id'],
if not ovn_conf.is_ovn_metadata_enabled():
return
if self._find_metadata_port(context, network['id']):
return
# Create a neutron port for DHCP/metadata services
filters = {'network_id': [network['id']]}
subnets = self._plugin.get_subnets(context, filters=filters)
fixed_ips = [{'subnet_id': s['id']}
for s in subnets if s['enable_dhcp']]
port = {'port': {'network_id': network['id'],
'tenant_id': network['project_id'],
'device_owner': const.DEVICE_OWNER_DISTRIBUTED,
'device_id': 'ovnmeta-%s' % network['id']}}
# TODO(boden): rehome create_port into neutron-lib
p_utils.create_port(self._plugin, context, port)
'device_id': 'ovnmeta-%s' % network['id'],
'fixed_ips': fixed_ips,
}
}
# TODO(boden): rehome create_port into neutron-lib
p_utils.create_port(self._plugin, context, port)
def update_metadata_port(self, context, network_id, subnet=None):
"""Update metadata port.

View File

@ -0,0 +1,68 @@
# Copyright 2023 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron_lib import constants
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf as ovn_config
from neutron.tests.functional import base
class TestOVNClient(base.TestOVNFunctionalBase):
def test_create_metadata_port(self):
def check_metadata_port(enable_dhcp):
ports = self.plugin.get_ports(
self.context, filters={'network_id': [network['id']]})
self.assertEqual(1, len(ports))
if enable_dhcp:
self.assertEqual(1, len(ports[0]['fixed_ips']))
else:
self.assertEqual(0, len(ports[0]['fixed_ips']))
return ports
ovn_config.cfg.CONF.set_override('ovn_metadata_enabled', True,
group='ovn')
ovn_client = self.mech_driver._ovn_client
for enable_dhcp in (True, False):
network_args = {'tenant_id': 'project_1',
'name': 'test_net_1',
'admin_state_up': True,
'shared': False,
'status': constants.NET_STATUS_ACTIVE}
network = self.plugin.create_network(self.context,
{'network': network_args})
subnet_args = {'tenant_id': 'project_1',
'name': 'test_snet_1',
'network_id': network['id'],
'ip_version': constants.IP_VERSION_4,
'cidr': '10.210.10.0/28',
'enable_dhcp': enable_dhcp,
'gateway_ip': constants.ATTR_NOT_SPECIFIED,
'allocation_pools': constants.ATTR_NOT_SPECIFIED,
'dns_nameservers': constants.ATTR_NOT_SPECIFIED,
'host_routes': constants.ATTR_NOT_SPECIFIED}
self.plugin.create_subnet(self.context, {'subnet': subnet_args})
# The metadata port has been created during the network creation.
ports = check_metadata_port(enable_dhcp)
# Force the deletion and creation the metadata port.
self.plugin.delete_port(self.context, ports[0]['id'])
ovn_client.create_metadata_port(self.context, network)
check_metadata_port(enable_dhcp)
# Call again the "create_metadata_port" method as is idempotent
# because it checks first if the metadata port exists.
ovn_client.create_metadata_port(self.context, network)
check_metadata_port(enable_dhcp)