From c32c0af9afc3e08727f7129a93bf78bacb789201 Mon Sep 17 00:00:00 2001
From: Rodolfo Alonso Hernandez <ralonsoh@redhat.com>
Date: Tue, 7 Sep 2021 10:34:55 +0000
Subject: [PATCH] [OVN] Metadata ports device_owner is "network:distributed"
 only

Metadata ports are OVN distributed ports (localports) [1]. The
"device_owner" is set to "network:distributed". Before that,
the "device_owner" was "network:dhcp" but those ports didn't belong
to the DHCP server.

Since Wallaby, only "network:distributed" will be assigned to those
ports.

[1]https://www.ovn.org/support/dist-docs/ovn-nb.5.txt

Closes-Bug: #1942866
Change-Id: I39045276b6e083c77e6d03dc4eaa5047538c5bea
---
 neutron/common/ovn/utils.py                   | 11 -----
 .../ovn/mech_driver/ovsdb/ovn_client.py       | 43 +++++--------------
 .../ovn/mech_driver/ovsdb/ovn_db_sync.py      | 18 +++-----
 .../ovn/mech_driver/test_mech_driver.py       | 28 ------------
 4 files changed, 16 insertions(+), 84 deletions(-)

diff --git a/neutron/common/ovn/utils.py b/neutron/common/ovn/utils.py
index d14c03b5af4..7369cffc5b2 100644
--- a/neutron/common/ovn/utils.py
+++ b/neutron/common/ovn/utils.py
@@ -460,17 +460,6 @@ def is_provider_network(network):
     return network.get(external_net.EXTERNAL, False)
 
 
-def is_neutron_dhcp_agent_port(port):
-    """Check if the given DHCP port belongs to Neutron DHCP agents
-
-    The DHCP ports with the device_id equals to 'reserved_dhcp_port'
-    or starting with the word 'dhcp' belongs to the Neutron DHCP agents.
-    """
-    return (port['device_owner'] == const.DEVICE_OWNER_DHCP and
-            (port['device_id'] == const.DEVICE_ID_RESERVED_DHCP_PORT or
-             port['device_id'].startswith('dhcp')))
-
-
 def compute_address_pairs_diff(ovn_port, neutron_port):
     """Compute the differences in the allowed_address_pairs field."""
     ovn_ap = get_allowed_address_pairs_ip_addresses_from_ovn_port(
diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py
index 4f557c2be94..c3ea3296ab0 100644
--- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py
+++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py
@@ -266,14 +266,8 @@ class OVNClient(object):
                         options[ovn_const.LSP_OPTIONS_VIRTUAL_PARENTS_KEY] = (
                             ','.join(parents))
 
-            # Only adjust the OVN type if the port is not owned by Neutron
-            # DHCP agents.
-            # TODO(mjozefcz): Remove const.DEVICE_OWNER_DHCP
-            # from get_ports in W-release.
-            if (port['device_owner'] in [
-                    const.DEVICE_OWNER_DISTRIBUTED,
-                    const.DEVICE_OWNER_DHCP] and
-                    not utils.is_neutron_dhcp_agent_port(port)):
+            # Metadata port.
+            if port['device_owner'] == const.DEVICE_OWNER_DISTRIBUTED:
                 port_type = ovn_const.LSP_TYPE_LOCALPORT
 
             if utils.is_port_external(port):
@@ -2152,35 +2146,20 @@ class OVNClient(object):
 
     @staticmethod
     def is_metadata_port(port):
-        # TODO(ralonsoh): This method is implemented in order to be backported
-        # to stable releases; this is why a "const.DEVICE_OWNER_DHCP" port
-        # could be a metadata port.
-        return (port['device_owner'] == const.DEVICE_OWNER_DISTRIBUTED or
-                (port['device_owner'] == const.DEVICE_OWNER_DHCP and
-                 not utils.is_neutron_dhcp_agent_port(port)))
+        return port['device_owner'] == const.DEVICE_OWNER_DISTRIBUTED
 
     def _find_metadata_port(self, context, network_id):
         if not ovn_conf.is_ovn_metadata_enabled():
             return
 
-        # TODO(mjozefcz): Remove const.DEVICE_OWNER_DHCP
-        # from get_ports in W-release.
-        ports = self._plugin.get_ports(context, filters=dict(
-            network_id=[network_id],
-            device_owner=[
-                const.DEVICE_OWNER_DHCP,
-                const.DEVICE_OWNER_DISTRIBUTED]))
-        # TODO(mjozefcz): Remove this compatibility code in W release.
-        # First look for const.DEVICE_OWNER_DISTRIBUTED and then for
-        # const.DEVICE_OWNER_DHCP.
-        for port in ports:
-            if port['device_owner'] == const.DEVICE_OWNER_DISTRIBUTED:
-                return port
-        # Metadata ports are DHCP ports not belonging to the Neutron
-        # DHCP agents
-        for port in ports:
-            if not utils.is_neutron_dhcp_agent_port(port):
-                return port
+        ports = self._plugin.get_ports(
+            context, filters=dict(
+                network_id=[network_id],
+                device_owner=[const.DEVICE_OWNER_DISTRIBUTED]),
+            limit=1)
+
+        if ports:
+            return ports[0]
 
     def _find_metadata_port_ip(self, context, subnet):
         metadata_port = self._find_metadata_port(context, subnet['network_id'])
diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py
index 9e86474e268..9c55a082673 100644
--- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py
+++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_db_sync.py
@@ -902,21 +902,13 @@ class OvnNbSynchronizer(OvnDbSynchronizer):
         if not ovn_conf.is_ovn_metadata_enabled():
             return
         LOG.debug('OVN sync metadata ports started')
-        # TODO(mjozefcz): Remove constants.DEVICE_OWNER_DHCP
-        # from get_ports in W-release.
         for net in self.core_plugin.get_networks(ctx):
-            # Get only DHCP ports that don't belong to agent, it should return
-            # only OVN metadata ports
-            dhcp_ports = [
-                p for p in self.core_plugin.get_ports(
+            metadata_ports = self.core_plugin.get_ports(
                     ctx, filters=dict(
                         network_id=[net['id']],
-                        device_owner=[
-                            constants.DEVICE_OWNER_DISTRIBUTED,
-                            constants.DEVICE_OWNER_DHCP]))
-                if not utils.is_neutron_dhcp_agent_port(p)]
+                        device_owner=[constants.DEVICE_OWNER_DISTRIBUTED]))
 
