)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"8ab69b87e13a38910ce439f734801b8a4308e13b","unresolved":true,"context_lines":[{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"https: //bugs.launchpad.net/neutron/+bug/2002687"},{"line_number":15,"context_line":"Change-Id: Id885565e88f6f1898ca5cfac709a24dd62605d1a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":19,"id":"9b3ecb2e_bb4c6a72","line":14,"updated":"2023-03-17 18:34:46.000000000","message":"Add Depends-On: https://review.opendev.org/c/openstack/neutron-lib/+/870887 ?\n\nThe bug reference should probably also be a Partial-Bug: #","commit_id":"4bff3720898d1dd8a6802a427697127fd6f5f38b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"705523bd33a7efc00973399fd8b3ce0b9e77c240","unresolved":true,"context_lines":[{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"https: //bugs.launchpad.net/neutron/+bug/2002687"},{"line_number":15,"context_line":"Change-Id: Id885565e88f6f1898ca5cfac709a24dd62605d1a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":19,"id":"ba95a6eb_4dcd9101","line":14,"in_reply_to":"9b3ecb2e_bb4c6a72","updated":"2023-03-17 19:16:48.000000000","message":"Ack, will amend on the next re-upload.","commit_id":"4bff3720898d1dd8a6802a427697127fd6f5f38b"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"52645eb4a783045452bec35eac0873032ae77478","unresolved":false,"context_lines":[{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"https: //bugs.launchpad.net/neutron/+bug/2002687"},{"line_number":15,"context_line":"Change-Id: Id885565e88f6f1898ca5cfac709a24dd62605d1a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":19,"id":"c53a1786_03345558","line":14,"in_reply_to":"ba95a6eb_4dcd9101","updated":"2023-03-29 17:54:53.000000000","message":"Done","commit_id":"4bff3720898d1dd8a6802a427697127fd6f5f38b"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"d3d6c4a79664ce3a949eaff18c45ffe5dfc740a7","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Allow Multiple External Gateways"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"e2bff700_b79a17ba","line":9,"updated":"2023-03-30 08:21:29.000000000","message":"I would have exposed the API at the end of the whole implementation so if the feature is not all merged for 2023.2 we don\u0027t expose an API that is \"doing nothing\". Don\u0027t you think?\n\nAlso, a reno note will be needed.","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"7b2eb12760691023a3b6b1fa97d31f83120676e8","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Allow Multiple External Gateways"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"1a74bd7c_1d4eae09","line":9,"in_reply_to":"30f66f77_515f8ad8","updated":"2023-04-05 11:58:12.000000000","message":"Ack","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"72d171506f0177aff402d730291d8f5c55828561","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Allow Multiple External Gateways"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":28,"id":"30f66f77_515f8ad8","line":9,"in_reply_to":"e2bff700_b79a17ba","updated":"2023-04-04 14:27:45.000000000","message":"I can move it closer to the point where the OVN L3 plugin is more ready for implementing it but the unit tests for the OVN part need to call the new API in order to test the added functionality.\n\nAck on reno.","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"19fdb5ecc757b39b163d66c09c598ffbd6057740","unresolved":true,"context_lines":[{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Partial-Bug: #2002687"},{"line_number":15,"context_line":"Depends-On: I2618475636b2bb9bfd743a62f5d4859d4f68a547"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":51,"id":"f9641b88_81141437","line":12,"updated":"2023-05-23 21:31:48.000000000","message":"If you have to re-spin you could add this:\n\nThis patch also bumps neutron-lib requirement to 3.6.0.","commit_id":"ecabbff1ba2c6d4bba540332e8e81384fb145e8e"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"155a74a712d4a389047e6378eeb391a8be877b22","unresolved":false,"context_lines":[{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Partial-Bug: #2002687"},{"line_number":15,"context_line":"Depends-On: I2618475636b2bb9bfd743a62f5d4859d4f68a547"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":51,"id":"3fe20a4e_b5b70e43","line":12,"in_reply_to":"d8601f53_6598f39a","updated":"2023-05-24 17:40:20.000000000","message":"I guess I won\u0027t have to because somebody already bumped it to 3.6.1 so I just need a rebase.","commit_id":"ecabbff1ba2c6d4bba540332e8e81384fb145e8e"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"b1d15b0b6df1a8a01d46643de177848df55d1698","unresolved":true,"context_lines":[{"line_number":9,"context_line":"* Add a new API for adding/updating/removing multiple gateway ports"},{"line_number":10,"context_line":"  on routers;"},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"* Implement the necessary backend changes."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Partial-Bug: #2002687"},{"line_number":15,"context_line":"Depends-On: I2618475636b2bb9bfd743a62f5d4859d4f68a547"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":51,"id":"d8601f53_6598f39a","line":12,"in_reply_to":"f9641b88_81141437","updated":"2023-05-24 17:38:29.000000000","message":"Ack","commit_id":"ecabbff1ba2c6d4bba540332e8e81384fb145e8e"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"bde348a90c045b97cac51da063fd126640e95fb6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":13,"id":"b53c4241_770d3c96","updated":"2023-02-19 18:27:58.000000000","message":"Added the new update API in the last change.","commit_id":"59c9610b373bc4d959109e246dd7a22019dc6874"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"bb35fd776eadb3edb9ab395b9115652aa772b59b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"d66a8140_15ea0cee","updated":"2023-02-20 15:35:26.000000000","message":"Fixed an issue with reordering of gateway ports in the \"update\" path.","commit_id":"4ed4f0c65e7a4a200a61162175405baeb2643808"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"db02ee1b3f1c9e03190318e48d77e4f132743726","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"b3fa7e02_0d1da2e5","updated":"2023-02-28 19:26:56.000000000","message":"https://zuul.opendev.org/t/openstack/build/0301687cb5bd4f72841ea2ed8a6bcaa2\n\n2023-02-28 15:19:43.376 | ./stack.sh:1298:start_neutron_service_and_check\n2023-02-28 15:19:43.376 | /opt/stack/devstack/lib/neutron:615:test_with_retry\n2023-02-28 15:19:43.376 | /opt/stack/devstack/functions-common:2378:die\n2023-02-28 15:19:43.381 | [ERROR] /opt/stack/devstack/functions-common:2378 Neutron did not start\n2023-02-28 15:19:43.381 | /opt/stack/devstack/functions-common: line 310: /opt/stack/logs/error.log: Permission denied\n","commit_id":"137437f6a409c3244edbc4fd815cf4f0557f8f16"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"f8d2d2db5a10a464b3df334ba2beb171f3c75f22","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":19,"id":"59339cd3_947c4975","updated":"2023-03-17 18:23:53.000000000","message":"As of now there are some failures related to dependency resolution until we get the associated neutron-lib change in.","commit_id":"4bff3720898d1dd8a6802a427697127fd6f5f38b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"0da193be66348a0751f9f55bf4830e6d29dea5bf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":20,"id":"eb084362_aff3b2b2","updated":"2023-03-18 02:02:28.000000000","message":"The latest rev includes partial fixed IP matches - this allows updating a set of fixed IPs for gateway ports without having to recreate them.\n\nThe logic is a bit more involved but it should avoid unneeded interruptions during production use.\n\nIt also allows removing ports without having to specify all fixed IP addresses when there are multiple ports attached to the same network. The IPAM logic would not allow duplicate IPs in the first place so we know we can do partial matches on fixed IPs instead of full matches.\n\nI\u0027m going to update the neutron-lib change as well so that the port re-creation logic references are removed.\n\nWhile changing fixed IPs may seem like an edge case, documenting a certain logic in the API requires us to then follow to preserve compatibility, hence it\u0027s better to address it now.","commit_id":"398750c3fc699865bc06af07782af9d51dd96574"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"c3bf8610553174b62d0f69bde7b4b70175c38ebe","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":25,"id":"9f4281e7_a43aa460","updated":"2023-03-27 09:20:27.000000000","message":"recheck","commit_id":"9e8d4ab155f5cad2e5757868b192aa55266ca51b"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"d3d6c4a79664ce3a949eaff18c45ffe5dfc740a7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"82712ed4_7a1b72bc","updated":"2023-03-30 08:21:29.000000000","message":"Thanks ++, the changes looks almost good I have not looked in detail the API implementation I think that part should be proposed at the very end of your changes. Feel free to let me know if I\u0027m wrong","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"27458e0b6169716b33302d854aae200e2a6914a6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"b03261fd_a609926d","in_reply_to":"82712ed4_7a1b72bc","updated":"2023-03-30 20:09:00.000000000","message":"Thank you for taking the time to review, much appreciated.\n\nActually, the API definition is provided in the associated neutron-lib change [0]. In that change we provide a provisional release note declaring that the implementation has not been merged yet. We will follow up with an update to that release note when the implementation has merged. It is my understanding that this is the usual way to add new Neutron extensions [1].\n\nThe latter patches in this series all require this patch set for lint, unit and functional tests to work, and as such it needs to be the first in the series.\n\n0: https://review.opendev.org/c/openstack/neutron-lib/+/870887\n1: https://docs.openstack.org/neutron-lib/latest/contributor/api_extensions.html","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"2d22b2b3b99f0d600562aa63675219ae9adf3299","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"bc9500f8_ecc5722d","in_reply_to":"b03261fd_a609926d","updated":"2023-04-05 15:47:54.000000000","message":"ACK I don\u0027t want to make any trouble on this point. Let\u0027s make effort and time on making everything merged for bobcat","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":29,"id":"0930fba5_f5a94cd6","updated":"2023-03-30 22:26:50.000000000","message":"I didn\u0027t completely get through this, but think I raised enough questions to wait for a new PS.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"1a47b68fac16eb55248e534be226e74a79d4bb9d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":29,"id":"dcfb1400_3e45e959","updated":"2023-03-31 16:01:42.000000000","message":"Thx for review, have answered a couple of the questions in-line, will put up a new patch set shortly to save in-flight change pointing at the new neutron-lib revision and exception names.\n\nWe\u0027ll continue addressing your comments in a following patch set.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":33,"id":"9164f2cc_84ded905","updated":"2023-04-02 14:14:19.000000000","message":"I\u0027m also guessing the global-requirements stuff will go away once neutron-lib is bumped.","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"e79d3230f687ad00197d7383b6b5333c876a5049","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":33,"id":"2cdd2c48_7d6be1ca","in_reply_to":"9164f2cc_84ded905","updated":"2023-04-03 13:53:23.000000000","message":"Yes, that\u0027s here temporarily so that we can use the new neutron-lib code during development before it is merged.","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"2d22b2b3b99f0d600562aa63675219ae9adf3299","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":37,"id":"3317b666_d05a4f10","updated":"2023-04-05 15:47:54.000000000","message":"I think you still want to make some improvement suggested by Brian, besides that sounds good for me and it\u0027s pretty well tested. ","commit_id":"5cebc13908ccdf6e0db36b35316f2029cbb61586"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"d6ad585a942373d64e1a1139a7a4e9f0c9d9431c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":37,"id":"a6078a62_1fbe0337","in_reply_to":"3317b666_d05a4f10","updated":"2023-04-06 11:43:19.000000000","message":"Ack, working on the other suggestions and will re-upload.","commit_id":"5cebc13908ccdf6e0db36b35316f2029cbb61586"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"b7227832456604dde158ac955eeb7be42de6f8f1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"4a36a771_9debea0f","updated":"2023-04-18 22:28:04.000000000","message":"Note that the `neutron-tempest-plugin-ovn` failure is due to the fact that the neutron-lib dependency isn\u0027t merged yet. From the devstack journal:\n\n```\napr 18 22:04:45 np0033775328 neutron-server[100336]: CRITICAL neutron [-] Unhandled error: ImportError: cannot import name \u0027l3_ext_gw_multihoming\u0027 from \u0027neutron_lib.api.definitions\u0027 (/usr/local/lib/python3.8/dis\nt-packages/neutron_lib/api/definitions/__init__.py)\n# ...\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"/usr/lib/python3.8/importlib/__init__.py\", line 127, in import_module\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron     return _bootstrap._gcd_import(name[level:], package, level)\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap\u003e\", line 1014, in _gcd_import\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap\u003e\", line 991, in _find_and_load\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap\u003e\", line 975, in _find_and_load_unlocked\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap\u003e\", line 671, in _load_unlocked\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap_external\u003e\", line 848, in exec_module\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"\u003cfrozen importlib._bootstrap\u003e\", line 219, in _call_with_frames_removed\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"/opt/stack/neutron/neutron/services/ovn_l3/plugin.py\", line 42, in \u003cmodule\u003e\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron     from neutron.db import l3_extra_gws_db\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron   File \"/opt/stack/neutron/neutron/db/l3_extra_gws_db.py\", line 25, in \u003cmodule\u003e\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron     from neutron_lib.api.definitions import l3_ext_gw_multihoming\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron ImportError: cannot import name \u0027l3_ext_gw_multihoming\u0027 from \u0027neutron_lib.api.definitions\u0027 (/usr/local/lib/python3.8/dist-packages/neutron_lib/a\npi/definitions/__init__.py)\napr 18 22:04:45 np0033775328 neutron-server[100336]: ERROR neutron \n```","commit_id":"8e6aae043fa17b833aa19c120b7f897c5c5be7e8"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"13e0fea79c623226b6fbb6d68308787235df79b0","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":39,"id":"561b4947_cbfb921a","updated":"2023-04-27 14:40:53.000000000","message":"Replaced the use of new neutron-lib constants/exceptions with their exact copies with TODO notes: as discussed with Radolfo, while the neutron-lib change was merged a new release is too soon to be done https://meetings.opendev.org/irclogs/%23openstack-neutron/%23openstack-neutron.2023-04-24.log.html#t2023-04-24T12:14:39 and copies will be used instead for now.","commit_id":"8e6aae043fa17b833aa19c120b7f897c5c5be7e8"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"5fbd9dfb9122bbe6bb2bbfac0c8c0aaffd3f42bf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"cfa3621c_e82b521f","updated":"2023-04-28 09:58:28.000000000","message":"A mirror timeout:\n\nhttps://zuul.opendev.org/t/openstack/build/92603c9450d54a97a44253ee259697e8\n```\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/main/libs/libsodium/libsodium23_1.0.18-1_amd64.deb  Could not connect to mirror.ca-ymq-1.vexxhost.opendev.org:443 (2604:e100:1:0:f816:3eff:fe0c:e2c0), connection timed out Could not connect to mirror.ca-ymq-1.vexxhost.opendev.org:443 (199.204.45.149), connection timed out\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/n/norm/libnorm1_1.5.8+dfsg2-2build1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/libp/libpgm/libpgm-5.2-0_5.2.122~dfsg-3ubuntu1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/z/zeromq3/libzmq5_4.3.2-2ubuntu1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/u/uwsgi/uwsgi-core_2.0.18-11ubuntu1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/u/uwsgi/uwsgi_2.0.18-11ubuntu1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Failed to fetch https://mirror.ca-ymq-1.vexxhost.opendev.org/ubuntu/pool/universe/u/uwsgi/uwsgi-plugin-python3_2.0.18-11ubuntu1_amd64.deb  Unable to connect to mirror.ca-ymq-1.vexxhost.opendev.org:https:\nE: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?\n```","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"78569cb808bb45851a8e082bbc75e8773f2a3e7f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"25a0e4f3_32ef13ce","updated":"2023-04-30 20:55:22.000000000","message":"The func test failure is due to this bug:\n\nhttps://bugs.launchpad.net/neutron/+bug/2018130\nhttps://review.opendev.org/c/openstack/neutron/+/881896\n\nI\u0027ll wait until this is merged before making another recheck.","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"0b7081d30f556095dd77d8d56a9242a9277f942d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"56b06b14_2c7848a0","updated":"2023-04-27 22:12:17.000000000","message":"recheck","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"b8b9a2e55e92b2873642f3ff5913df8cf7a17ab9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"ec2c91e2_1648a1e3","updated":"2023-04-28 09:58:36.000000000","message":"recheck","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"45b53dc07823486887215a93092650385688788a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"12cd85aa_0d6e1630","updated":"2023-05-01 20:48:19.000000000","message":"recheck vexxhost nested virt hosts disabled","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"8c7a0dee98116f230f21f11206d693a70240c43d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"52b3151c_6bff6f01","updated":"2023-04-28 15:10:59.000000000","message":"recheck vexxhost nested virt hosts disabled","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"de04f17aa7c4354d959bd5269bb0b88cd9d5f2c4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":41,"id":"74534307_2f33cda1","updated":"2023-04-30 14:11:09.000000000","message":"recheck vexxhost nested virt hosts disabled","commit_id":"75a8df50a861e2a123618fbb92533a4ac250f304"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"34dcc2ad980d6fda2d0d713895b4451569648b70","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":43,"id":"c5db5369_c45ad5ed","updated":"2023-05-02 21:22:38.000000000","message":"recheck","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"25dc74e2de983f3716c31dfc2176c68e166cc125","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"266cc2d8_f63a5c08","updated":"2023-05-08 22:01:05.000000000","message":"recheck","commit_id":"96d3e96b95c9053da6129a4c7c1c2cd54f2802e1"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"1fcc3691cf5425870a77565e784f33994ae1cae7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"98c90d7d_46314dd5","updated":"2023-05-09 07:28:26.000000000","message":"recheck vexxhost nested virt hosts disabled","commit_id":"96d3e96b95c9053da6129a4c7c1c2cd54f2802e1"},{"author":{"_account_id":8313,"name":"Lajos Katona","display_name":"lajoskatona","email":"katonalala@gmail.com","username":"elajkat","status":"Ericsson Software Technology"},"change_message_id":"3761f18fa3f6d7c10a6625344b18fa57eec15a92","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":48,"id":"7fbbaaa3_7133be77","updated":"2023-05-15 08:59:39.000000000","message":"recheck\nhttps://review.opendev.org/c/openstack/neutron/+/883081 fixed pep8","commit_id":"d1448362a6f0dae8de1f188abd7d5872d71eac67"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f9bf39fb69ddabb10813eef81da0698578f6605d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":50,"id":"bc26936b_fb5d1ec0","updated":"2023-05-17 17:27:57.000000000","message":"Looks good, just had one question in the code...","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"d9302d7170947651a69c1fd82034b801e1a1fae9","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":52,"id":"a208d56c_8ee199fc","updated":"2023-05-24 23:30:52.000000000","message":"Did a rebase with conflict resolution for the series so the +2 is gone.\n\nFor this change it\u0027s just the removal of a change to `requirements.txt` since this has already been addressed in `master`:\n\nhttps://review.opendev.org/c/openstack/neutron/+/873593/51..52","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"6279b5c4a7421888328d06155edefa32f8c6453c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":52,"id":"e9342d7b_82db9872","updated":"2023-05-30 18:04:18.000000000","message":"Just soliciting a review based on the people who participated in the spec approval.\n\nAppreciate there are other things you are working on (I just don\u0027t a have visibility into it).\n\nThanks in advance!","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"5577d3da91d509fc5e5733cc4c0ee0042e7e03f4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":52,"id":"29617545_57c382bf","updated":"2023-06-06 21:32:50.000000000","message":"Nice work! ralonsoh indicated during today\u0027s Neutron irc meeting that he is going to review this patch tomorrow. I want to give him the opportunity to look at it. If he doesn\u0027t have time to do it by the end of this week though, ping me (mlavalle) in the Neutron channel and I\u0027ll be happy to merge it","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"60799a50194ada0e66ec4de4cd3a7b46b5dac477","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":52,"id":"818d11fd_99e7e15a","updated":"2023-06-09 21:52:59.000000000","message":"recheck","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"f9a12d02b65f3f0a5da81343f7e2393dc53b089e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":52,"id":"8ece95d0_dade4c40","in_reply_to":"29617545_57c382bf","updated":"2023-06-06 21:49:08.000000000","message":"Ack, tyvm!","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"}],"neutron/db/l3_db.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":509,"context_line":"            self._check_for_dup_router_subnets("},{"line_number":510,"context_line":"                context, router,"},{"line_number":511,"context_line":"                subnets,"},{"line_number":512,"context_line":"                constants.DEVICE_OWNER_ROUTER_GW,"},{"line_number":513,"context_line":"            )"},{"line_number":514,"context_line":"            self._create_router_gw_port(context, router,"},{"line_number":515,"context_line":"                                        new_network_id, ext_ips)"}],"source_content_type":"text/x-python","patch_set":43,"id":"ac064989_8611aafc","line":512,"range":{"start_line":512,"start_character":48,"end_line":512,"end_character":49},"updated":"2023-05-03 08:34:07.000000000","message":"nit: trailing comma, but I guess pep8 doesn\u0027t care","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":509,"context_line":"            self._check_for_dup_router_subnets("},{"line_number":510,"context_line":"                context, router,"},{"line_number":511,"context_line":"                subnets,"},{"line_number":512,"context_line":"                constants.DEVICE_OWNER_ROUTER_GW,"},{"line_number":513,"context_line":"            )"},{"line_number":514,"context_line":"            self._create_router_gw_port(context, router,"},{"line_number":515,"context_line":"                                        new_network_id, ext_ips)"}],"source_content_type":"text/x-python","patch_set":43,"id":"2b42d044_f38891bb","line":512,"range":{"start_line":512,"start_character":48,"end_line":512,"end_character":49},"in_reply_to":"ac064989_8611aafc","updated":"2023-05-04 00:12:52.000000000","message":"Ack","commit_id":"3f7b6455bec61017de9f64453a77724256954164"}],"neutron/db/l3_extra_gws_db.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":56,"context_line":"                l3_plugin, l3_ext_gw_multihoming.ALIAS):"},{"line_number":57,"context_line":"            return"},{"line_number":58,"context_line":"        ctx \u003d context.get_admin_context()"},{"line_number":59,"context_line":"        router \u003d l3_obj.Router.get_object(ctx, id\u003drouter_db.id)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        external_gateways \u003d []"},{"line_number":62,"context_line":"        for gw_port_id in router.gw_ports:"}],"source_content_type":"text/x-python","patch_set":29,"id":"ffce9edf_8929e1ac","line":59,"updated":"2023-03-30 22:26:50.000000000","message":"Do you need this call? Can\u0027t you just use the passed router_db object?","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"b4e7a3c6ec3341b1f1ae71ecc3496ac2d8633d15","unresolved":false,"context_lines":[{"line_number":56,"context_line":"                l3_plugin, l3_ext_gw_multihoming.ALIAS):"},{"line_number":57,"context_line":"            return"},{"line_number":58,"context_line":"        ctx \u003d context.get_admin_context()"},{"line_number":59,"context_line":"        router \u003d l3_obj.Router.get_object(ctx, id\u003drouter_db.id)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        external_gateways \u003d []"},{"line_number":62,"context_line":"        for gw_port_id in router.gw_ports:"}],"source_content_type":"text/x-python","patch_set":29,"id":"834044f0_e3c61e37","line":59,"in_reply_to":"05432051_2d56b9e4","updated":"2023-03-31 16:41:21.000000000","message":"Done","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"1a47b68fac16eb55248e534be226e74a79d4bb9d","unresolved":true,"context_lines":[{"line_number":56,"context_line":"                l3_plugin, l3_ext_gw_multihoming.ALIAS):"},{"line_number":57,"context_line":"            return"},{"line_number":58,"context_line":"        ctx \u003d context.get_admin_context()"},{"line_number":59,"context_line":"        router \u003d l3_obj.Router.get_object(ctx, id\u003drouter_db.id)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        external_gateways \u003d []"},{"line_number":62,"context_line":"        for gw_port_id in router.gw_ports:"}],"source_content_type":"text/x-python","patch_set":29,"id":"05432051_2d56b9e4","line":59,"in_reply_to":"ffce9edf_8929e1ac","updated":"2023-03-31 16:01:42.000000000","message":"I think it was done this way because the DB router object does not have the `gw_ports` synthetic field.\n\nWe could probably filter the contents of the `router_db.attached_ports` attribute instead though if the overhead of the object is too large.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"5b4f4e12_825f56a6","line":110,"updated":"2023-03-30 22:26:50.000000000","message":"This should be outside the loop since the arguments don\u0027t change, and then can you remove the get_object() above or are different things needed?","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"01241222799e9e929fabf6746facdc8b0d6643b5","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"f27c3544_e825c029","line":110,"in_reply_to":"4a64f451_0892d0db","updated":"2023-04-01 07:10:09.000000000","message":"A potential improvement could be to have the methods that manipulate the router_db return a in-memory updated copy so that we don\u0027t need the additional lookups, but I have not checked how feasible that is.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"1a47b68fac16eb55248e534be226e74a79d4bb9d","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"d1ba9c21_51aaaa30","line":110,"in_reply_to":"5b4f4e12_825f56a6","updated":"2023-03-31 16:01:42.000000000","message":"The `self._validate_gw_info` method requires a DB object, it also iterates over the `attached_ports` attribute, and given we are adding multiple ports here I think we need to pass in an updated copy of the object for the check to run against updated information for each iteration.\n\nIf we need both a object and DB object in the same method is a different question though, I guess we could filter the `attached_ports` attribute instead if retrieving the object has an overhead.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"82171ecb1da3b12e4306b8b058d7089311d64378","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"79c0e364_8b3b3733","line":110,"in_reply_to":"6d9d529b_0208e812","updated":"2023-03-31 18:59:50.000000000","message":"I discovered this later in the series in a functional test when it exploded here:\nhttps://review.opendev.org/c/openstack/neutron/+/873593/31/neutron/db/l3_db.py#401\n\nIf a plain dict is passed in elsewhere in the code base, it might be that the above is a bug though.\n\nIn any case, I\u0027ll see if we can get rid of using both the object and DB object in the same method, as that does appear wasteful.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"691a4599babf7f59f5298ccaa917b0c2650b452b","unresolved":false,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"4a64f451_0892d0db","line":110,"in_reply_to":"79c0e364_8b3b3733","updated":"2023-03-31 19:49:47.000000000","message":"Done","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"1c6224bdf09e23dfd8e612875c6183419d5ba253","unresolved":true,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"6d9d529b_0208e812","line":110,"in_reply_to":"d1ba9c21_51aaaa30","updated":"2023-03-31 18:54:49.000000000","message":"Ok, I guess I didn\u0027t think _validate_gw_info() needed a DB object since the update_router() path can pass the json from the API call. But like you said, you need to re-load it if something was added. _create_extra_gw_port() will do this again in the reader context so I was hoping there was some way to reduce all the calls.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"54d5651245e49bf34372f48936c5e5aa1c42007d","unresolved":false,"context_lines":[{"line_number":107,"context_line":""},{"line_number":108,"context_line":"        # Go over extra gateway ports and add them to the router."},{"line_number":109,"context_line":"        for gw_info in extra_gw_info:"},{"line_number":110,"context_line":"            router_db \u003d self._get_router(context, router_id)"},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":113,"context_line":"            # as there are no ports yet."}],"source_content_type":"text/x-python","patch_set":29,"id":"23f21f97_3f1e8fae","line":110,"in_reply_to":"f27c3544_e825c029","updated":"2023-05-05 23:12:26.000000000","message":"Ack","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        return added_gateways"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def _create_extra_gw_port(self, context, router_id, router, new_network_id,"},{"line_number":128,"context_line":"                              ext_ips):"},{"line_number":129,"context_line":"        with db_api.CONTEXT_READER.using(context):"},{"line_number":130,"context_line":"            router_db \u003d self._get_router(context, router_id)"}],"source_content_type":"text/x-python","patch_set":29,"id":"3989c729_ef525a78","line":127,"range":{"start_line":127,"start_character":56,"end_line":127,"end_character":62},"updated":"2023-03-30 22:26:50.000000000","message":"This is unused here, but if you passed router_db would you have to look it up again?","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":13686,"name":"Frode Nordahl","email":"fnordahl@ubuntu.com","username":"fnordahl"},"change_message_id":"691a4599babf7f59f5298ccaa917b0c2650b452b","unresolved":false,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":"        return added_gateways"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":"    def _create_extra_gw_port(self, context, router_id, router, new_network_id,"},{"line_number":128,"context_line":"                              ext_ips):"},{"line_number":129,"context_line":"        with db_api.CONTEXT_READER.using(context):"},{"line_number":130,"context_line":"            router_db \u003d self._get_router(context, router_id)"}],"source_content_type":"text/x-python","patch_set":29,"id":"f5537027_13e54fae","line":127,"range":{"start_line":127,"start_character":56,"end_line":127,"end_character":62},"in_reply_to":"3989c729_ef525a78","updated":"2023-03-31 19:49:47.000000000","message":"Done","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":181,"context_line":""},{"line_number":182,"context_line":"        # Ignore temporary Prefix Delegation CIDRs"},{"line_number":183,"context_line":"        new_subnets \u003d [s for s in new_subnets"},{"line_number":184,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"},{"line_number":185,"context_line":"        id_filter \u003d {\u0027id\u0027: router_subnets}"},{"line_number":186,"context_line":"        subnets \u003d self._core_plugin.get_subnets(context.elevated(),"},{"line_number":187,"context_line":"                                                filters\u003did_filter)"}],"source_content_type":"text/x-python","patch_set":29,"id":"3202a1c5_a97cdede","line":184,"updated":"2023-03-30 22:26:50.000000000","message":"You\u0027re not using new_subnets until below, then you\u0027re looping through it looking at a single item, network_id. Could short-cut that a little by doing that here:\n\nnet_subnet_netids \u003d [s[\u0027network_id\u0027] for s in ....]\n\nThen below could do:\n\nfor sub in subnets:\n   if sub[\u0027network_id\u0027] in net_subnet_netids:\n       raise","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"7b2eb12760691023a3b6b1fa97d31f83120676e8","unresolved":false,"context_lines":[{"line_number":181,"context_line":""},{"line_number":182,"context_line":"        # Ignore temporary Prefix Delegation CIDRs"},{"line_number":183,"context_line":"        new_subnets \u003d [s for s in new_subnets"},{"line_number":184,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"},{"line_number":185,"context_line":"        id_filter \u003d {\u0027id\u0027: router_subnets}"},{"line_number":186,"context_line":"        subnets \u003d self._core_plugin.get_subnets(context.elevated(),"},{"line_number":187,"context_line":"                                                filters\u003did_filter)"}],"source_content_type":"text/x-python","patch_set":29,"id":"c51e4cde_eeed4de2","line":184,"in_reply_to":"3202a1c5_a97cdede","updated":"2023-04-05 11:58:12.000000000","message":"Commented in: https://review.opendev.org/c/openstack/neutron/+/873593/comments/ce8e603d_94eca90d","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":184,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"},{"line_number":185,"context_line":"        id_filter \u003d {\u0027id\u0027: router_subnets}"},{"line_number":186,"context_line":"        subnets \u003d self._core_plugin.get_subnets(context.elevated(),"},{"line_number":187,"context_line":"                                                filters\u003did_filter)"},{"line_number":188,"context_line":"        for sub in subnets:"},{"line_number":189,"context_line":"            for s in new_subnets:"},{"line_number":190,"context_line":"                # Overlapping subnet ranges are a problem if we are attaching"}],"source_content_type":"text/x-python","patch_set":29,"id":"ce8e603d_94eca90d","line":187,"updated":"2023-03-30 22:26:50.000000000","message":"Now that I\u0027m looking close at this I\u0027m wondering why we\u0027re calling get_subnets() again? We just called above to build router_subnets, can\u0027t we just store the network_ids when we did that?\n\nSo maybe there\u0027s a way to make this quicker using sets and my above comments?","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"54d5651245e49bf34372f48936c5e5aa1c42007d","unresolved":false,"context_lines":[{"line_number":184,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"},{"line_number":185,"context_line":"        id_filter \u003d {\u0027id\u0027: router_subnets}"},{"line_number":186,"context_line":"        subnets \u003d self._core_plugin.get_subnets(context.elevated(),"},{"line_number":187,"context_line":"                                                filters\u003did_filter)"},{"line_number":188,"context_line":"        for sub in subnets:"},{"line_number":189,"context_line":"            for s in new_subnets:"},{"line_number":190,"context_line":"                # Overlapping subnet ranges are a problem if we are attaching"}],"source_content_type":"text/x-python","patch_set":29,"id":"a6df56ee_779284d0","line":187,"in_reply_to":"084ee1c9_48ada12d","updated":"2023-05-05 23:12:26.000000000","message":"The name of the function is now the same as in the parent class and the overlap check covers both the old and new logic for extra gateway ports.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"7b2eb12760691023a3b6b1fa97d31f83120676e8","unresolved":true,"context_lines":[{"line_number":184,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"},{"line_number":185,"context_line":"        id_filter \u003d {\u0027id\u0027: router_subnets}"},{"line_number":186,"context_line":"        subnets \u003d self._core_plugin.get_subnets(context.elevated(),"},{"line_number":187,"context_line":"                                                filters\u003did_filter)"},{"line_number":188,"context_line":"        for sub in subnets:"},{"line_number":189,"context_line":"            for s in new_subnets:"},{"line_number":190,"context_line":"                # Overlapping subnet ranges are a problem if we are attaching"}],"source_content_type":"text/x-python","patch_set":29,"id":"084ee1c9_48ada12d","line":187,"in_reply_to":"ce8e603d_94eca90d","updated":"2023-04-05 11:58:12.000000000","message":"This method is similar to the one of the parent https://github.com/openstack/neutron/blob/b1ca854791fe391ccbb7ac3a019dc9b9d46a3995/neutron/db/l3_db.py#L670-L699 but with caveats because the logic for multiple gateways is different.\n\nWhen it comes to just using IDs, we actually need both subnet objects passed into _raise_on_subnets_overlap which uses both `subnet[\u0027id\u0027]` and `subnet[\u0027cidr\u0027]` fields.\n https://github.com/openstack/neutron/blob/b1ca854791fe391ccbb7ac3a019dc9b9d46a3995/neutron/db/l3_db.py#L572-L587\n \nThe list of subnet IDs (`router_subnets`) is also formed both based on the output of `get_subnets` and the subnet IDs taken from fixed IPs:\n\nhttps://github.com/openstack/neutron/blob/master/neutron/db/l3_db.py#L688-L689\n\nSo I cannot avoid additional queries either via `get_subnets` or one by one when taking subnet_ids from fixed IPs.\n\nThat being said, I should likely use the same name for this function as in the parent class so that any compatibility functions using this method do not break when detecting overlap in the presence of multiple gateway ports.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":250,"context_line":"                        matched_port_ids[gw_port[\u0027id\u0027]] \u003d gw_info"},{"line_number":251,"context_line":"                    matched \u003d True"},{"line_number":252,"context_line":"                    break"},{"line_number":253,"context_line":"            if not matched:"},{"line_number":254,"context_line":"                raise l3_mh_exc.UnableToMatchGateways("},{"line_number":255,"context_line":"                    router_id\u003drouter_id,"},{"line_number":256,"context_line":"                    reason\u003d_(\u0027could not match a gateway port attached to \u0027"}],"source_content_type":"text/x-python","patch_set":29,"id":"b44296b0_b1e48679","line":253,"range":{"start_line":253,"start_character":12,"end_line":253,"end_character":27},"updated":"2023-03-30 22:26:50.000000000","message":"nit: this could also be \"else:\" which would only trigger if you didn\u0027t find a match\n\nhttps://book.pythontips.com/en/latest/for_-_else.html","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"4362e55fce8c28c4188d9ab2ea1f34383b87e4e8","unresolved":false,"context_lines":[{"line_number":250,"context_line":"                        matched_port_ids[gw_port[\u0027id\u0027]] \u003d gw_info"},{"line_number":251,"context_line":"                    matched \u003d True"},{"line_number":252,"context_line":"                    break"},{"line_number":253,"context_line":"            if not matched:"},{"line_number":254,"context_line":"                raise l3_mh_exc.UnableToMatchGateways("},{"line_number":255,"context_line":"                    router_id\u003drouter_id,"},{"line_number":256,"context_line":"                    reason\u003d_(\u0027could not match a gateway port attached to \u0027"}],"source_content_type":"text/x-python","patch_set":29,"id":"d54750b5_35097154","line":253,"range":{"start_line":253,"start_character":12,"end_line":253,"end_character":27},"in_reply_to":"b44296b0_b1e48679","updated":"2023-04-13 18:52:57.000000000","message":"Yes, that\u0027s much better, ty.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":283,"context_line":"        # Go over extra gateways and validate the specified information."},{"line_number":284,"context_line":"        for gw_info in gw_info_list:"},{"line_number":285,"context_line":"            ext_ips \u003d gw_info.get("},{"line_number":286,"context_line":"                \u0027external_fixed_ips\u0027, []) if gw_info else []"},{"line_number":287,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"}],"source_content_type":"text/x-python","patch_set":29,"id":"2e34d7bf_be5b8fe3","line":286,"range":{"start_line":286,"start_character":42,"end_line":286,"end_character":52},"updated":"2023-03-30 22:26:50.000000000","message":"Can this happen? Or is there a None element in the list?","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"4362e55fce8c28c4188d9ab2ea1f34383b87e4e8","unresolved":false,"context_lines":[{"line_number":283,"context_line":"        # Go over extra gateways and validate the specified information."},{"line_number":284,"context_line":"        for gw_info in gw_info_list:"},{"line_number":285,"context_line":"            ext_ips \u003d gw_info.get("},{"line_number":286,"context_line":"                \u0027external_fixed_ips\u0027, []) if gw_info else []"},{"line_number":287,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":288,"context_line":""},{"line_number":289,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"}],"source_content_type":"text/x-python","patch_set":29,"id":"41513228_e72b34ac","line":286,"range":{"start_line":286,"start_character":42,"end_line":286,"end_character":52},"in_reply_to":"2e34d7bf_be5b8fe3","updated":"2023-04-13 18:52:57.000000000","message":"Good point, I think I might have carried this over from an earlier iteration of the code while what I intended to check is already handled.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":407,"context_line":""},{"line_number":408,"context_line":"    def _remove_all_gateways(self, context, router_id):"},{"line_number":409,"context_line":"        # Remove the compatibility gw port using the compatibility API."},{"line_number":410,"context_line":"        super()._update_router_gw_info(context, router_id, {}, {})"},{"line_number":411,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":412,"context_line":"        for gw_port_id in router.gw_ports[1:]:"},{"line_number":413,"context_line":"            self._delete_extra_gw_port(context, router_id, gw_port_id)"}],"source_content_type":"text/x-python","patch_set":29,"id":"303b5295_74635aed","line":410,"updated":"2023-03-30 22:26:50.000000000","message":"This seems odd to me. Typically you don\u0027t invoke super() with a different method name, can\u0027t this just be self._update_router_gw_info() since it\u0027s inheriting the class? It\u0027s not illegal of course...","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"4362e55fce8c28c4188d9ab2ea1f34383b87e4e8","unresolved":true,"context_lines":[{"line_number":407,"context_line":""},{"line_number":408,"context_line":"    def _remove_all_gateways(self, context, router_id):"},{"line_number":409,"context_line":"        # Remove the compatibility gw port using the compatibility API."},{"line_number":410,"context_line":"        super()._update_router_gw_info(context, router_id, {}, {})"},{"line_number":411,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":412,"context_line":"        for gw_port_id in router.gw_ports[1:]:"},{"line_number":413,"context_line":"            self._delete_extra_gw_port(context, router_id, gw_port_id)"}],"source_content_type":"text/x-python","patch_set":29,"id":"94ae0b7d_d4871a01","line":410,"in_reply_to":"303b5295_74635aed","updated":"2023-04-13 18:52:57.000000000","message":"I could call `self._update_router_gw_info()` directly.\n\nI am getting spurious DB exceptions\n\n```\noslo_db.exception.DBReferenceError: (sqlite3.IntegrityError) FOREIGN KEY constraint failed\n```\n\nif I do - trying to work out where the issue arises (maybe a transaction context is used where it should not be - could not find after spending some time - need to figure it out).","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"54d5651245e49bf34372f48936c5e5aa1c42007d","unresolved":false,"context_lines":[{"line_number":407,"context_line":""},{"line_number":408,"context_line":"    def _remove_all_gateways(self, context, router_id):"},{"line_number":409,"context_line":"        # Remove the compatibility gw port using the compatibility API."},{"line_number":410,"context_line":"        super()._update_router_gw_info(context, router_id, {}, {})"},{"line_number":411,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":412,"context_line":"        for gw_port_id in router.gw_ports[1:]:"},{"line_number":413,"context_line":"            self._delete_extra_gw_port(context, router_id, gw_port_id)"}],"source_content_type":"text/x-python","patch_set":29,"id":"190f3b23_24b305af","line":410,"in_reply_to":"94ae0b7d_d4871a01","updated":"2023-05-05 23:12:26.000000000","message":"Turns out, there is (obviously) lack of ordering in what `get_gw_port_ids_by_router_id` returns: there is no guarantee that the compat `gw_port_id` will be the first one in the list. Therefore, assuming that `gw_ports[1:]` will carve out extra gateway ports is wrong. In that case, if the overridden `_update_router_gw_info` method is called, it will take the remaining extra gateway port and make it a compatibility gateway port causing one of the tests to fail.\n\n```\n# gw_port_id -\u003e 7d873580-1d68-4358-b609-9421a5692717\n(Pdb) router_db\n\u003cneutron.db.models.l3.Router[object at 7f0e7b26f880] {project_id\u003d\u002761c6c22c-71f4-4ffb-a524-d83cc8f66aba\u0027, id\u003d\u0027ddea2dc3-251c-4ef6-bb21-5f4e496e098b\u0027, name\u003dNone, status\u003d\u0027ACTIVE\u0027, admin_state_up\u003dTrue, gw_port_id\u003d\u00277d873580-1d68-4358-b609-9421a5692717\u0027, flavor_id\u003dNone, standard_attr_id\u003d7, enable_snat\u003dTrue}\u003e\n\n(Pdb) n\n\u003e /home/ubuntu/src/opendev/neutron/neutron/db/l3_extra_gws_db.py(471)_remove_all_gateways()\n-\u003e router_id)\n(Pdb) n\n\u003e /home/ubuntu/src/opendev/neutron/neutron/db/l3_extra_gws_db.py(470)_remove_all_gateways()\n-\u003e gw_ports \u003d l3_obj.RouterPort.get_gw_port_ids_by_router_id(context,\n(Pdb) n\n\u003e /home/ubuntu/src/opendev/neutron/neutron/db/l3_extra_gws_db.py(472)_remove_all_gateways()\n-\u003e for gw_port_id in gw_ports[1:]:\n# gw_port_id is not the first one in the list:\n(Pdb) gw_ports\n[\u002708746b86-0089-4004-a681-3b2d555cf7a7\u0027, \u00277d873580-1d68-4358-b609-9421a5692717\u0027]\n```\n\nSo I found a way to avoid calling `super()._update_router_gw_info` in `_remove_all_gateways`.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":498,"context_line":"            return {\u0027router\u0027: router}"},{"line_number":499,"context_line":""},{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"}],"source_content_type":"text/x-python","patch_set":29,"id":"0bfd6f9c_4f8f866c","line":501,"updated":"2023-03-30 22:26:50.000000000","message":"Oh, because here you are defining it, :-/\n\nThis can just take more args and not call the parent class with them.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"4362e55fce8c28c4188d9ab2ea1f34383b87e4e8","unresolved":true,"context_lines":[{"line_number":498,"context_line":"            return {\u0027router\u0027: router}"},{"line_number":499,"context_line":""},{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"}],"source_content_type":"text/x-python","patch_set":29,"id":"b9db2f98_d92cdd48","line":501,"in_reply_to":"0bfd6f9c_4f8f866c","updated":"2023-04-13 18:52:57.000000000","message":"Here I am not changing the parameters - just trying to do something like this:\n\n```\nIn [20]: class X:\n    ...:     def do(self):\n    ...:         self.something(\u0027arg\u0027)\n    ...: \n    ...:     def something(self, x):\n    ...:         print(\u0027parent something\u0027)\n    ...: \n\nIn [21]: class Y(X):\n    ...:     def something(self, x):\n    ...:         super().something(\u0027\u0027)\n    ...:         print(\u0027child something\u0027)\n    ...: \n\nIn [22]: y \u003d Y()\n\nIn [23]: y.do()\nparent something\nchild something\n```\n\nSo that whenever the compatibility API is called on the frontend it\u0027s doing a slightly different thing.\n\nUnless I didn\u0027t catch what you mean.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"54d5651245e49bf34372f48936c5e5aa1c42007d","unresolved":false,"context_lines":[{"line_number":498,"context_line":"            return {\u0027router\u0027: router}"},{"line_number":499,"context_line":""},{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"}],"source_content_type":"text/x-python","patch_set":29,"id":"50e4290f_0f5999de","line":501,"in_reply_to":"2e89b219_6bf91250","updated":"2023-05-05 23:12:26.000000000","message":"Ack","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":498,"context_line":"            return {\u0027router\u0027: router}"},{"line_number":499,"context_line":""},{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"}],"source_content_type":"text/x-python","patch_set":29,"id":"2e89b219_6bf91250","line":501,"in_reply_to":"b9db2f98_d92cdd48","updated":"2023-05-03 08:34:07.000000000","message":"I guess this had to do with my comment on L468, but my brain has lost a little context.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"fd945590c0c1154574e67e4f90f8a663ebb86b9c","unresolved":true,"context_lines":[{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"},{"line_number":505,"context_line":"        # (by passing empty info for external_gateway_info) replace it with"},{"line_number":506,"context_line":"        # one of the existing ones."}],"source_content_type":"text/x-python","patch_set":29,"id":"1c8ceb58_8d1b5aed","line":503,"updated":"2023-03-30 22:26:50.000000000","message":"The super() of this class in l3_gwmode_db will return a router db object so you probably don\u0027t need to get it below.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"4362e55fce8c28c4188d9ab2ea1f34383b87e4e8","unresolved":false,"context_lines":[{"line_number":500,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":501,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":502,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":503,"context_line":"                                       request_body, router)"},{"line_number":504,"context_line":"        # If a compatibility port got removed as a result of a router update"},{"line_number":505,"context_line":"        # (by passing empty info for external_gateway_info) replace it with"},{"line_number":506,"context_line":"        # one of the existing ones."}],"source_content_type":"text/x-python","patch_set":29,"id":"0614b13d_77dbd470","line":503,"in_reply_to":"1c8ceb58_8d1b5aed","updated":"2023-04-13 18:52:57.000000000","message":"It returns a DB object back\n\n(Pdb) type(router)\n\u003cclass \u0027neutron.db.models.l3.Router\u0027\u003e\n\nbut I need an extended one with the `gw_ports` synthetic field to do the check. So this is just to avoid rewriting what `gw_ports` is already doing.","commit_id":"0e8b2aae53323b13b7248782bd6436a6b6a795fa"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":291,"context_line":"                \u0027external_fixed_ips\u0027, []) if gw_info else []"},{"line_number":292,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":295,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":296,"context_line":"                                                gw_info_list)"},{"line_number":297,"context_line":"        if nonexistent_port_info:"}],"source_content_type":"text/x-python","patch_set":33,"id":"195a0050_c3cbdafd","line":294,"range":{"start_line":294,"start_character":65,"end_line":294,"end_character":66},"updated":"2023-04-02 14:14:19.000000000","message":"nit: we try to use () instead of a backslash when possible in the tree","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":291,"context_line":"                \u0027external_fixed_ips\u0027, []) if gw_info else []"},{"line_number":292,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":293,"context_line":""},{"line_number":294,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":295,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":296,"context_line":"                                                gw_info_list)"},{"line_number":297,"context_line":"        if nonexistent_port_info:"}],"source_content_type":"text/x-python","patch_set":33,"id":"f1301c3d_2c3de25e","line":294,"range":{"start_line":294,"start_character":65,"end_line":294,"end_character":66},"in_reply_to":"195a0050_c3cbdafd","updated":"2023-04-03 13:06:04.000000000","message":"Done","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":332,"context_line":"            new_network_id \u003d port_obj.Port.get_object("},{"line_number":333,"context_line":"                context, id\u003dnew_gw_port_id).network_id"},{"line_number":334,"context_line":"            # Replace the gw_port_id on the router object with an existing one."},{"line_number":335,"context_line":"            self._replace_compat_gw_port(context, router[\u0027id\u0027], new_gw_port_id)"},{"line_number":336,"context_line":"            # Generate a compatibility payload."},{"line_number":337,"context_line":"            synthetic_payload \u003d copy.deepcopy(payload)"},{"line_number":338,"context_line":"            synthetic_payload[\u0027router\u0027].pop(\u0027external_gateways\u0027)"}],"source_content_type":"text/x-python","patch_set":33,"id":"95e3a801_9b79cf10","line":335,"range":{"start_line":335,"start_character":50,"end_line":335,"end_character":62},"updated":"2023-04-02 14:14:19.000000000","message":"super nit: router_id, at least it better be the same","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":332,"context_line":"            new_network_id \u003d port_obj.Port.get_object("},{"line_number":333,"context_line":"                context, id\u003dnew_gw_port_id).network_id"},{"line_number":334,"context_line":"            # Replace the gw_port_id on the router object with an existing one."},{"line_number":335,"context_line":"            self._replace_compat_gw_port(context, router[\u0027id\u0027], new_gw_port_id)"},{"line_number":336,"context_line":"            # Generate a compatibility payload."},{"line_number":337,"context_line":"            synthetic_payload \u003d copy.deepcopy(payload)"},{"line_number":338,"context_line":"            synthetic_payload[\u0027router\u0027].pop(\u0027external_gateways\u0027)"}],"source_content_type":"text/x-python","patch_set":33,"id":"afe9cf73_5758d153","line":335,"range":{"start_line":335,"start_character":50,"end_line":335,"end_character":62},"in_reply_to":"95e3a801_9b79cf10","updated":"2023-04-03 13:06:04.000000000","message":"Done","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":386,"context_line":""},{"line_number":387,"context_line":"    @db_api.retry_if_session_inactive()"},{"line_number":388,"context_line":"    def add_external_gateways(self, context, router_id, body\u003dNone):"},{"line_number":389,"context_line":"        gateways \u003d body[\u0027router\u0027][\u0027external_gateways\u0027]"},{"line_number":390,"context_line":"        external_gateways \u003d self._add_external_gateways("},{"line_number":391,"context_line":"            context, router_id, gateways, body)"},{"line_number":392,"context_line":""}],"source_content_type":"text/x-python","patch_set":33,"id":"604ebde0_5a10ceb9","line":389,"updated":"2023-04-02 14:14:19.000000000","message":"If body is None this will raise, not sure if it can be?","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":386,"context_line":""},{"line_number":387,"context_line":"    @db_api.retry_if_session_inactive()"},{"line_number":388,"context_line":"    def add_external_gateways(self, context, router_id, body\u003dNone):"},{"line_number":389,"context_line":"        gateways \u003d body[\u0027router\u0027][\u0027external_gateways\u0027]"},{"line_number":390,"context_line":"        external_gateways \u003d self._add_external_gateways("},{"line_number":391,"context_line":"            context, router_id, gateways, body)"},{"line_number":392,"context_line":""}],"source_content_type":"text/x-python","patch_set":33,"id":"f78a6775_2005ae08","line":389,"in_reply_to":"604ebde0_5a10ceb9","updated":"2023-04-03 13:06:04.000000000","message":"I doubt it can be actually - I don\u0027t see precedent for that in other API methods for different resources.\n\nI added handling for the lack of \u0027external_gateways\u0027 though.","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":399,"context_line":""},{"line_number":400,"context_line":"    @db_api.retry_if_session_inactive()"},{"line_number":401,"context_line":"    def remove_external_gateways(self, context, router_id, body\u003dNone):"},{"line_number":402,"context_line":"        gateways \u003d body[\u0027router\u0027][\u0027external_gateways\u0027]"},{"line_number":403,"context_line":"        external_gateways \u003d self._remove_external_gateways("},{"line_number":404,"context_line":"            context, router_id, gateways, body)"},{"line_number":405,"context_line":"        with db_api.CONTEXT_WRITER.using(context):"}],"source_content_type":"text/x-python","patch_set":33,"id":"abafe448_2b6edbf6","line":402,"updated":"2023-04-02 14:14:19.000000000","message":"same","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":399,"context_line":""},{"line_number":400,"context_line":"    @db_api.retry_if_session_inactive()"},{"line_number":401,"context_line":"    def remove_external_gateways(self, context, router_id, body\u003dNone):"},{"line_number":402,"context_line":"        gateways \u003d body[\u0027router\u0027][\u0027external_gateways\u0027]"},{"line_number":403,"context_line":"        external_gateways \u003d self._remove_external_gateways("},{"line_number":404,"context_line":"            context, router_id, gateways, body)"},{"line_number":405,"context_line":"        with db_api.CONTEXT_WRITER.using(context):"}],"source_content_type":"text/x-python","patch_set":33,"id":"38cfe897_5a36c6a4","line":402,"in_reply_to":"abafe448_2b6edbf6","updated":"2023-04-03 13:06:04.000000000","message":"Done","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":434,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"        # Find a match for the first gateway in the list."},{"line_number":437,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":438,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":439,"context_line":"                                                gw_info_list[:1])"},{"line_number":440,"context_line":"        # If there is already an existing extra gateway port matching what was"}],"source_content_type":"text/x-python","patch_set":33,"id":"f6a21af5_303b9ea2","line":437,"range":{"start_line":437,"start_character":65,"end_line":437,"end_character":66},"updated":"2023-04-02 14:14:19.000000000","message":"same","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":434,"context_line":"            self._validate_gw_info(context, gw_info, ext_ips, router_db)"},{"line_number":435,"context_line":""},{"line_number":436,"context_line":"        # Find a match for the first gateway in the list."},{"line_number":437,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":438,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":439,"context_line":"                                                gw_info_list[:1])"},{"line_number":440,"context_line":"        # If there is already an existing extra gateway port matching what was"}],"source_content_type":"text/x-python","patch_set":33,"id":"1112c24d_2317bf5f","line":437,"range":{"start_line":437,"start_character":65,"end_line":437,"end_character":66},"in_reply_to":"f6a21af5_303b9ea2","updated":"2023-04-03 13:06:04.000000000","message":"Done","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"135031a4792c6d8c98894c87488a938678504137","unresolved":true,"context_lines":[{"line_number":450,"context_line":"        super()._update_router_gw_info(context, router_id, gw_info_list[0], {})"},{"line_number":451,"context_line":""},{"line_number":452,"context_line":"        # Find a match for the rest of the gateway list."},{"line_number":453,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":454,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":455,"context_line":"                                                gw_info_list[1:])"},{"line_number":456,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"}],"source_content_type":"text/x-python","patch_set":33,"id":"0551f042_3c7d03f4","line":453,"range":{"start_line":453,"start_character":65,"end_line":453,"end_character":66},"updated":"2023-04-02 14:14:19.000000000","message":"same","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"fd237e33a05d168e5c0e8d6740459ec27d1d129c","unresolved":false,"context_lines":[{"line_number":450,"context_line":"        super()._update_router_gw_info(context, router_id, gw_info_list[0], {})"},{"line_number":451,"context_line":""},{"line_number":452,"context_line":"        # Find a match for the rest of the gateway list."},{"line_number":453,"context_line":"        found_gw_port_ids, part_matches, nonexistent_port_info \u003d \\"},{"line_number":454,"context_line":"            self._match_requested_gateway_ports(context, router_id,"},{"line_number":455,"context_line":"                                                gw_info_list[1:])"},{"line_number":456,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"}],"source_content_type":"text/x-python","patch_set":33,"id":"afd2d25b_0df549fd","line":453,"range":{"start_line":453,"start_character":65,"end_line":453,"end_character":66},"in_reply_to":"0551f042_3c7d03f4","updated":"2023-04-03 13:06:04.000000000","message":"Done","commit_id":"a96782aba11e25a815afff4c5c219f5a5d7cb17b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"class UnableToMatchGateways(exceptions.NeutronException):"},{"line_number":52,"context_line":"    message \u003d _(\"Unable to match a requested gateway port to\""},{"line_number":53,"context_line":"                \" existing gateway ports for router %(router_id)s\")"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"def format_gateway_info(gw_port):"}],"source_content_type":"text/x-python","patch_set":43,"id":"58f49a6a_14783810","line":53,"updated":"2023-05-03 08:34:07.000000000","message":"I noticed neutron-lib has a fourth exception defined, UnableToAddExtraGatewayPort - is that used anywhere? I didn\u0027t see it in follow-on patches either.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":true,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"class UnableToMatchGateways(exceptions.NeutronException):"},{"line_number":52,"context_line":"    message \u003d _(\"Unable to match a requested gateway port to\""},{"line_number":53,"context_line":"                \" existing gateway ports for router %(router_id)s\")"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"def format_gateway_info(gw_port):"}],"source_content_type":"text/x-python","patch_set":43,"id":"dad89f11_a858fd2d","line":53,"in_reply_to":"58f49a6a_14783810","updated":"2023-05-04 00:12:52.000000000","message":"I think we lost the need for it in one of the iterations. I can raise a review for neutron-lib to remove it.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"435b2360761b2dfdeb6224a4eebdd88ec1a1ed65","unresolved":false,"context_lines":[{"line_number":50,"context_line":""},{"line_number":51,"context_line":"class UnableToMatchGateways(exceptions.NeutronException):"},{"line_number":52,"context_line":"    message \u003d _(\"Unable to match a requested gateway port to\""},{"line_number":53,"context_line":"                \" existing gateway ports for router %(router_id)s\")"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"def format_gateway_info(gw_port):"}],"source_content_type":"text/x-python","patch_set":43,"id":"5b402094_131fd2ab","line":53,"in_reply_to":"dad89f11_a858fd2d","updated":"2023-05-04 15:46:06.000000000","message":"https://review.opendev.org/c/openstack/neutron-lib/+/882334","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"        if [rp.port"},{"line_number":107,"context_line":"                for rp in router_db.attached_ports"},{"line_number":108,"context_line":"                if rp.port.device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW]:"},{"line_number":109,"context_line":"            # Matching for gateway ports with the same network_id and set of"},{"line_number":110,"context_line":"            # fixed_ips is not needed since an IP allocation would fail in this"},{"line_number":111,"context_line":"            # case. And if fixed IPs don\u0027t overlap or are not specified a new"}],"source_content_type":"text/x-python","patch_set":43,"id":"ad4620b4_23a2c6b0","line":108,"updated":"2023-05-03 08:34:07.000000000","message":"Since we\u0027re never using this list, should probably use any() here, like\n\nif any(rp.port.device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW\n       for rp in router_db.attached_ports)\n       \nThink I got the syntax correct.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":105,"context_line":""},{"line_number":106,"context_line":"        if [rp.port"},{"line_number":107,"context_line":"                for rp in router_db.attached_ports"},{"line_number":108,"context_line":"                if rp.port.device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW]:"},{"line_number":109,"context_line":"            # Matching for gateway ports with the same network_id and set of"},{"line_number":110,"context_line":"            # fixed_ips is not needed since an IP allocation would fail in this"},{"line_number":111,"context_line":"            # case. And if fixed IPs don\u0027t overlap or are not specified a new"}],"source_content_type":"text/x-python","patch_set":43,"id":"3509a88d_cb34dd0e","line":108,"in_reply_to":"ad4620b4_23a2c6b0","updated":"2023-05-04 00:12:52.000000000","message":"Done","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":156,"context_line":"            if not router_db.gw_port:"},{"line_number":157,"context_line":"                raise UnableToAddExtraGateways("},{"line_number":158,"context_line":"                    router_id\u003drouter_db.id,"},{"line_number":159,"context_line":"                    reason\u003d_(\u0027a router does not have a compatibility gateway \u0027"},{"line_number":160,"context_line":"                             \u0027port\u0027))"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"            new_valid_gw_port_attachment \u003d new_network_id is not None"}],"source_content_type":"text/x-python","patch_set":43,"id":"777fc5fe_78e3c628","line":159,"range":{"start_line":159,"start_character":30,"end_line":159,"end_character":38},"updated":"2023-05-03 08:34:07.000000000","message":"nit: \u0027router does not...\u0027","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":156,"context_line":"            if not router_db.gw_port:"},{"line_number":157,"context_line":"                raise UnableToAddExtraGateways("},{"line_number":158,"context_line":"                    router_id\u003drouter_db.id,"},{"line_number":159,"context_line":"                    reason\u003d_(\u0027a router does not have a compatibility gateway \u0027"},{"line_number":160,"context_line":"                             \u0027port\u0027))"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"            new_valid_gw_port_attachment \u003d new_network_id is not None"}],"source_content_type":"text/x-python","patch_set":43,"id":"1ccb947c_9eb50674","line":159,"range":{"start_line":159,"start_character":30,"end_line":159,"end_character":38},"in_reply_to":"777fc5fe_78e3c628","updated":"2023-05-04 00:12:52.000000000","message":"Done","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":159,"context_line":"                    reason\u003d_(\u0027a router does not have a compatibility gateway \u0027"},{"line_number":160,"context_line":"                             \u0027port\u0027))"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"            new_valid_gw_port_attachment \u003d new_network_id is not None"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        if new_valid_gw_port_attachment:"},{"line_number":165,"context_line":"            subnets \u003d self._core_plugin.get_subnets_by_network(context,"}],"source_content_type":"text/x-python","patch_set":43,"id":"e44deb15_1c4ad890","line":162,"updated":"2023-05-03 08:34:07.000000000","message":"This is only assigned once, so probably unnecessary, can just change code below to make the same check, or just\n\nif not new_network_id:\n    return\n\n(or does that need to be \u0027if new_network_id is None\u0027 ?)","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":159,"context_line":"                    reason\u003d_(\u0027a router does not have a compatibility gateway \u0027"},{"line_number":160,"context_line":"                             \u0027port\u0027))"},{"line_number":161,"context_line":""},{"line_number":162,"context_line":"            new_valid_gw_port_attachment \u003d new_network_id is not None"},{"line_number":163,"context_line":""},{"line_number":164,"context_line":"        if new_valid_gw_port_attachment:"},{"line_number":165,"context_line":"            subnets \u003d self._core_plugin.get_subnets_by_network(context,"}],"source_content_type":"text/x-python","patch_set":43,"id":"b9ae07af_da0a9a3c","line":162,"in_reply_to":"e44deb15_1c4ad890","updated":"2023-05-04 00:12:52.000000000","message":"I think using `not new_network_id` is better here as you say (the `None` check is a bit superfluous)\n\n```\nif not new_network_id:\n    return\n```\n\nI\u0027ll change it.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":226,"context_line":"                        ext_subnets.add(sub[\u0027id\u0027])"},{"line_number":227,"context_line":"                else:"},{"line_number":228,"context_line":"                    router_subnets.append(ip[\u0027subnet_id\u0027])"},{"line_number":229,"context_line":""},{"line_number":230,"context_line":"        # Ignore temporary Prefix Delegation CIDRs"},{"line_number":231,"context_line":"        new_subnets \u003d [s for s in new_subnets"},{"line_number":232,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"}],"source_content_type":"text/x-python","patch_set":43,"id":"d67dfd22_67127795","line":229,"updated":"2023-05-03 08:34:07.000000000","message":"can router_subnets ever still be [] here? If so should we just return early? I guess it would if existing_port_owner is not the correct value.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":226,"context_line":"                        ext_subnets.add(sub[\u0027id\u0027])"},{"line_number":227,"context_line":"                else:"},{"line_number":228,"context_line":"                    router_subnets.append(ip[\u0027subnet_id\u0027])"},{"line_number":229,"context_line":""},{"line_number":230,"context_line":"        # Ignore temporary Prefix Delegation CIDRs"},{"line_number":231,"context_line":"        new_subnets \u003d [s for s in new_subnets"},{"line_number":232,"context_line":"                       if s[\u0027cidr\u0027] !\u003d constants.PROVISIONAL_IPV6_PD_PREFIX]"}],"source_content_type":"text/x-python","patch_set":43,"id":"d885f192_b0c0527c","line":229,"in_reply_to":"d67dfd22_67127795","updated":"2023-05-04 00:12:52.000000000","message":"Agreed, will add a check and early return.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":241,"context_line":"                # (including the case where an attempt to add multiple internal"},{"line_number":242,"context_line":"                # ports on the same subnet is made for the same router)."},{"line_number":243,"context_line":"                if not (new_s[\u0027id\u0027] in ext_subnets and"},{"line_number":244,"context_line":"                        new_device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW):"},{"line_number":245,"context_line":"                    self._raise_on_subnets_overlap(sub, new_s)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"    def _match_requested_gateway_ports(self, context, router_id,"}],"source_content_type":"text/x-python","patch_set":43,"id":"eb76a6f2_22656acd","line":244,"range":{"start_line":244,"start_character":24,"end_line":244,"end_character":76},"updated":"2023-05-03 08:34:07.000000000","message":"So this check here has nothing to do with the data in the loop, in that it\u0027s not comparing against subnet info. For that reason it seems it can be the first thing to check in the function and just return early, right?\n\nif new_device_owner !\u003d constants.DEVICE_OWNER_ROUTER_GW:\n    return\n\nSimilar thing for existing_device_owner.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"0911121a05bc1c623acb3a4c14bcd7e68e8bfbf4","unresolved":false,"context_lines":[{"line_number":241,"context_line":"                # (including the case where an attempt to add multiple internal"},{"line_number":242,"context_line":"                # ports on the same subnet is made for the same router)."},{"line_number":243,"context_line":"                if not (new_s[\u0027id\u0027] in ext_subnets and"},{"line_number":244,"context_line":"                        new_device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW):"},{"line_number":245,"context_line":"                    self._raise_on_subnets_overlap(sub, new_s)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"    def _match_requested_gateway_ports(self, context, router_id,"}],"source_content_type":"text/x-python","patch_set":43,"id":"24b4ef6c_c2d067db","line":244,"range":{"start_line":244,"start_character":24,"end_line":244,"end_character":76},"in_reply_to":"22fb6b3b_23ae9c31","updated":"2023-05-04 10:24:04.000000000","message":"Ack","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":true,"context_lines":[{"line_number":241,"context_line":"                # (including the case where an attempt to add multiple internal"},{"line_number":242,"context_line":"                # ports on the same subnet is made for the same router)."},{"line_number":243,"context_line":"                if not (new_s[\u0027id\u0027] in ext_subnets and"},{"line_number":244,"context_line":"                        new_device_owner \u003d\u003d constants.DEVICE_OWNER_ROUTER_GW):"},{"line_number":245,"context_line":"                    self._raise_on_subnets_overlap(sub, new_s)"},{"line_number":246,"context_line":""},{"line_number":247,"context_line":"    def _match_requested_gateway_ports(self, context, router_id,"}],"source_content_type":"text/x-python","patch_set":43,"id":"22fb6b3b_23ae9c31","line":244,"range":{"start_line":244,"start_character":24,"end_line":244,"end_character":76},"in_reply_to":"eb76a6f2_22656acd","updated":"2023-05-04 00:12:52.000000000","message":"It\u0027s very subtle because we are working with the *intent* for which `new_subnets` are being added and the purpose of existing subnets of a router.\n\nMoving the check to the beginning of the function will cause several existing overlap tests to fail: https://paste.opendev.org/show/by47e3dKcXIdsc5g8RlP/\n\n```\n         if new_device_owner !\u003d constants.DEVICE_OWNER_ROUTER_GW:\n             return\n         router_subnets \u003d []\n         ext_subnets \u003d set()\n         # ...\n```\n\nThe `new_device_owner` check only comes into play if the a new subnet ID already matches one of the existing \"external subnets\" of a router. In that case, if we are adding another gateway port, then it\u0027s simply an extra port attached to the same subnet as one of the existing gateway ports and the overlap check isn\u0027t needed. In all other cases we have to do an overlap check ignoring the `new_device_owner` value.\n\nIn an abstract example:\n\n```\nIn [1]: if not (False and print(\u0027some check\u0027)):\n   ...:     print(\u0027do\u0027)\n   ...: \ndo\n```\n\nSo we can only do the `new_device_owner` check once we know the set of `ext_subnets` and whether a given new subnet ID is in this set or not.\n\nI hope that makes sense.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"015cd02997136c717fb253238bcb20043671837a","unresolved":true,"context_lines":[{"line_number":565,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":566,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":567,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":568,"context_line":"                                       request_body, router)"},{"line_number":569,"context_line":"        # If a compatibility port got removed as a result of a router update"},{"line_number":570,"context_line":"        # (by passing empty info for external_gateway_info) replace it with"},{"line_number":571,"context_line":"        # one of the existing ones."}],"source_content_type":"text/x-python","patch_set":43,"id":"cb134d3e_d979b10c","line":568,"updated":"2023-05-03 08:34:07.000000000","message":"This should return a router_db item, at least looking at l3_gwmode_db.py, but I guess the parent in l3_db.py does not. I guess if inheritance-wise if this was calling the gwmode one we could just save the return value.\n\nI might just be rambling on now though...","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"cee990ed2751c767fe330c2b79956e0fe71ad82b","unresolved":false,"context_lines":[{"line_number":565,"context_line":"    def _update_router_gw_info(self, context, router_id,"},{"line_number":566,"context_line":"                               info, request_body, router\u003dNone):"},{"line_number":567,"context_line":"        super()._update_router_gw_info(context, router_id, info,"},{"line_number":568,"context_line":"                                       request_body, router)"},{"line_number":569,"context_line":"        # If a compatibility port got removed as a result of a router update"},{"line_number":570,"context_line":"        # (by passing empty info for external_gateway_info) replace it with"},{"line_number":571,"context_line":"        # one of the existing ones."}],"source_content_type":"text/x-python","patch_set":43,"id":"57d36f4c_da5ae18f","line":568,"in_reply_to":"cb134d3e_d979b10c","updated":"2023-05-04 00:12:52.000000000","message":"Yes, I suppose we could just reuse the returned value instead of doing another call to get it. I\u0027ll fix it.","commit_id":"3f7b6455bec61017de9f64453a77724256954164"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f9bf39fb69ddabb10813eef81da0698578f6605d","unresolved":true,"context_lines":[{"line_number":118,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":119,"context_line":"            # as there are no ports yet."},{"line_number":120,"context_line":"            ext_ips \u003d gw_info.get("},{"line_number":121,"context_line":"                \u0027external_fixed_ips\u0027, [])"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"}],"source_content_type":"text/x-python","patch_set":50,"id":"506be74e_fecae31f","line":121,"updated":"2023-05-17 17:27:57.000000000","message":"super nit: could be on previous line","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"1fc13e9af075592635dda5825eab3f18ce130552","unresolved":true,"context_lines":[{"line_number":118,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":119,"context_line":"            # as there are no ports yet."},{"line_number":120,"context_line":"            ext_ips \u003d gw_info.get("},{"line_number":121,"context_line":"                \u0027external_fixed_ips\u0027, [])"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"}],"source_content_type":"text/x-python","patch_set":50,"id":"b77ccd4e_20d3eb87","line":121,"in_reply_to":"506be74e_fecae31f","updated":"2023-05-17 22:38:01.000000000","message":"Ack","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"df8cdc29c7f748db03990a2ba02c98ae10022099","unresolved":false,"context_lines":[{"line_number":118,"context_line":"            # Here we do not need to check for external gateway port IP changes"},{"line_number":119,"context_line":"            # as there are no ports yet."},{"line_number":120,"context_line":"            ext_ips \u003d gw_info.get("},{"line_number":121,"context_line":"                \u0027external_fixed_ips\u0027, [])"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"}],"source_content_type":"text/x-python","patch_set":50,"id":"6ebb9ff1_f0994fb2","line":121,"in_reply_to":"b77ccd4e_20d3eb87","updated":"2023-05-19 09:48:57.000000000","message":"Done","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f9bf39fb69ddabb10813eef81da0698578f6605d","unresolved":true,"context_lines":[{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"},{"line_number":125,"context_line":"            # NOTE(dmitriis): that this is not done within the writer context"},{"line_number":126,"context_line":"            # as doing so will cause create_port to fail in some cases."},{"line_number":127,"context_line":"            self._create_extra_gw_port(context, router_db,"},{"line_number":128,"context_line":"                                       network_id, ext_ips)"},{"line_number":129,"context_line":"            added_gateways.append(gw_info)"}],"source_content_type":"text/x-python","patch_set":50,"id":"8dd3df11_cb901278","line":126,"updated":"2023-05-17 17:27:57.000000000","message":"nit: comment seems a little out of place since there isn\u0027t a writer context method in this function. And I guess it applies to the self._create_router_gw_port() call on L157 since that function has a similar warning.","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"df8cdc29c7f748db03990a2ba02c98ae10022099","unresolved":false,"context_lines":[{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"},{"line_number":125,"context_line":"            # NOTE(dmitriis): that this is not done within the writer context"},{"line_number":126,"context_line":"            # as doing so will cause create_port to fail in some cases."},{"line_number":127,"context_line":"            self._create_extra_gw_port(context, router_db,"},{"line_number":128,"context_line":"                                       network_id, ext_ips)"},{"line_number":129,"context_line":"            added_gateways.append(gw_info)"}],"source_content_type":"text/x-python","patch_set":50,"id":"b2be8c59_0bb16cf4","line":126,"in_reply_to":"5dd0b4b7_c2a78bbf","updated":"2023-05-19 09:48:57.000000000","message":"Done","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"1fc13e9af075592635dda5825eab3f18ce130552","unresolved":true,"context_lines":[{"line_number":123,"context_line":"            network_id \u003d self._validate_gw_info(context, gw_info,"},{"line_number":124,"context_line":"                                                ext_ips, router_db)"},{"line_number":125,"context_line":"            # NOTE(dmitriis): that this is not done within the writer context"},{"line_number":126,"context_line":"            # as doing so will cause create_port to fail in some cases."},{"line_number":127,"context_line":"            self._create_extra_gw_port(context, router_db,"},{"line_number":128,"context_line":"                                       network_id, ext_ips)"},{"line_number":129,"context_line":"            added_gateways.append(gw_info)"}],"source_content_type":"text/x-python","patch_set":50,"id":"5dd0b4b7_c2a78bbf","line":126,"in_reply_to":"8dd3df11_cb901278","updated":"2023-05-17 22:38:01.000000000","message":"Indeed, could be that I forgot to remove it during proofreading.","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"f9bf39fb69ddabb10813eef81da0698578f6605d","unresolved":true,"context_lines":[{"line_number":303,"context_line":"        if not gw_info_list:"},{"line_number":304,"context_line":"            return removed_gateways"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":307,"context_line":"        gw_ports \u003d l3_obj.RouterPort.get_gw_port_ids_by_router_id(context,"},{"line_number":308,"context_line":"                                                                  router_id)"},{"line_number":309,"context_line":"        if not gw_ports:"}],"source_content_type":"text/x-python","patch_set":50,"id":"ce556c12_5075688b","line":306,"updated":"2023-05-17 17:27:57.000000000","message":"Is this just to possibly trigger an exception for a non-existent router? Since I don\u0027t see \u0027router\u0027 being used before it\u0027s re-assigned below on L356","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"df8cdc29c7f748db03990a2ba02c98ae10022099","unresolved":false,"context_lines":[{"line_number":303,"context_line":"        if not gw_info_list:"},{"line_number":304,"context_line":"            return removed_gateways"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":307,"context_line":"        gw_ports \u003d l3_obj.RouterPort.get_gw_port_ids_by_router_id(context,"},{"line_number":308,"context_line":"                                                                  router_id)"},{"line_number":309,"context_line":"        if not gw_ports:"}],"source_content_type":"text/x-python","patch_set":50,"id":"80f5fd7a_7f1054a4","line":306,"in_reply_to":"5f64568a_7921b5ac","updated":"2023-05-19 09:48:57.000000000","message":"Done","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"1fc13e9af075592635dda5825eab3f18ce130552","unresolved":true,"context_lines":[{"line_number":303,"context_line":"        if not gw_info_list:"},{"line_number":304,"context_line":"            return removed_gateways"},{"line_number":305,"context_line":""},{"line_number":306,"context_line":"        router \u003d l3_obj.Router.get_object(context, id\u003drouter_id)"},{"line_number":307,"context_line":"        gw_ports \u003d l3_obj.RouterPort.get_gw_port_ids_by_router_id(context,"},{"line_number":308,"context_line":"                                                                  router_id)"},{"line_number":309,"context_line":"        if not gw_ports:"}],"source_content_type":"text/x-python","patch_set":50,"id":"5f64568a_7921b5ac","line":306,"in_reply_to":"ce556c12_5075688b","updated":"2023-05-17 22:38:01.000000000","message":"I think I used it for something else in one of the previous iterations but now I don\u0027t see much use for it to be honest.\n\nThanks for spotting!","commit_id":"083cb9a1429e85779dd42b9e0e9d9be9dbbe1a40"},{"author":{"_account_id":8313,"name":"Lajos Katona","display_name":"lajoskatona","email":"katonalala@gmail.com","username":"elajkat","status":"Ericsson Software Technology"},"change_message_id":"0a9e60a4beff7cc9955cb0bb7ec00efc49798aee","unresolved":true,"context_lines":[{"line_number":161,"context_line":""},{"line_number":162,"context_line":"    def _check_for_dup_router_subnets(self, context, router_db,"},{"line_number":163,"context_line":"                                      new_subnets, new_device_owner):"},{"line_number":164,"context_line":"        \"\"\"Check for overlapping subnets on different networks."},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"        This method overrides the one in the base class so the logic will be"},{"line_number":167,"context_line":"        triggered for both the compatibility code that might alter the state"}],"source_content_type":"text/x-python","patch_set":52,"id":"7cdbaae6_fe3fb0e5","line":164,"updated":"2023-06-08 08:40:11.000000000","message":"+1 for the docstring","commit_id":"a221764751de05e42069f1c097b1025bd9c4fc52"}],"neutron/extensions/l3_extra_gws.py":[{"author":{"_account_id":8313,"name":"Lajos Katona","display_name":"lajoskatona","email":"katonalala@gmail.com","username":"elajkat","status":"Ericsson Software Technology"},"change_message_id":"3761f18fa3f6d7c10a6625344b18fa57eec15a92","unresolved":true,"context_lines":[{"line_number":19,"context_line":"from neutron_lib.api.definitions import l3_ext_gw_mode"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# TODO(dmitriis): Replace with the module from neutron-lib after a new release"},{"line_number":22,"context_line":"# containing e52a9372f76aa104543ab04cf1723e58da17d379 is out."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class L3ExtGwMultihomingAPIDefinition:"}],"source_content_type":"text/x-python","patch_set":48,"id":"6b3526ab_ba9c1313","line":22,"range":{"start_line":22,"start_character":13,"end_line":22,"end_character":53},"updated":"2023-05-15 08:59:39.000000000","message":"neutron-lib 3.6.0 already out with the extension, could you use/import that ?","commit_id":"d1448362a6f0dae8de1f188abd7d5872d71eac67"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"bfb68609b5d2997dc5366629d691aff6b160d381","unresolved":true,"context_lines":[{"line_number":19,"context_line":"from neutron_lib.api.definitions import l3_ext_gw_mode"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# TODO(dmitriis): Replace with the module from neutron-lib after a new release"},{"line_number":22,"context_line":"# containing e52a9372f76aa104543ab04cf1723e58da17d379 is out."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class L3ExtGwMultihomingAPIDefinition:"}],"source_content_type":"text/x-python","patch_set":48,"id":"828e56b4_2359f694","line":22,"range":{"start_line":22,"start_character":13,"end_line":22,"end_character":53},"in_reply_to":"6b3526ab_ba9c1313","updated":"2023-05-15 10:32:16.000000000","message":"Ack, I\u0027ll bring the imports back and remove the TODOs.","commit_id":"d1448362a6f0dae8de1f188abd7d5872d71eac67"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"3554397c471aba79239fe9aafb5bdf8ba9d8487c","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from neutron_lib.api.definitions import l3_ext_gw_mode"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"# TODO(dmitriis): Replace with the module from neutron-lib after a new release"},{"line_number":22,"context_line":"# containing e52a9372f76aa104543ab04cf1723e58da17d379 is out."},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class L3ExtGwMultihomingAPIDefinition:"}],"source_content_type":"text/x-python","patch_set":48,"id":"30ab0734_cedef762","line":22,"range":{"start_line":22,"start_character":13,"end_line":22,"end_character":53},"in_reply_to":"828e56b4_2359f694","updated":"2023-05-16 21:46:29.000000000","message":"The last update should do it.","commit_id":"d1448362a6f0dae8de1f188abd7d5872d71eac67"}],"neutron/objects/router.py":[{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"d3d6c4a79664ce3a949eaff18c45ffe5dfc740a7","unresolved":true,"context_lines":[{"line_number":198,"context_line":"    # Version 1.0: Initial version"},{"line_number":199,"context_line":"    # Version 1.1: Added \"qos_policy_id\" field"},{"line_number":200,"context_line":"    # Version 1.2: Added the \"gw_ports\" field"},{"line_number":201,"context_line":"    VERSION \u003d \u00271.2\u0027"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    db_model \u003d l3.Router"},{"line_number":204,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"8901824b_6de3d4fe","line":201,"updated":"2023-03-30 08:21:29.000000000","message":"You should probably not mix this change with an API change.","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"72d171506f0177aff402d730291d8f5c55828561","unresolved":false,"context_lines":[{"line_number":198,"context_line":"    # Version 1.0: Initial version"},{"line_number":199,"context_line":"    # Version 1.1: Added \"qos_policy_id\" field"},{"line_number":200,"context_line":"    # Version 1.2: Added the \"gw_ports\" field"},{"line_number":201,"context_line":"    VERSION \u003d \u00271.2\u0027"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    db_model \u003d l3.Router"},{"line_number":204,"context_line":""}],"source_content_type":"text/x-python","patch_set":28,"id":"c13ba422_e2022b5e","line":201,"in_reply_to":"8901824b_6de3d4fe","updated":"2023-04-04 14:27:45.000000000","message":"Done","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"d3d6c4a79664ce3a949eaff18c45ffe5dfc740a7","unresolved":true,"context_lines":[{"line_number":263,"context_line":""},{"line_number":264,"context_line":"        self.gw_ports \u003d [router_port[\u0027port_id\u0027] for"},{"line_number":265,"context_line":"                         router_port in gw_ports]"},{"line_number":266,"context_line":"        self.obj_reset_changes([\u0027gw_ports\u0027])"},{"line_number":267,"context_line":""},{"line_number":268,"context_line":"    def create(self):"},{"line_number":269,"context_line":"        fields \u003d self.obj_get_changes()"}],"source_content_type":"text/x-python","patch_set":28,"id":"b9cd609f_0a8cf300","line":266,"updated":"2023-03-30 08:21:29.000000000","message":"You should probably return changed fields so you avoid to call obj_reset_change two times.","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"72d171506f0177aff402d730291d8f5c55828561","unresolved":false,"context_lines":[{"line_number":263,"context_line":""},{"line_number":264,"context_line":"        self.gw_ports \u003d [router_port[\u0027port_id\u0027] for"},{"line_number":265,"context_line":"                         router_port in gw_ports]"},{"line_number":266,"context_line":"        self.obj_reset_changes([\u0027gw_ports\u0027])"},{"line_number":267,"context_line":""},{"line_number":268,"context_line":"    def create(self):"},{"line_number":269,"context_line":"        fields \u003d self.obj_get_changes()"}],"source_content_type":"text/x-python","patch_set":28,"id":"04934496_c80fc001","line":266,"in_reply_to":"b9cd609f_0a8cf300","updated":"2023-04-04 14:27:45.000000000","message":"Done","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"d3d6c4a79664ce3a949eaff18c45ffe5dfc740a7","unresolved":true,"context_lines":[{"line_number":287,"context_line":"            self.qos_policy_id \u003d db_obj.qos_policy_binding.policy_id"},{"line_number":288,"context_line":"            fields_to_change.append(\u0027qos_policy_id\u0027)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"        self._load_router_gw_ports()"},{"line_number":291,"context_line":"        self.obj_reset_changes(fields_to_change)"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"    def obj_make_compatible(self, primitive, target_version):"}],"source_content_type":"text/x-python","patch_set":28,"id":"2bb8f39e_6fec3594","line":290,"updated":"2023-03-30 08:21:29.000000000","message":"Here is your method return the changed field, you can add that to `fields_to_change`","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"},{"author":{"_account_id":24824,"name":"Dmitrii Shcherbakov","username":"dmitriis"},"change_message_id":"72d171506f0177aff402d730291d8f5c55828561","unresolved":false,"context_lines":[{"line_number":287,"context_line":"            self.qos_policy_id \u003d db_obj.qos_policy_binding.policy_id"},{"line_number":288,"context_line":"            fields_to_change.append(\u0027qos_policy_id\u0027)"},{"line_number":289,"context_line":""},{"line_number":290,"context_line":"        self._load_router_gw_ports()"},{"line_number":291,"context_line":"        self.obj_reset_changes(fields_to_change)"},{"line_number":292,"context_line":""},{"line_number":293,"context_line":"    def obj_make_compatible(self, primitive, target_version):"}],"source_content_type":"text/x-python","patch_set":28,"id":"0d4f3971_1ae312d5","line":290,"in_reply_to":"2bb8f39e_6fec3594","updated":"2023-04-04 14:27:45.000000000","message":"Done","commit_id":"2ba3cae8cc741970711cf5b9b1a81786fcbbb226"}]}
