)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"a2d86b1fd8081cff3485cbf6e34a03ed8d9467b2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"b63511b1_96b0e60a","updated":"2025-10-14 10:03:13.000000000","message":"This patch (PS6) is completely blocking the API. I\u0027ve tested it in an environment with one single controller running 6 API workers. None of the workers can finish a single command and the system hangs unresponsive. I need to manually kill the WSGI workers.","commit_id":"9d24129137992dff8b131b398efe8d8c9c35d719"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1864bb1b86e822066cbd92aef54dd544722686ba","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"fccaeca9_40d73447","in_reply_to":"b63511b1_96b0e60a","updated":"2025-10-14 23:59:15.000000000","message":"@ralonsoh@redhat.com yes, it is what I mentioned above.\nI tried to explain why we cannot use write_lock_register what you recommended. https://bugs.launchpad.net/neutron/+bug/2125500/comments/4\nI\u0027d appreciate your feedback again.","commit_id":"9d24129137992dff8b131b398efe8d8c9c35d719"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"ca9d13f2bdc5adb139b95161eb21249bbae6b7b6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"808db394_573a00c5","updated":"2025-12-23 09:02:55.000000000","message":"recheck","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"927770c6f32e0b664587c7f32c1ba167a6849deb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":21,"id":"cb53e6f3_ae3b9bbf","updated":"2025-12-24 01:12:16.000000000","message":"recheck","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"1f753fd0eb4d51730eb4b4cad5734c0cd53f8c81","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"8d3a12ae_988c3674","updated":"2026-04-30 14:12:53.000000000","message":"And I just want to get Rodolfo\u0027s opinion on the updates as well","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":38904,"name":"Ryan","email":"ryancobb65@gmail.com","username":"cobbr"},"change_message_id":"3b4457de2cc0e58fbf5cbccef768952ebb896096","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"133b2e6c_9e2e3909","updated":"2026-03-06 15:31:08.000000000","message":"Thanks for the work on this one @okozachenko1203@gmail.com . Just wanted to voice my support for this change, this issue has given us a lot of problems with asynchronously creating subnets. And it currently prevents us from being able to utilize Openstack Heat at all, since we are not able to force synchronous subnet creation. Getting this fix in will greatly benefit us.\n\nDon\u0027t mean to rush the reviewers @haleyb.dev@gmail.com and @ralonsoh@redhat.com , just wanted to let everyone to know that we are eager to see this one land once it is ready.","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"026a568b02218a0bbb3ae4490e096ab037965fe2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"2cf04372_3df202e2","updated":"2026-02-11 23:35:48.000000000","message":"recheck","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"4d1ba48d42e9a741358114bbf4db6c0af994ebfc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"306edece_feac01ee","updated":"2026-02-13 01:46:01.000000000","message":"recheck","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f3a4f291932188e427990c2c70979c9202a348e5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"7041e959_9b13775d","updated":"2026-02-10 00:34:19.000000000","message":"recheck","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"675e28f773a691e2ef00a6edbd242823252f099e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"ce85bf9b_6c26e9dc","updated":"2026-02-05 02:34:18.000000000","message":"recheck","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"17956fd5c7d9d5f5cfc05efa920c536c15cff48a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"e68e8c37_9a1d91c4","updated":"2026-01-28 08:27:12.000000000","message":"recheck","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"36e7534220eb200a592575712eb4fc69fd7c7b2a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"2d8ddb29_a6e74136","updated":"2026-04-30 14:12:33.000000000","message":"recheck get new logs","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"0c5f6f977fdddbc3335f43735846f5057b34cee0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":24,"id":"cad518f1_ec3fa786","updated":"2026-05-06 07:43:22.000000000","message":"recheck","commit_id":"ed4aa41c9376909dd092009cd7f151d6a04a4071"}],"neutron/db/ipam_pluggable_backend.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"36e7534220eb200a592575712eb4fc69fd7c7b2a","unresolved":true,"context_lines":[{"line_number":314,"context_line":""},{"line_number":315,"context_line":"        if not ips:"},{"line_number":316,"context_line":"            LOG.debug(\"No IPs to allocate for subnets %s on port %s\","},{"line_number":317,"context_line":"                     subnet_ids, db_port.id)"},{"line_number":318,"context_line":"            return []"},{"line_number":319,"context_line":""},{"line_number":320,"context_line":"        # Allocate IPs using IPAM driver"}],"source_content_type":"text/x-python","patch_set":22,"id":"ff6ba357_3f9e30a8","line":317,"range":{"start_line":317,"start_character":21,"end_line":317,"end_character":31},"updated":"2026-04-30 14:12:33.000000000","message":"nit: should this be subnets_to_add ? Same below","commit_id":"bc8120dfcdf4ebdaf1169b7db8dd68232b4980c1"}],"neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"a32c8554eeb20f9b2e701b257c80f7dfb19c8bba","unresolved":true,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"6ee06aff_da744800","line":2785,"updated":"2025-09-29 10:50:32.000000000","message":"This lock won\u0027t work if you have several controllers running the Neutron API. This lock works between workers in the same controller only.\n\nIn order to achieve this lock, we need to enforce a global lock. For example, using the DB engine. I propose:\n* To call this method inside a DB writer context.\n* To use [1] once you have created/read the metadata port (L2816).\n```metadata_port \u003d self.create_metadata_port(context, network)```\n\n[1]https://github.com/openstack/neutron/blob/783ce1cd4d99ca20fb705d6540fbce5865fe07d7/neutron/db/models_v2.py#L54","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"482de9a3ec3266574d6ed3c4371519878dd37a52","unresolved":true,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"69fa409b_86681997","line":2785,"in_reply_to":"4110aada_635e4c00","updated":"2025-10-08 02:39:00.000000000","message":"@ralonsoh@redhat.com\nwe cannot use write_lock_register. ML2 plugin\u0027s update_port is under transaction guard so we cannot call this under a transaction. On the other hands, write_lock_register release the lock at the transaction commit.\nSo it ends up to the forever lock.","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"864588b952d98d337ff2d52b311718674e10affb","unresolved":true,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"4110aada_635e4c00","line":2785,"in_reply_to":"47e62298_a07524d3","updated":"2025-10-02 10:57:29.000000000","message":"@ralonsoh@redhat.com i followed your feedback.\nBtw, I think we need to use the same db writer context for update_port, no? But we cannot call update_port in the transaction. https://files.openstack.org/docs/developer/neutron/devref/calling_ml2_plugin.html\nAlso this write_lock_register is never released. I think it is because update_port is using the different context.","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"1f762517ef200418ff649a85eb21698fd2a2a6b6","unresolved":false,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"f857057a_af386f62","line":2785,"in_reply_to":"69fa409b_86681997","updated":"2025-10-22 11:28:32.000000000","message":"The issue seems to be in the `self._plugin.update_port` call, using another context (elevated). I\u0027ve pushed a new PS using the same one.","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"3068a90486b6adbe56d7ba72a737b6f550daf4d6","unresolved":true,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"8abe670f_be4d52a4","line":2785,"in_reply_to":"6ee06aff_da744800","updated":"2025-09-30 01:59:21.000000000","message":"@ralonsoh@redhat.com It is true that the oslo_concurrency.lockutils only works for single neutron server. So need to find a way for global shared lock mech.\nBut I don\u0027t think this write_lock_register will work because ovn transaction occurs in the post commit function of subnet creation/update operation and ovn transaction is not against mysql db, it\u0027s an operation to ovn db.\nSo we cannot guarantee mysql db commit and ovn db commit to be in one logical transaction now and it ends up race condition again even with write_lock_register.\nWe can\u0027t lock separately for ovn commit using write_lock_register either because this lock is released automatically when the first mysq db commit is made. There is no mysql commit for ovn commit.","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"9d2f81e635a14683796c7de641c7c84eeb4714a5","unresolved":true,"context_lines":[{"line_number":2782,"context_line":"                }"},{"line_number":2783,"context_line":"        return p_utils.create_port(self._plugin, context, port)"},{"line_number":2784,"context_line":""},{"line_number":2785,"context_line":"    @lockutils.synchronized(\u0027ovn-metadata-port-lock-%s\u0027, \u0027network_id\u0027, external\u003dTrue)"},{"line_number":2786,"context_line":"    def update_metadata_port(self, context, network, subnet\u003dNone):"},{"line_number":2787,"context_line":"        \"\"\"Update metadata port."},{"line_number":2788,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"47e62298_a07524d3","line":2785,"in_reply_to":"8abe670f_be4d52a4","updated":"2025-09-30 08:31:07.000000000","message":"The issue here is the metadata port update, in particular the `fixed_ips`. This is done here in this method and we actually call the Neutron DB in the line I highlighted. This is Neutron DB transaction, same as the `fixed_ips` update command done in L2809.\n\nAs commented, you can protect part of this method with a writer DB context and use the `write_lock_register` method for this port in particular.","commit_id":"0eee073b6a0d9daa07170e87567b0d38f664e424"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"a7d28cef0f6fa2fe1928669622c45502a4603767","unresolved":true,"context_lines":[{"line_number":2581,"context_line":"            subnet[\u0027id\u0027])[\u0027subnet\u0027]"},{"line_number":2582,"context_line":""},{"line_number":2583,"context_line":"        if subnet[\u0027enable_dhcp\u0027] or ovn_subnet:"},{"line_number":2584,"context_line":"            with db_api.CONTEXT_WRITER.using(context):"},{"line_number":2585,"context_line":"                self.update_metadata_port(context, network, subnet\u003dsubnet)"},{"line_number":2586,"context_line":""},{"line_number":2587,"context_line":"        check_rev_cmd \u003d self._nb_idl.check_revision_number("}],"source_content_type":"text/x-python","patch_set":4,"id":"f0d86402_5fe4e5b0","line":2584,"range":{"start_line":2584,"start_character":12,"end_line":2584,"end_character":54},"updated":"2025-10-02 14:03:43.000000000","message":"Instead of adding the context here, you can add a decorator in the method itself. That makes unnecessary to wrap the method call each time. Same comment in the upper call.","commit_id":"bec886746200bf9753f04b5fb67f4378c40de58c"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"fe5ac7583ee613b299c9a7546429001738a58df2","unresolved":false,"context_lines":[{"line_number":2581,"context_line":"            subnet[\u0027id\u0027])[\u0027subnet\u0027]"},{"line_number":2582,"context_line":""},{"line_number":2583,"context_line":"        if subnet[\u0027enable_dhcp\u0027] or ovn_subnet:"},{"line_number":2584,"context_line":"            with db_api.CONTEXT_WRITER.using(context):"},{"line_number":2585,"context_line":"                self.update_metadata_port(context, network, subnet\u003dsubnet)"},{"line_number":2586,"context_line":""},{"line_number":2587,"context_line":"        check_rev_cmd \u003d self._nb_idl.check_revision_number("}],"source_content_type":"text/x-python","patch_set":4,"id":"7434ba80_0817e306","line":2584,"range":{"start_line":2584,"start_character":12,"end_line":2584,"end_character":54},"in_reply_to":"f0d86402_5fe4e5b0","updated":"2025-10-03 07:57:31.000000000","message":"Acknowledged","commit_id":"bec886746200bf9753f04b5fb67f4378c40de58c"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"a7d28cef0f6fa2fe1928669622c45502a4603767","unresolved":true,"context_lines":[{"line_number":2823,"context_line":""},{"line_number":2824,"context_line":"        # Acquire a row-level lock on the metadata port"},{"line_number":2825,"context_line":"        models_v2.Port.write_lock_register("},{"line_number":2826,"context_line":"            context, Exception(\"Metadata port in use\"), id\u003dmetadata_port[\u0027id\u0027])"},{"line_number":2827,"context_line":""},{"line_number":2828,"context_line":"        port_subnet_ids \u003d {ip[\u0027subnet_id\u0027] for ip in"},{"line_number":2829,"context_line":"                           metadata_port[\u0027fixed_ips\u0027]}"}],"source_content_type":"text/x-python","patch_set":4,"id":"da471037_1254d8e7","line":2826,"range":{"start_line":2826,"start_character":21,"end_line":2826,"end_character":30},"updated":"2025-10-02 14:03:43.000000000","message":"Please implement a new exception based in ``neutron_lib.exceptions.InUse``, similar to ``SubnetInUse``.","commit_id":"bec886746200bf9753f04b5fb67f4378c40de58c"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"b48e2b14d02163116e09ebe0d1610951110c6aa7","unresolved":false,"context_lines":[{"line_number":2823,"context_line":""},{"line_number":2824,"context_line":"        # Acquire a row-level lock on the metadata port"},{"line_number":2825,"context_line":"        models_v2.Port.write_lock_register("},{"line_number":2826,"context_line":"            context, Exception(\"Metadata port in use\"), id\u003dmetadata_port[\u0027id\u0027])"},{"line_number":2827,"context_line":""},{"line_number":2828,"context_line":"        port_subnet_ids \u003d {ip[\u0027subnet_id\u0027] for ip in"},{"line_number":2829,"context_line":"                           metadata_port[\u0027fixed_ips\u0027]}"}],"source_content_type":"text/x-python","patch_set":4,"id":"e2261349_1967b1f3","line":2826,"range":{"start_line":2826,"start_character":21,"end_line":2826,"end_character":30},"in_reply_to":"c606f73a_1f7e2052","updated":"2025-10-03 08:10:19.000000000","message":"https://review.opendev.org/c/openstack/neutron-lib/+/962906","commit_id":"bec886746200bf9753f04b5fb67f4378c40de58c"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"fe5ac7583ee613b299c9a7546429001738a58df2","unresolved":false,"context_lines":[{"line_number":2823,"context_line":""},{"line_number":2824,"context_line":"        # Acquire a row-level lock on the metadata port"},{"line_number":2825,"context_line":"        models_v2.Port.write_lock_register("},{"line_number":2826,"context_line":"            context, Exception(\"Metadata port in use\"), id\u003dmetadata_port[\u0027id\u0027])"},{"line_number":2827,"context_line":""},{"line_number":2828,"context_line":"        port_subnet_ids \u003d {ip[\u0027subnet_id\u0027] for ip in"},{"line_number":2829,"context_line":"                           metadata_port[\u0027fixed_ips\u0027]}"}],"source_content_type":"text/x-python","patch_set":4,"id":"c606f73a_1f7e2052","line":2826,"range":{"start_line":2826,"start_character":21,"end_line":2826,"end_character":30},"in_reply_to":"da471037_1254d8e7","updated":"2025-10-03 07:57:31.000000000","message":"Acknowledged","commit_id":"bec886746200bf9753f04b5fb67f4378c40de58c"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"bed527e0a80b58131e33ad5a6bed2533d2805704","unresolved":true,"context_lines":[{"line_number":27,"context_line":"from neutron_lib.api.definitions import provider_net as pnet"},{"line_number":28,"context_line":"from neutron_lib.api.definitions import qinq as qinq_apidef"},{"line_number":29,"context_line":"from neutron_lib.api.definitions import segment as segment_def"},{"line_number":30,"context_line":"from neutron_lib.db import api as db_api"},{"line_number":31,"context_line":"from neutron_lib import constants as const"},{"line_number":32,"context_line":"from neutron_lib import context as n_context"},{"line_number":33,"context_line":"from neutron_lib import exceptions as n_exc"}],"source_content_type":"text/x-python","patch_set":9,"id":"43a3f681_3b6bf8d1","line":30,"updated":"2025-10-22 14:03:57.000000000","message":"Looks like this needs to be below const for pep8","commit_id":"f727a5221e0c33afa94ec5e2d89b8b99170329df"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":27,"context_line":"from neutron_lib.api.definitions import provider_net as pnet"},{"line_number":28,"context_line":"from neutron_lib.api.definitions import qinq as qinq_apidef"},{"line_number":29,"context_line":"from neutron_lib.api.definitions import segment as segment_def"},{"line_number":30,"context_line":"from neutron_lib.db import api as db_api"},{"line_number":31,"context_line":"from neutron_lib import constants as const"},{"line_number":32,"context_line":"from neutron_lib import context as n_context"},{"line_number":33,"context_line":"from neutron_lib import exceptions as n_exc"}],"source_content_type":"text/x-python","patch_set":9,"id":"3c9b1757_a048c9f2","line":30,"in_reply_to":"43a3f681_3b6bf8d1","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"f727a5221e0c33afa94ec5e2d89b8b99170329df"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"bed527e0a80b58131e33ad5a6bed2533d2805704","unresolved":true,"context_lines":[{"line_number":2783,"context_line":"            # to prevent future errors, this call should be moved outside"},{"line_number":2784,"context_line":"            # the current transaction."},{"line_number":2785,"context_line":"            ctx.GUARD_TRANSACTION \u003d False"},{"line_number":2786,"context_line":"            self._plugin.update_port(ctx, metadata_port[\u0027id\u0027], port)"},{"line_number":2787,"context_line":""},{"line_number":2788,"context_line":"        if not ovn_conf.is_ovn_metadata_enabled():"},{"line_number":2789,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":9,"id":"421216aa_1557a64f","line":2786,"updated":"2025-10-22 14:03:57.000000000","message":"Does this need to be an escalated context?","commit_id":"f727a5221e0c33afa94ec5e2d89b8b99170329df"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2783,"context_line":"            # to prevent future errors, this call should be moved outside"},{"line_number":2784,"context_line":"            # the current transaction."},{"line_number":2785,"context_line":"            ctx.GUARD_TRANSACTION \u003d False"},{"line_number":2786,"context_line":"            self._plugin.update_port(ctx, metadata_port[\u0027id\u0027], port)"},{"line_number":2787,"context_line":""},{"line_number":2788,"context_line":"        if not ovn_conf.is_ovn_metadata_enabled():"},{"line_number":2789,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":9,"id":"c5e21f51_0624e3df","line":2786,"in_reply_to":"2f4da3ae_3a75faf0","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"f727a5221e0c33afa94ec5e2d89b8b99170329df"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"e41f1cd3ef240664e815ed9f347cb62b12c2ce73","unresolved":true,"context_lines":[{"line_number":2783,"context_line":"            # to prevent future errors, this call should be moved outside"},{"line_number":2784,"context_line":"            # the current transaction."},{"line_number":2785,"context_line":"            ctx.GUARD_TRANSACTION \u003d False"},{"line_number":2786,"context_line":"            self._plugin.update_port(ctx, metadata_port[\u0027id\u0027], port)"},{"line_number":2787,"context_line":""},{"line_number":2788,"context_line":"        if not ovn_conf.is_ovn_metadata_enabled():"},{"line_number":2789,"context_line":"            return False"}],"source_content_type":"text/x-python","patch_set":9,"id":"2f4da3ae_3a75faf0","line":2786,"in_reply_to":"421216aa_1557a64f","updated":"2025-10-23 08:44:51.000000000","message":"Most probably it will be needed, if the user doesn\u0027t have permissions on this network. In any case the race condition is still there. The problem is that we can\u0027t call this method `self._plugin.update_port` inside a DB transaction. If we do this, we loose the IPAM allocation.\n\nIn the other hand, if we use a different context (admin or elevated), the lock used in previous commits doesn\u0027t work, because the \"for update\" clause was created by other context.\n\nAnd if we don\u0027t have a way to lock the port table (or any other), we can ensure that the subnet list in each parallel execution has all the existing and \"on the way to be created\" subnets. I added extra logs in the IPAM module with the base code and I can see how some operations are called with some missing subnets; this is triggering the deletion of the corresponding IPAM allocation in this subnet and this is why the metadata port has less IPs than subnets.\n\nOne solution, not easy to implement, is to create an additional API method in the IPAM module. Instead of [1], that is called from (in order) [2][3][4], we could have something that only adds the new subnet to the IPallocations.\n\n[1]https://github.com/openstack/neutron/blob/03baa20a9d972a5f053cdb032e1387c64859d71d/neutron/db/ipam_backend_mixin.py#L712\n[2]https://github.com/openstack/neutron/blob/03baa20a9d972a5f053cdb032e1387c64859d71d/neutron/db/db_base_plugin_v2.py#L1628\n[3]https://github.com/openstack/neutron/blob/03baa20a9d972a5f053cdb032e1387c64859d71d/neutron/plugins/ml2/plugin.py#L1971\n[4]https://github.com/openstack/neutron/blob/03baa20a9d972a5f053cdb032e1387c64859d71d/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py#L2773","commit_id":"f727a5221e0c33afa94ec5e2d89b8b99170329df"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f6001e4d65089336b0118339023f526c3c8165e6","unresolved":true,"context_lines":[{"line_number":2889,"context_line":"            \"\"\""},{"line_number":2890,"context_line":"            # pylint: disable\u003dimport-outside-toplevel"},{"line_number":2891,"context_line":"            from neutron.db import ipam_pluggable_backend"},{"line_number":2892,"context_line":"            from neutron.db import models_v2"},{"line_number":2893,"context_line":""},{"line_number":2894,"context_line":"            # Get the port from database"},{"line_number":2895,"context_line":"            db_port \u003d ctx.session.query(models_v2.Port).filter_by("}],"source_content_type":"text/x-python","patch_set":21,"id":"f572c144_63102017","line":2892,"updated":"2026-01-28 00:03:05.000000000","message":"Why are we doing this here or below? Seems wrong.","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2889,"context_line":"            \"\"\""},{"line_number":2890,"context_line":"            # pylint: disable\u003dimport-outside-toplevel"},{"line_number":2891,"context_line":"            from neutron.db import ipam_pluggable_backend"},{"line_number":2892,"context_line":"            from neutron.db import models_v2"},{"line_number":2893,"context_line":""},{"line_number":2894,"context_line":"            # Get the port from database"},{"line_number":2895,"context_line":"            db_port \u003d ctx.session.query(models_v2.Port).filter_by("}],"source_content_type":"text/x-python","patch_set":21,"id":"9493ec6d_53c072c0","line":2892,"in_reply_to":"563e970e_94b80e97","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1b8e687019495f103fadc4e7b551e30ec6866c5c","unresolved":true,"context_lines":[{"line_number":2889,"context_line":"            \"\"\""},{"line_number":2890,"context_line":"            # pylint: disable\u003dimport-outside-toplevel"},{"line_number":2891,"context_line":"            from neutron.db import ipam_pluggable_backend"},{"line_number":2892,"context_line":"            from neutron.db import models_v2"},{"line_number":2893,"context_line":""},{"line_number":2894,"context_line":"            # Get the port from database"},{"line_number":2895,"context_line":"            db_port \u003d ctx.session.query(models_v2.Port).filter_by("}],"source_content_type":"text/x-python","patch_set":21,"id":"563e970e_94b80e97","line":2892,"in_reply_to":"f572c144_63102017","updated":"2026-01-28 01:42:37.000000000","message":"Consolidated all imports at the top of the inner function with a comment explaining why","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f6001e4d65089336b0118339023f526c3c8165e6","unresolved":true,"context_lines":[{"line_number":2932,"context_line":"                else:"},{"line_number":2933,"context_line":"                    LOG.warning(\"Failed to allocate IPs for subnets %s on \""},{"line_number":2934,"context_line":"                               \"metadata port %s\", add_subnet_ids,"},{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"}],"source_content_type":"text/x-python","patch_set":21,"id":"f73c658b_849f8e1c","line":2935,"updated":"2026-01-28 00:03:05.000000000","message":"Seems this should be a fatal error and return early?","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2932,"context_line":"                else:"},{"line_number":2933,"context_line":"                    LOG.warning(\"Failed to allocate IPs for subnets %s on \""},{"line_number":2934,"context_line":"                               \"metadata port %s\", add_subnet_ids,"},{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"}],"source_content_type":"text/x-python","patch_set":21,"id":"28baa0f1_b08b6f21","line":2935,"in_reply_to":"827b3456_e639c6d4","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1b8e687019495f103fadc4e7b551e30ec6866c5c","unresolved":true,"context_lines":[{"line_number":2932,"context_line":"                else:"},{"line_number":2933,"context_line":"                    LOG.warning(\"Failed to allocate IPs for subnets %s on \""},{"line_number":2934,"context_line":"                               \"metadata port %s\", add_subnet_ids,"},{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"}],"source_content_type":"text/x-python","patch_set":21,"id":"827b3456_e639c6d4","line":2935,"in_reply_to":"f73c658b_849f8e1c","updated":"2026-01-28 01:42:37.000000000","message":"Changed LOG.warning to LOG.error and added return to exit early on IP allocation failure","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f6001e4d65089336b0118339023f526c3c8165e6","unresolved":true,"context_lines":[{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"},{"line_number":2939,"context_line":"                # Refresh port from database to get updated fixed_ips"},{"line_number":2940,"context_line":"                ctx.session.refresh(db_port, [\u0027fixed_ips\u0027])"},{"line_number":2941,"context_line":"                # Get updated port dict"}],"source_content_type":"text/x-python","patch_set":21,"id":"90fcf7aa_2fdb1764","line":2938,"updated":"2026-01-28 00:03:05.000000000","message":"I don\u0027t understand how this check can ever be false as the only callers always pass one of them.","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"},{"line_number":2939,"context_line":"                # Refresh port from database to get updated fixed_ips"},{"line_number":2940,"context_line":"                ctx.session.refresh(db_port, [\u0027fixed_ips\u0027])"},{"line_number":2941,"context_line":"                # Get updated port dict"}],"source_content_type":"text/x-python","patch_set":21,"id":"70989699_bb16a753","line":2938,"in_reply_to":"65951e3c_c6a6ac0e","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1b8e687019495f103fadc4e7b551e30ec6866c5c","unresolved":true,"context_lines":[{"line_number":2935,"context_line":"                               metadata_port[\u0027id\u0027])"},{"line_number":2936,"context_line":""},{"line_number":2937,"context_line":"            # Update OVN Logical Switch Port with new addresses if IPs changed"},{"line_number":2938,"context_line":"            if add_subnet_ids or del_subnet_ids:"},{"line_number":2939,"context_line":"                # Refresh port from database to get updated fixed_ips"},{"line_number":2940,"context_line":"                ctx.session.refresh(db_port, [\u0027fixed_ips\u0027])"},{"line_number":2941,"context_line":"                # Get updated port dict"}],"source_content_type":"text/x-python","patch_set":21,"id":"65951e3c_c6a6ac0e","line":2938,"in_reply_to":"90fcf7aa_2fdb1764","updated":"2026-01-28 01:42:37.000000000","message":"Added early return at function start (if not add_subnet_ids and not del_subnet_ids: return) and removed the redundant check before OVN update","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f6001e4d65089336b0118339023f526c3c8165e6","unresolved":true,"context_lines":[{"line_number":2977,"context_line":"                    # Update DHCP options for metadata port subnets"},{"line_number":2978,"context_line":"                    network \u003d self._plugin.get_network("},{"line_number":2979,"context_line":"                        admin_context,"},{"line_number":2980,"context_line":"                        updated_port[\u0027network_id\u0027]"},{"line_number":2981,"context_line":"                    )"},{"line_number":2982,"context_line":"                    subnet_ids \u003d ["},{"line_number":2983,"context_line":"                        _ip[\u0027subnet_id\u0027]"}],"source_content_type":"text/x-python","patch_set":21,"id":"d2994bbc_7a33cbdb","line":2980,"updated":"2026-01-28 00:03:05.000000000","message":"Can the network for this port actually be on a different one than the network passed as an argument to update_metadata_port()?","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2977,"context_line":"                    # Update DHCP options for metadata port subnets"},{"line_number":2978,"context_line":"                    network \u003d self._plugin.get_network("},{"line_number":2979,"context_line":"                        admin_context,"},{"line_number":2980,"context_line":"                        updated_port[\u0027network_id\u0027]"},{"line_number":2981,"context_line":"                    )"},{"line_number":2982,"context_line":"                    subnet_ids \u003d ["},{"line_number":2983,"context_line":"                        _ip[\u0027subnet_id\u0027]"}],"source_content_type":"text/x-python","patch_set":21,"id":"a00e5048_8a9fe6eb","line":2980,"in_reply_to":"46397ccf_55898a2c","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1b8e687019495f103fadc4e7b551e30ec6866c5c","unresolved":true,"context_lines":[{"line_number":2977,"context_line":"                    # Update DHCP options for metadata port subnets"},{"line_number":2978,"context_line":"                    network \u003d self._plugin.get_network("},{"line_number":2979,"context_line":"                        admin_context,"},{"line_number":2980,"context_line":"                        updated_port[\u0027network_id\u0027]"},{"line_number":2981,"context_line":"                    )"},{"line_number":2982,"context_line":"                    subnet_ids \u003d ["},{"line_number":2983,"context_line":"                        _ip[\u0027subnet_id\u0027]"}],"source_content_type":"text/x-python","patch_set":21,"id":"46397ccf_55898a2c","line":2980,"in_reply_to":"d2994bbc_7a33cbdb","updated":"2026-01-28 01:42:37.000000000","message":"Removed the redundant get_network() call - now uses the network from the outer scope with a comment explaining why this is safe","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f6001e4d65089336b0118339023f526c3c8165e6","unresolved":true,"context_lines":[{"line_number":2985,"context_line":"                        if \u0027subnet_id\u0027 in _ip"},{"line_number":2986,"context_line":"                    ]"},{"line_number":2987,"context_line":"                    for subnet in self._plugin.get_subnets("},{"line_number":2988,"context_line":"                            admin_context, filters\u003d{\u0027id\u0027: subnet_ids}):"},{"line_number":2989,"context_line":"                        if not subnet[\u0027enable_dhcp\u0027]:"},{"line_number":2990,"context_line":"                            continue"},{"line_number":2991,"context_line":"                        self._update_subnet_dhcp_options("}],"source_content_type":"text/x-python","patch_set":21,"id":"7fed1d46_4e403a99","line":2988,"updated":"2026-01-28 00:03:05.000000000","message":"The code at L3042 has a better version of using the DB call to filter subnets. But then it seems we\u0027ll be making the same call twice? We really need to not do that.","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"f71128f6a06f1f201c8b214b254d2bce3518e938","unresolved":false,"context_lines":[{"line_number":2985,"context_line":"                        if \u0027subnet_id\u0027 in _ip"},{"line_number":2986,"context_line":"                    ]"},{"line_number":2987,"context_line":"                    for subnet in self._plugin.get_subnets("},{"line_number":2988,"context_line":"                            admin_context, filters\u003d{\u0027id\u0027: subnet_ids}):"},{"line_number":2989,"context_line":"                        if not subnet[\u0027enable_dhcp\u0027]:"},{"line_number":2990,"context_line":"                            continue"},{"line_number":2991,"context_line":"                        self._update_subnet_dhcp_options("}],"source_content_type":"text/x-python","patch_set":21,"id":"a0be530b_6191869d","line":2988,"in_reply_to":"6dc529c4_37a8588c","updated":"2026-04-30 07:29:18.000000000","message":"Done","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"},{"author":{"_account_id":31746,"name":"Oleksandr Kozachenko","email":"okozachenko1203@gmail.com","username":"okozachenko"},"change_message_id":"1b8e687019495f103fadc4e7b551e30ec6866c5c","unresolved":true,"context_lines":[{"line_number":2985,"context_line":"                        if \u0027subnet_id\u0027 in _ip"},{"line_number":2986,"context_line":"                    ]"},{"line_number":2987,"context_line":"                    for subnet in self._plugin.get_subnets("},{"line_number":2988,"context_line":"                            admin_context, filters\u003d{\u0027id\u0027: subnet_ids}):"},{"line_number":2989,"context_line":"                        if not subnet[\u0027enable_dhcp\u0027]:"},{"line_number":2990,"context_line":"                            continue"},{"line_number":2991,"context_line":"                        self._update_subnet_dhcp_options("}],"source_content_type":"text/x-python","patch_set":21,"id":"6dc529c4_37a8588c","line":2988,"in_reply_to":"7fed1d46_4e403a99","updated":"2026-01-28 01:42:37.000000000","message":"Added \u0027enable_dhcp: True\u0027 to the DB filter, matching the pattern at L3042 and removing the Python-side filtering","commit_id":"d7e9563df46e3628a1e4925b74a6e06458086991"}]}
