Browse Source

Merge "[DVR] Add lock during creation of FIP agent gateway port" into stable/rocky

changes/22/676922/1
Zuul 1 month ago
parent
commit
ed3b41a0cd
1 changed files with 44 additions and 32 deletions
  1. 44
    32
      neutron/db/l3_dvr_db.py

+ 44
- 32
neutron/db/l3_dvr_db.py View File

@@ -30,6 +30,7 @@ from neutron_lib.exceptions import l3 as l3_exc
30 30
 from neutron_lib.plugins import constants as plugin_constants
31 31
 from neutron_lib.plugins import directory
32 32
 from neutron_lib.plugins import utils as plugin_utils
33
+from oslo_concurrency import lockutils
33 34
 from oslo_config import cfg
34 35
 from oslo_log import helpers as log_helper
35 36
 from oslo_log import log as logging
@@ -982,13 +983,9 @@ class _DVRAgentInterfaceMixin(object):
982 983
 
983 984
     def create_fip_agent_gw_port_if_not_exists(
984 985
         self, context, network_id, host):
985
-        """Function to return the FIP Agent GW port.
986
-
987
-        This function will create a FIP Agent GW port
988
-        if required. If the port already exists, it
989
-        will return the existing port and will not
990
-        create a new one.
991
-        """
986
+        # TODO(slaweq): add proper constraint on database level to avoid
987
+        # creation of duplicated Floating IP gateway ports for same network and
988
+        # same L3 agent. When this will be done, we can get rid of this lock.
992 989
         try:
993 990
             l3_agent_db = self._get_agent_by_type_and_host(
994 991
                 context, const.AGENT_TYPE_L3, host)
@@ -1001,31 +998,46 @@ class _DVRAgentInterfaceMixin(object):
1001 998
         l3_agent_mode = self._get_agent_mode(l3_agent_db)
1002 999
         if l3_agent_mode == const.L3_AGENT_MODE_DVR_NO_EXTERNAL:
1003 1000
             return
1004
-        if l3_agent_db:
1005
-            LOG.debug("Agent ID exists: %s", l3_agent_db['id'])
1006
-            f_port = self._get_agent_gw_ports_exist_for_network(
1007
-                context, network_id, host, l3_agent_db['id'])
1008
-            if not f_port:
1009
-                LOG.info('Agent Gateway port does not exist,'
1010
-                         ' so create one: %s', f_port)
1011
-                port_data = {'tenant_id': '',
1012
-                             'network_id': network_id,
1013
-                             'device_id': l3_agent_db['id'],
1014
-                             'device_owner': const.DEVICE_OWNER_AGENT_GW,
1015
-                             portbindings.HOST_ID: host,
1016
-                             'admin_state_up': True,
1017
-                             'name': ''}
1018
-                agent_port = plugin_utils.create_port(
1019
-                    self._core_plugin, context, {'port': port_data})
1020
-                if agent_port:
1021
-                    self._populate_mtu_and_subnets_for_ports(context,
1022
-                                                             [agent_port])
1023
-                    return agent_port
1024
-                msg = _("Unable to create the Agent Gateway Port")
1025
-                raise n_exc.BadRequest(resource='router', msg=msg)
1026
-            else:
1027
-                self._populate_mtu_and_subnets_for_ports(context, [f_port])
1028
-                return f_port
1001
+        if not l3_agent_db:
1002
+            return
1003
+        lock_name = 'fip-gw-lock-' + network_id + '-' + host
1004
+        with lockutils.lock(lock_name, external=True):
1005
+            return self._create_fip_agent_gw_port_if_not_exists(
1006
+                context, network_id, host, l3_agent_db)
1007
+
1008
+    def _create_fip_agent_gw_port_if_not_exists(self, context, network_id,
1009
+                                                host, l3_agent_db):
1010
+        """Function to return the FIP Agent GW port.
1011
+
1012
+        This function will create a FIP Agent GW port
1013
+        if required. If the port already exists, it
1014
+        will return the existing port and will not
1015
+        create a new one.
1016
+        """
1017
+        LOG.debug("Agent ID exists: %s", l3_agent_db['id'])
1018
+        f_port = self._get_agent_gw_ports_exist_for_network(
1019
+            context, network_id, host, l3_agent_db['id'])
1020
+        if not f_port:
1021
+            LOG.info('Agent Gateway port does not exist,'
1022
+                     ' so create one: %s', f_port)
1023
+            port_data = {'tenant_id': '',
1024
+                         'network_id': network_id,
1025
+                         'device_id': l3_agent_db['id'],
1026
+                         'device_owner': const.DEVICE_OWNER_AGENT_GW,
1027
+                         portbindings.HOST_ID: host,
1028
+                         'admin_state_up': True,
1029
+                         'name': ''}
1030
+            agent_port = plugin_utils.create_port(
1031
+                self._core_plugin, context, {'port': port_data})
1032
+            if agent_port:
1033
+                self._populate_mtu_and_subnets_for_ports(context,
1034
+                                                         [agent_port])
1035
+                return agent_port
1036
+            msg = _("Unable to create the Agent Gateway Port")
1037
+            raise n_exc.BadRequest(resource='router', msg=msg)
1038
+        else:
1039
+            self._populate_mtu_and_subnets_for_ports(context, [f_port])
1040
+            return f_port
1029 1041
 
1030 1042
     def _generate_arp_table_and_notify_agent(
1031 1043
         self, context, fixed_ip, mac_address, notifier):

Loading…
Cancel
Save