-            if not dhcp_ports:
+            if not metadata_ports:
                 LOG.warning('Missing metadata port found in Neutron for '
                             'network %s', net['id'])
                 if self.mode == SYNC_MODE_REPAIR:
@@ -933,7 +925,7 @@ class OvnNbSynchronizer(OvnDbSynchronizer):
             else:
                 # Delete all but one DHCP ports. Only one is needed for
                 # metadata.
-                for port in dhcp_ports[1:]:
+                for port in metadata_ports[1:]:
                     LOG.warning('Unnecessary DHCP port %s for network %s '
                                 'found in Neutron', port['id'], net['id'])
                     if self.mode == SYNC_MODE_REPAIR:
@@ -941,7 +933,7 @@ class OvnNbSynchronizer(OvnDbSynchronizer):
                                     'network %s', port['id'], net['id'])
                         self.core_plugin.delete_port(ctx, port['id'])
                     db_ports.pop(port['id'], None)
-                port = dhcp_ports[0]
+                port = metadata_ports[0]
                 if port['id'] in db_ports.keys():
                     LOG.warning('Metadata port %s for network %s found in '
                                 'Neutron but not in OVN',
diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py
index 33b56bcab31..3b791137e88 100644
--- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py
+++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/test_mech_driver.py
@@ -3447,34 +3447,6 @@ class TestOVNMechanismDriverMetadataPort(MechDriverSetupBase,
             port['device_owner'] = const.DEVICE_OWNER_DHCP
         return port
 
-    @mock.patch.object(db_base_plugin_v2.NeutronDbPluginV2, 'get_ports')
-    def test__find_metadata_port(self, mock_get_ports):
-        ports = [
-            self._create_fake_dhcp_port('dhcp-0', neutron_port=True),
-            self._create_fake_dhcp_port('dhcp-1', neutron_port=True),
-            self._create_fake_dhcp_port(const.DEVICE_ID_RESERVED_DHCP_PORT,
-                                        neutron_port=True),
-            self._create_fake_dhcp_port('ovnmeta-0')]
-        mock_get_ports.return_value = ports
-
-        md_port = self.mech_driver._ovn_client._find_metadata_port(
-            self.ctx, 'fake-net-id')
-        self.assertEqual('ovnmeta-0', md_port['device_id'])
-
-    @mock.patch.object(db_base_plugin_v2.NeutronDbPluginV2, 'get_ports')
-    def test__find_metadata_port_compat(self, mock_get_ports):
-        ports = [
-            self._create_fake_dhcp_port('dhcp-0', neutron_port=True),
-            self._create_fake_dhcp_port('dhcp-1', neutron_port=True),
-            self._create_fake_dhcp_port(const.DEVICE_ID_RESERVED_DHCP_PORT,
-                                        neutron_port=True),
-            self._create_fake_dhcp_port('ovnmeta-0', neutron_port=True)]
-        mock_get_ports.return_value = ports
-
-        md_port = self.mech_driver._ovn_client._find_metadata_port(
-            self.ctx, 'fake-net-id')
-        self.assertEqual('ovnmeta-0', md_port['device_id'])
-
     def test_metadata_port_on_network_create(self):
         """Check metadata port create.