Browse Source

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

changes/56/677056/1
Zuul 1 month ago
parent
commit
546b7620a0
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

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

Loading…
Cancel
Save