)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":9,"context_line":"The patch introduces the Main BGP router and a router per chassis."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"TODO:"},{"line_number":12,"context_line":"   - Create switches per chassis per peer"},{"line_number":13,"context_line":"   - Create connection between Neutron and BGP using provider network"},{"line_number":14,"context_line":"     switches"},{"line_number":15,"context_line":"   - Introduce basic OVN agent BGP extension"},{"line_number":16,"context_line":"   - Monitor the configured BGP bridges with the extension"},{"line_number":17,"context_line":"   - Register events to the BGP idls that use the idempotent BGP"},{"line_number":18,"context_line":"     commands to re-configure affected resources"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Related-Bug: #2111276"},{"line_number":21,"context_line":"Assisted-By: claude-4-sonnet"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"c3ae7981_24cc7ca9","line":18,"range":{"start_line":12,"start_character":5,"end_line":18,"end_character":48},"updated":"2025-09-10 09:58:14.000000000","message":"I don\u0027t think we need to mention them here. Just push new patches on top of this one.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":9,"context_line":"The patch introduces the Main BGP router and a router per chassis."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"TODO:"},{"line_number":12,"context_line":"   - Create switches per chassis per peer"},{"line_number":13,"context_line":"   - Create connection between Neutron and BGP using provider network"},{"line_number":14,"context_line":"     switches"},{"line_number":15,"context_line":"   - Introduce basic OVN agent BGP extension"},{"line_number":16,"context_line":"   - Monitor the configured BGP bridges with the extension"},{"line_number":17,"context_line":"   - Register events to the BGP idls that use the idempotent BGP"},{"line_number":18,"context_line":"     commands to re-configure affected resources"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"Related-Bug: #2111276"},{"line_number":21,"context_line":"Assisted-By: claude-4-sonnet"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":4,"id":"1982e389_6937a1d4","line":18,"range":{"start_line":12,"start_character":5,"end_line":18,"end_character":48},"in_reply_to":"c3ae7981_24cc7ca9","updated":"2025-09-10 15:12:37.000000000","message":"Acknowledged","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"64bc6a324ccaa3ebb9ac977880dfdbe5a5f6adbf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"7fc5b969_fccb68f8","updated":"2025-09-08 19:34:37.000000000","message":"I guess I need to split this into smaller patches ..","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"c91c8daf6e9596182606307721b4bbc5dd92dd82","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"4e63a764_4919bf95","in_reply_to":"7fc5b969_fccb68f8","updated":"2025-09-10 09:07:24.000000000","message":"Agree. That will be easier to review.\n\nI know that from PS1 to PS4, you have already reduced the number of commands added. But I think you can push them independently (or grouped by table).","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"fec3d9ee29b6b34aaad2de89de88e64bfddf69f5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"09b1bf81_54925547","updated":"2025-09-11 13:12:26.000000000","message":"Putting temporary -W until past RC1","commit_id":"c89465866d47f7893532a3c9ef5345d9f9c97972"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"c37a12d975e988e78be868749b6b5d2759e6fb3d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"582ea7f9_3d772913","updated":"2025-09-17 17:11:58.000000000","message":"recheck","commit_id":"342dd55acd0b21e101f524a032108f67183ffcf7"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"81f146f4efc0cf2802aca68253aaa90bb509aef3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"5880ce05_12f6244e","updated":"2025-09-18 10:49:18.000000000","message":"recheck neutron-functional","commit_id":"342dd55acd0b21e101f524a032108f67183ffcf7"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"c67042f9c59687064087f0dd389d8f86f51b5a7e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"8f2e51fc_47edce70","updated":"2025-10-14 07:38:24.000000000","message":"recheck functional","commit_id":"f2ad4bad34d322f59d10eb26c12393dbc7955dcd"},{"author":{"_account_id":31291,"name":"Eduardo Olivares","email":"eolivare@redhat.com","username":"eolivare"},"change_message_id":"718b5ef08db229982324d49a0bfb4fe793c9e5ff","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"5750a78d_bc8d9944","updated":"2025-11-20 15:42:00.000000000","message":"bgp functional tests failing neutron.tests.functional.services.bgp\nhttps://zuul.opendev.org/t/openstack/build/42c30a9f46a6401cb99ee131661d25d4","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":31291,"name":"Eduardo Olivares","email":"eolivare@redhat.com","username":"eolivare"},"change_message_id":"a7ee1abfd71755e7d45fdb58694096f064f3bfbb","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"48da7017_6531a246","updated":"2025-11-20 15:06:04.000000000","message":"recheck","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":13861,"name":"yatin","email":"ykarel@redhat.com","username":"yatinkarel"},"change_message_id":"b75016959787ed479a668a8a529c68e02ee8f72d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"c75b58d2_b3e1bb3b","updated":"2025-11-21 07:35:46.000000000","message":"recheck ovsdbapp workaround applied","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b9d7b33bc246c986f58995784c3d50274814b439","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"b221004b_572c9c39","in_reply_to":"5750a78d_bc8d9944","updated":"2025-11-20 19:31:29.000000000","message":"Likely got broken by https://review.opendev.org/c/openstack/ovsdbapp/+/962732","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"044710dc03128602fcd00bf28da6149edfedcd31","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":14,"id":"e570d90f_8cbc3a54","in_reply_to":"b221004b_572c9c39","updated":"2025-11-21 07:37:21.000000000","message":"That\u0027s an issue in the ovsdbapp library, we are releasing a new version reverting the affected patches.","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":31291,"name":"Eduardo Olivares","email":"eolivare@redhat.com","username":"eolivare"},"change_message_id":"6c5f6030cf796d7e19deca081389a6a5d3f1fa74","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"90f9c274_c38562fa","updated":"2025-12-02 13:57:42.000000000","message":"recheck\nhttps://review.opendev.org/c/openstack/ovsdbapp/+/967844 was merged on Nov 21 and should fix functional tests","commit_id":"95c2d3f5b729bcad32d14eb965d6409883fd9962"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"68a78f9700f6833b8ab0c2e624f6c7d873c9f859","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"39e91f44_1ea95781","updated":"2025-12-09 14:42:01.000000000","message":"FTs fixed now","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"540f4dfc_41e6469e","updated":"2025-12-09 16:09:41.000000000","message":"Just a start of review, haven\u0027t made it through the test code yet.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":16,"id":"b05e3703_2f7b3a25","updated":"2025-12-09 19:58:58.000000000","message":"Some comments, but I need to come back to look at more files","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"0d061bcf8ca57af863f8b7fb835c3edf5aadd68e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":17,"id":"6df3757a_7ed47b23","updated":"2025-12-09 19:42:07.000000000","message":"There is an unfinished discussion around how to approach predictable MAC generation - https://review.opendev.org/c/openstack/neutron/+/959890/16..17/neutron/services/bgp/commands.py#b148 please anyone share your opinions :)","commit_id":"5e42366f4a85209793c4c266ad1eaf3263fb3b6b"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"0d8914c637672087e5431e2f0d6e0633e7e14d79","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":19,"id":"b21e2a15_633c420b","updated":"2025-12-10 11:47:19.000000000","message":"recheck - unrelated kernel panic in the grenade job","commit_id":"c6b2c1d61247a2cdd84d804ba7d29886fce28b25"}],"neutron/services/bgp/commands.py":[{"author":{"_account_id":32288,"name":"Martin Kalcok","email":"martin.kalcok@canonical.com","username":"martin.kalcok"},"change_message_id":"724754e4aa8c8ff848d4aa02f9a61a6b3a1e044c","unresolved":true,"context_lines":[{"line_number":551,"context_line":"            # port parameter is OVN output_port column"},{"line_number":552,"context_line":"            port\u003dget_lrp_name(self.router_name, self.switch_name),"},{"line_number":553,"context_line":"            may_exist\u003dTrue,"},{"line_number":554,"context_line":"        ), txn)"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"        # TODO(jlibosva): Workaround for ovsdbapp bug, remove once fixed"},{"line_number":557,"context_line":"        cmd.DbSetCommand("}],"source_content_type":"text/x-python","patch_set":1,"id":"8cdc39df_f3c3d01b","line":554,"updated":"2025-09-10 12:03:16.000000000","message":"Hi @libosvar@redhat.com I haven\u0027t gone through the full review, but I wanted to discuss this static route.\nWith the option `dynamic-routing`[0] enabled, ovn-controller is able to learn routes from the VRF. So if the BGP peer announces default route, and the BGP daemon on the chassis injects it into the VRF, the OVN will pick up the route. Is it then necessary to manually add the route?\n\n[0] https://man7.org/linux/man-pages/man5/ovn-nb.5.html","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":true,"context_lines":[{"line_number":551,"context_line":"            # port parameter is OVN output_port column"},{"line_number":552,"context_line":"            port\u003dget_lrp_name(self.router_name, self.switch_name),"},{"line_number":553,"context_line":"            may_exist\u003dTrue,"},{"line_number":554,"context_line":"        ), txn)"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"        # TODO(jlibosva): Workaround for ovsdbapp bug, remove once fixed"},{"line_number":557,"context_line":"        cmd.DbSetCommand("}],"source_content_type":"text/x-python","patch_set":1,"id":"e6f06a95_9de0768e","line":554,"in_reply_to":"8cdc39df_f3c3d01b","updated":"2025-09-10 15:12:37.000000000","message":"Hi :) yes, I think this is what we discussed on our Monday community meeting. It makes sense, though I haven\u0027t tried it yet. Having it done through BGP would decrease a lot of complexity in this code and the agent that needs to figure out what the peer IP is and then report it to the CMS through the Chassis external_ids column - https://github.com/cubeek/neutron/blob/ovn-native-bgp/neutron/services/bgp/agent/extension.py#L38\n\nThanks for bringing this up, I\u0027ll need to have a closer look at the FRR configuration and how it can put the routes into the monitored VRF.","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":551,"context_line":"            # port parameter is OVN output_port column"},{"line_number":552,"context_line":"            port\u003dget_lrp_name(self.router_name, self.switch_name),"},{"line_number":553,"context_line":"            may_exist\u003dTrue,"},{"line_number":554,"context_line":"        ), txn)"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"        # TODO(jlibosva): Workaround for ovsdbapp bug, remove once fixed"},{"line_number":557,"context_line":"        cmd.DbSetCommand("}],"source_content_type":"text/x-python","patch_set":1,"id":"8c038f81_10c49485","line":554,"in_reply_to":"c8b5290d_41d1b68f","updated":"2025-12-09 18:55:25.000000000","message":"I found a way, I\u0027ll incorporate it in the patch series and will remove the thread monitoring the BGP connections on the node.","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":32288,"name":"Martin Kalcok","email":"martin.kalcok@canonical.com","username":"martin.kalcok"},"change_message_id":"ccc4d9b773917cc5a50c7e99e4eed128ead6df07","unresolved":true,"context_lines":[{"line_number":551,"context_line":"            # port parameter is OVN output_port column"},{"line_number":552,"context_line":"            port\u003dget_lrp_name(self.router_name, self.switch_name),"},{"line_number":553,"context_line":"            may_exist\u003dTrue,"},{"line_number":554,"context_line":"        ), txn)"},{"line_number":555,"context_line":""},{"line_number":556,"context_line":"        # TODO(jlibosva): Workaround for ovsdbapp bug, remove once fixed"},{"line_number":557,"context_line":"        cmd.DbSetCommand("}],"source_content_type":"text/x-python","patch_set":1,"id":"c8b5290d_41d1b68f","line":554,"in_reply_to":"e6f06a95_9de0768e","updated":"2025-09-10 16:29:33.000000000","message":"Sure thing :)\nIf you want to take a look, this is not ideal example [0] (it\u0027s a golang function that generates FRR config), but it can be used to piece together what we use in our experimental microovn branch. Key points are using \"prefix-list\" and \"soft-reconfiguration\" for an \"address-family\", and specifying \"vrf\" for \"router bgp\"\n\n[0] https://github.com/canonical/microovn/blob/34d4c563a125624a3fe2de3d1296f9b3cbbca84d/microovn/frr/bgp/redirect.go#L356","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":58,"context_line":""},{"line_number":59,"context_line":"class LrAddCommand(nb_cmd.LrAddCommand):"},{"line_number":60,"context_line":"    def run_idl(self, txn):"},{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":63,"context_line":"        except idlutils.RowNotFound:"},{"line_number":64,"context_line":"            super().run_idl(txn)"},{"line_number":65,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        self.set_columns(self.result, **self.columns)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"124bf30a_2c3e86f9","line":66,"range":{"start_line":61,"start_character":8,"end_line":66,"end_character":1},"updated":"2025-09-10 09:58:14.000000000","message":"LrAddCommand.run_idl will do the same if `self.may_exist\u003dTrue`\n\nhttps://github.com/openstack/ovsdbapp/blob/b61e1551f512d78bffbc8862132f5f9b193da9cf/ovsdbapp/schema/ovn_northbound/commands.py#L810-L818","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":true,"context_lines":[{"line_number":58,"context_line":""},{"line_number":59,"context_line":"class LrAddCommand(nb_cmd.LrAddCommand):"},{"line_number":60,"context_line":"    def run_idl(self, txn):"},{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":63,"context_line":"        except idlutils.RowNotFound:"},{"line_number":64,"context_line":"            super().run_idl(txn)"},{"line_number":65,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        self.set_columns(self.result, **self.columns)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"4696c80c_8bfcd792","line":66,"range":{"start_line":61,"start_character":8,"end_line":66,"end_character":1},"in_reply_to":"124bf30a_2c3e86f9","updated":"2025-09-10 15:12:37.000000000","message":"ovsdbapp creates the entry if it doesn\u0027t exist and returns the existing object if the entry exists. But if we want to have idempotent commands, we also need to set the columns, with `may_exist\u003dTrue` this is ignore. That is the reason why I had to do the lookup and then explicitly set the columns.\n\nFor example\n```\nLrAddCommand(\u0027lr1\u0027, external_ids\u003d{\u0027foo\u0027: \u0027bar\u0027}).execute(check_errors\u003dTrue)\nLrAddCommand(\u0027lr1\u0027, may_exist\u003dTrue, external_ids\u003d{\u0027bar\u0027: \u0027baz\u0027}).execute(check_errors\u003dTrue)\n```\nwill result in having only `\u0027foo\u0027: \u0027bar\u0027` in the `external_ids`.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"59b47f13299f0c0206a29cd8111df5fc63b27001","unresolved":false,"context_lines":[{"line_number":58,"context_line":""},{"line_number":59,"context_line":"class LrAddCommand(nb_cmd.LrAddCommand):"},{"line_number":60,"context_line":"    def run_idl(self, txn):"},{"line_number":61,"context_line":"        try:"},{"line_number":62,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":63,"context_line":"        except idlutils.RowNotFound:"},{"line_number":64,"context_line":"            super().run_idl(txn)"},{"line_number":65,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        self.set_columns(self.result, **self.columns)"},{"line_number":68,"context_line":""},{"line_number":69,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"2a6468df_3ddc98be","line":66,"range":{"start_line":61,"start_character":8,"end_line":66,"end_character":1},"in_reply_to":"4696c80c_8bfcd792","updated":"2025-09-11 06:51:20.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":74,"context_line":"        super().__init__(api, router_name, lrp_name, mac, networks, **kwargs)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def run_idl(self, txn):"},{"line_number":77,"context_line":"        try:"},{"line_number":78,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router_Port\u0027, self.port)"},{"line_number":79,"context_line":"        except idlutils.RowNotFound:"},{"line_number":80,"context_line":"            super().run_idl(txn)"},{"line_number":81,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router_Port\u0027, self.port)"},{"line_number":82,"context_line":"        self.result.mac \u003d self.mac"},{"line_number":83,"context_line":"        self.result.networks \u003d self.networks"},{"line_number":84,"context_line":"        self.result.peer \u003d self.peer"}],"source_content_type":"text/x-python","patch_set":4,"id":"f992a3ed_1688b14b","line":81,"range":{"start_line":77,"start_character":8,"end_line":81,"end_character":75},"updated":"2025-09-10 09:58:14.000000000","message":"same comment, you just need to set `self.may_exist\u003dTrue`","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"59b47f13299f0c0206a29cd8111df5fc63b27001","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        super().__init__(api, router_name, lrp_name, mac, networks, **kwargs)"},{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    def run_idl(self, txn):"},{"line_number":77,"context_line":"        try:"},{"line_number":78,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router_Port\u0027, self.port)"},{"line_number":79,"context_line":"        except idlutils.RowNotFound:"},{"line_number":80,"context_line":"            super().run_idl(txn)"},{"line_number":81,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router_Port\u0027, self.port)"},{"line_number":82,"context_line":"        self.result.mac \u003d self.mac"},{"line_number":83,"context_line":"        self.result.networks \u003d self.networks"},{"line_number":84,"context_line":"        self.result.peer \u003d self.peer"}],"source_content_type":"text/x-python","patch_set":4,"id":"85371e8d_78a20b0a","line":81,"range":{"start_line":77,"start_character":8,"end_line":81,"end_character":75},"in_reply_to":"f992a3ed_1688b14b","updated":"2025-09-11 06:51:20.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"class HAChassisGroupAddCommand(nb_cmd.HAChassisGroupAddCommand):"},{"line_number":89,"context_line":"    def run_idl(self, txn):"},{"line_number":90,"context_line":"        try:"},{"line_number":91,"context_line":"            hcg \u003d self.api.lookup(\u0027HA_Chassis_Group\u0027, self.name)"},{"line_number":92,"context_line":"        except idlutils.RowNotFound:"},{"line_number":93,"context_line":"            super().run_idl(txn)"},{"line_number":94,"context_line":"            hcg \u003d self.api.lookup(\u0027HA_Chassis_Group\u0027, self.name)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"        self.set_columns(hcg, **self.columns)"},{"line_number":97,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"b462ecb5_7bf97db7","line":94,"range":{"start_line":90,"start_character":8,"end_line":94,"end_character":64},"updated":"2025-09-10 09:58:14.000000000","message":"same comment","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"59b47f13299f0c0206a29cd8111df5fc63b27001","unresolved":false,"context_lines":[{"line_number":87,"context_line":""},{"line_number":88,"context_line":"class HAChassisGroupAddCommand(nb_cmd.HAChassisGroupAddCommand):"},{"line_number":89,"context_line":"    def run_idl(self, txn):"},{"line_number":90,"context_line":"        try:"},{"line_number":91,"context_line":"            hcg \u003d self.api.lookup(\u0027HA_Chassis_Group\u0027, self.name)"},{"line_number":92,"context_line":"        except idlutils.RowNotFound:"},{"line_number":93,"context_line":"            super().run_idl(txn)"},{"line_number":94,"context_line":"            hcg \u003d self.api.lookup(\u0027HA_Chassis_Group\u0027, self.name)"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"        self.set_columns(hcg, **self.columns)"},{"line_number":97,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"c8f32de0_68e50231","line":94,"range":{"start_line":90,"start_character":8,"end_line":94,"end_character":64},"in_reply_to":"b462ecb5_7bf97db7","updated":"2025-09-11 06:51:20.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"class ReconcileChassisRouterCommand(ReconcileRouterCommand):"},{"line_number":148,"context_line":"    def __init__(self, api, name, chassis):"},{"line_number":149,"context_line":"        self.chassis \u003d chassis"},{"line_number":150,"context_line":"        super().__init__(api, name)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":4,"id":"5a7405dd_ab027294","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":30},"updated":"2025-09-10 09:58:14.000000000","message":"Are we pinning the LRP to a chassis?","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"59b47f13299f0c0206a29cd8111df5fc63b27001","unresolved":false,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"class ReconcileChassisRouterCommand(ReconcileRouterCommand):"},{"line_number":148,"context_line":"    def __init__(self, api, name, chassis):"},{"line_number":149,"context_line":"        self.chassis \u003d chassis"},{"line_number":150,"context_line":"        super().__init__(api, name)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":4,"id":"023c70a4_706cb9a5","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":30},"in_reply_to":"2f642c43_f1588a2d","updated":"2025-09-11 06:51:20.000000000","message":"Ahhh ok, this is the per-node router that BGP creates that will be bound only in this node.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":true,"context_lines":[{"line_number":146,"context_line":""},{"line_number":147,"context_line":"class ReconcileChassisRouterCommand(ReconcileRouterCommand):"},{"line_number":148,"context_line":"    def __init__(self, api, name, chassis):"},{"line_number":149,"context_line":"        self.chassis \u003d chassis"},{"line_number":150,"context_line":"        super().__init__(api, name)"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    @property"}],"source_content_type":"text/x-python","patch_set":4,"id":"2f642c43_f1588a2d","line":149,"range":{"start_line":149,"start_character":8,"end_line":149,"end_character":30},"in_reply_to":"5a7405dd_ab027294","updated":"2025-09-10 15:12:37.000000000","message":"We bind each \u0027per-chassis router\u0027 to a chassis and then we use ha_chassis_group to also bind the peer LRP on the BGP main router side to the same chassis.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":236,"context_line":"        self.sb_api \u003d sb_api"},{"line_number":237,"context_line":"        self.chassis \u003d chassis"},{"line_number":238,"context_line":"        self.hostname \u003d self.chassis.hostname.split(\u0027.\u0027)[0]"},{"line_number":239,"context_line":"        self.chassis_index \u003d helpers.get_chassis_index(self.chassis)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def run_idl(self, txn):"},{"line_number":242,"context_line":"        hcg_name \u003d helpers.get_hcg_name(self.hostname)"}],"source_content_type":"text/x-python","patch_set":15,"id":"94a2ed38_a835d663","line":239,"updated":"2025-12-09 16:09:41.000000000","message":"This looks like it is unused.","commit_id":"95c2d3f5b729bcad32d14eb965d6409883fd9962"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":236,"context_line":"        self.sb_api \u003d sb_api"},{"line_number":237,"context_line":"        self.chassis \u003d chassis"},{"line_number":238,"context_line":"        self.hostname \u003d self.chassis.hostname.split(\u0027.\u0027)[0]"},{"line_number":239,"context_line":"        self.chassis_index \u003d helpers.get_chassis_index(self.chassis)"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    def run_idl(self, txn):"},{"line_number":242,"context_line":"        hcg_name \u003d helpers.get_hcg_name(self.hostname)"}],"source_content_type":"text/x-python","patch_set":15,"id":"9259e3f3_b3c5f7b0","line":239,"in_reply_to":"94a2ed38_a835d663","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"95c2d3f5b729bcad32d14eb965d6409883fd9962"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":33,"context_line":"    return cmd.result"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class _LrAddCommand(nb_cmd.LrAddCommand):"},{"line_number":37,"context_line":"    def run_idl(self, txn):"},{"line_number":38,"context_line":"        try:"},{"line_number":39,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"}],"source_content_type":"text/x-python","patch_set":16,"id":"4e18eec8_ae09b554","line":36,"updated":"2025-12-09 16:09:41.000000000","message":"A comment explaining why we subclass the Command objects to basically make them add-or-updated commands might be helpful for people new to the code.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    return cmd.result"},{"line_number":34,"context_line":""},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"class _LrAddCommand(nb_cmd.LrAddCommand):"},{"line_number":37,"context_line":"    def run_idl(self, txn):"},{"line_number":38,"context_line":"        try:"},{"line_number":39,"context_line":"            self.result \u003d self.api.lookup(\u0027Logical_Router\u0027, self.router)"}],"source_content_type":"text/x-python","patch_set":16,"id":"c0ab6496_d088ae88","line":36,"in_reply_to":"4e18eec8_ae09b554","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":true,"context_lines":[{"line_number":83,"context_line":"        # won\u0027t have that set until the transaction is committed"},{"line_number":84,"context_line":"        super().__init__("},{"line_number":85,"context_line":"            api, name, may_exist\u003dTrue, policies\u003d[], static_routes\u003d[])"},{"line_number":86,"context_line":"        mm \u003d helpers.LrpMacManager.get_instance()"},{"line_number":87,"context_line":"        mm.register_router(name, self.router_mac_prefix)"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def run_idl(self, txn):"}],"source_content_type":"text/x-python","patch_set":16,"id":"0740281b_e9fd3ea6","line":86,"range":{"start_line":86,"start_character":8,"end_line":86,"end_character":10},"updated":"2025-12-09 19:58:58.000000000","message":"nit: `mac_manager` or `mac_mgr`","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cc76735b31bd5003abc347088eac55c81b47d17","unresolved":false,"context_lines":[{"line_number":83,"context_line":"        # won\u0027t have that set until the transaction is committed"},{"line_number":84,"context_line":"        super().__init__("},{"line_number":85,"context_line":"            api, name, may_exist\u003dTrue, policies\u003d[], static_routes\u003d[])"},{"line_number":86,"context_line":"        mm \u003d helpers.LrpMacManager.get_instance()"},{"line_number":87,"context_line":"        mm.register_router(name, self.router_mac_prefix)"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"    def run_idl(self, txn):"}],"source_content_type":"text/x-python","patch_set":16,"id":"c971651e_41bfe28a","line":86,"range":{"start_line":86,"start_character":8,"end_line":86,"end_character":10},"in_reply_to":"0740281b_e9fd3ea6","updated":"2025-12-09 22:38:58.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":119,"context_line":"        }"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    @classmethod"},{"line_number":122,"context_line":"    def get_name(cls):"},{"line_number":123,"context_line":"        return bgp_config.get_main_router_name()"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"94c1f270_8981b53a","line":122,"range":{"start_line":122,"start_character":17,"end_line":122,"end_character":20},"updated":"2025-12-09 16:09:41.000000000","message":"cls is unused, so this could be staticmethod, but as `get_name()` is only used in `__init__()` once, it could also just be done inline.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":119,"context_line":"        }"},{"line_number":120,"context_line":""},{"line_number":121,"context_line":"    @classmethod"},{"line_number":122,"context_line":"    def get_name(cls):"},{"line_number":123,"context_line":"        return bgp_config.get_main_router_name()"},{"line_number":124,"context_line":""},{"line_number":125,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"daf84333_7334d9a7","line":122,"range":{"start_line":122,"start_character":17,"end_line":122,"end_character":20},"in_reply_to":"94c1f270_8981b53a","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"class ReconcileChassisRouterCommand(ReconcileRouterCommand):"},{"line_number":127,"context_line":"    def __init__(self, api, name, chassis):"},{"line_number":128,"context_line":"        self.chassis \u003d chassis"},{"line_number":129,"context_line":"        super().__init__(api, name)"},{"line_number":130,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"cfbb5406_b0a05564","line":127,"range":{"start_line":127,"start_character":28,"end_line":127,"end_character":32},"updated":"2025-12-09 16:09:41.000000000","message":"It looks like the router name is now wholly dependent on the Chassis, so like the MainRouter, we might not need to actually pass in `name`.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":124,"context_line":""},{"line_number":125,"context_line":""},{"line_number":126,"context_line":"class ReconcileChassisRouterCommand(ReconcileRouterCommand):"},{"line_number":127,"context_line":"    def __init__(self, api, name, chassis):"},{"line_number":128,"context_line":"        self.chassis \u003d chassis"},{"line_number":129,"context_line":"        super().__init__(api, name)"},{"line_number":130,"context_line":""}],"source_content_type":"text/x-python","patch_set":16,"id":"90a8468a_8e8996ae","line":127,"range":{"start_line":127,"start_character":28,"end_line":127,"end_character":32},"in_reply_to":"cfbb5406_b0a05564","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":145,"context_line":"        return f\u0027{base_mac}:{hex_str[0:2]}:{hex_str[2:4]}\u0027"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"class IndexAllChassis(ovs_cmd.BaseCommand):"},{"line_number":149,"context_line":"    def run_idl(self, txn):"},{"line_number":150,"context_line":"        used_indexes \u003d set()"},{"line_number":151,"context_line":"        chassis_without_index \u003d []"}],"source_content_type":"text/x-python","patch_set":16,"id":"ceb0f265_333cd764","line":148,"updated":"2025-12-09 16:09:41.000000000","message":"We\u0027ve chatted offline about this, but I figure there could be some public discussion. I am likely to get some details wrong, so please correct my mistakes. 😜\n\nThis currently would only run during a full-sync, which only happens at startup right now--but maybe could happen more in the future w/ scaling in/out Chassis.\n\nThe Indexing, my understanding is this primarily about being able to generate repeatable MAC addresses so that when we do ConnectRouterToMainRouterCommand, the LRP on the main router connected to the chassis can get the same MAC, for the purpose of idempotency, e.g. if a customer modifies the MAC directly in the DB, we will notice and change it back (though we don\u0027t currently have events to detect this change). And partially, changing the MAC back is easier than just updating the other things that change based on the MAC (IPv6 LLA for routing, etc.).\n\nIf we could make the MAC address something directly relatable to the LRP name (or chassis as that is the ultimate basis), then it seems like we could avoid all of the MAC tracking stuff. The address space would be 46 bits, IIRC, so if we are just generating randomly (e.g. taking a name/uuid5 -\u003e mac hash fn), we\u0027d be looking at a 1:70 trillion chance for collision. This is a lot less that a GUID, but we only have to be unique to one L2 domain, so at most like 500 mac. That\u0027d be like 500 people colliding on 10 earths worth of people, and seems reasonable to me, though it wouldn\u0027t be too hard to handle collisions if we really had to.\n\nWe don\u0027t currently handle scaling in/out Chassis, but when we do we need to be careful re: Chassis/Chassis_Private deletion, since deletion does not actually mean the Chassis is gone forever--ovn-controller shutting down gracefully will always delete these for example, and we may or may not want to recreate everything associated with the Chassis when this happens (the names will match, but the uuids will not). Neutron agent code, for example, goes to great lengths to make sure that an \"agent\" is only deleted if we call `network agent delete` even if the Chassis row disappears. If we handle Chassis deletion, if a couple of computes are shutdown cleanly, the indexes will disappear from the newly recreated Chassis external_ids. And the existing code wouldn\u0027t necessarily put the indexes back to where they were, etc.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"400e0b96b7530af7c9e048a26bf090d1eb6b6c07","unresolved":false,"context_lines":[{"line_number":145,"context_line":"        return f\u0027{base_mac}:{hex_str[0:2]}:{hex_str[2:4]}\u0027"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"class IndexAllChassis(ovs_cmd.BaseCommand):"},{"line_number":149,"context_line":"    def run_idl(self, txn):"},{"line_number":150,"context_line":"        used_indexes \u003d set()"},{"line_number":151,"context_line":"        chassis_without_index \u003d []"}],"source_content_type":"text/x-python","patch_set":16,"id":"8c57f3f2_40c4d39c","line":148,"in_reply_to":"23b3a764_08545211","updated":"2025-12-11 21:56:36.000000000","message":"\\o/","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"43f115bf42e92c5902511ce6c889ab02b2be8113","unresolved":true,"context_lines":[{"line_number":145,"context_line":"        return f\u0027{base_mac}:{hex_str[0:2]}:{hex_str[2:4]}\u0027"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"class IndexAllChassis(ovs_cmd.BaseCommand):"},{"line_number":149,"context_line":"    def run_idl(self, txn):"},{"line_number":150,"context_line":"        used_indexes \u003d set()"},{"line_number":151,"context_line":"        chassis_without_index \u003d []"}],"source_content_type":"text/x-python","patch_set":16,"id":"23b3a764_08545211","line":148,"in_reply_to":"81ef5803_7c2e060f","updated":"2025-12-10 16:01:35.000000000","message":"An attempt to address this is at https://review.opendev.org/c/openstack/neutron/+/970409/1\n\nIf it\u0027s good and it makes sense, I can squash it into this patch.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":true,"context_lines":[{"line_number":145,"context_line":"        return f\u0027{base_mac}:{hex_str[0:2]}:{hex_str[2:4]}\u0027"},{"line_number":146,"context_line":""},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"class IndexAllChassis(ovs_cmd.BaseCommand):"},{"line_number":149,"context_line":"    def run_idl(self, txn):"},{"line_number":150,"context_line":"        used_indexes \u003d set()"},{"line_number":151,"context_line":"        chassis_without_index \u003d []"}],"source_content_type":"text/x-python","patch_set":16,"id":"81ef5803_7c2e060f","line":148,"in_reply_to":"ceb0f265_333cd764","updated":"2025-12-09 18:55:25.000000000","message":"I\u0027d just add to this that the consistent MAC generation must be also available when wiring the Neutron logical routers to the BGP router. Although this does not use the chassis indexes, and the resources used to wire into the \"Neutron world\" use different MAC prefix, I wanted to provide the full picture.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"}],"neutron/services/bgp/constants.py":[{"author":{"_account_id":32288,"name":"Martin Kalcok","email":"martin.kalcok@canonical.com","username":"martin.kalcok"},"change_message_id":"d55197057fa1d5a1d6237ecfc8b927c4c1e3e740","unresolved":true,"context_lines":[{"line_number":18,"context_line":"LRP_CHASSIS_TO_MAIN_ROUTER \u003d 1"},{"line_number":19,"context_line":"LRP_MAIN_ROUTER_TO_CHASSIS \u003d 2"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"BGP_ROUTER_REDISTRIBUTE \u003d \u0027connected-as-host,nat\u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"1c92df26_b2622889","line":21,"updated":"2025-11-13 18:07:16.000000000","message":"Out of curiosity, why are LB IPs not redistributed?","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d9218b3d31893796b7e904b48d6a56d63ce2cd79","unresolved":true,"context_lines":[{"line_number":18,"context_line":"LRP_CHASSIS_TO_MAIN_ROUTER \u003d 1"},{"line_number":19,"context_line":"LRP_MAIN_ROUTER_TO_CHASSIS \u003d 2"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"BGP_ROUTER_REDISTRIBUTE \u003d \u0027connected-as-host,nat\u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"d9174077_06c4f14e","line":21,"in_reply_to":"1c92df26_b2622889","updated":"2025-11-17 15:43:49.000000000","message":"I have not got to work on that yet. That comes later.","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":32288,"name":"Martin Kalcok","email":"martin.kalcok@canonical.com","username":"martin.kalcok"},"change_message_id":"077e0d1b5e1719dfcfa1b0e662353cfcecc5b51f","unresolved":false,"context_lines":[{"line_number":18,"context_line":"LRP_CHASSIS_TO_MAIN_ROUTER \u003d 1"},{"line_number":19,"context_line":"LRP_MAIN_ROUTER_TO_CHASSIS \u003d 2"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"BGP_ROUTER_REDISTRIBUTE \u003d \u0027connected-as-host,nat\u0027"}],"source_content_type":"text/x-python","patch_set":14,"id":"de9f50cc_8e11a088","line":21,"in_reply_to":"d9174077_06c4f14e","updated":"2025-11-17 15:46:59.000000000","message":"ack, thanks.","commit_id":"5ab116a287d2c9496a8e5db45a372000f3f282b4"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":true,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING \u003d \u0027dynamic-routing\u0027"},{"line_number":26,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING_REDISTRIBUTE \u003d \u0027dynamic-routing-redistribute\u0027"},{"line_number":27,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING_VRF_ID \u003d \u0027dynamic-routing-vrf-id\u0027"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"HA_CHASSIS_GROUP_PRIORITY \u003d 10"}],"source_content_type":"text/x-python","patch_set":16,"id":"f5c4f01b_17b420d6","line":27,"range":{"start_line":27,"start_character":37,"end_line":27,"end_character":60},"updated":"2025-12-09 19:58:58.000000000","message":"Looking at ovn-nb man page [1] this should be `dynamic-routing-vrf-name` , right?\n\n[1] https://man7.org/linux/man-pages/man5/ovn-nb.5.html#Logical_Router_TABLE","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cc76735b31bd5003abc347088eac55c81b47d17","unresolved":false,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING \u003d \u0027dynamic-routing\u0027"},{"line_number":26,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING_REDISTRIBUTE \u003d \u0027dynamic-routing-redistribute\u0027"},{"line_number":27,"context_line":"LR_OPTIONS_DYNAMIC_ROUTING_VRF_ID \u003d \u0027dynamic-routing-vrf-id\u0027"},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"HA_CHASSIS_GROUP_PRIORITY \u003d 10"}],"source_content_type":"text/x-python","patch_set":16,"id":"b4607d28_baef49c7","line":27,"range":{"start_line":27,"start_character":37,"end_line":27,"end_character":60},"in_reply_to":"f5c4f01b_17b420d6","updated":"2025-12-09 22:38:58.000000000","message":"No, you might be referring to an old man page, this option was introduced recently and it should really be `-id`. Thanks for checking thoroughly though :)\n\nhttps://github.com/ovn-org/ovn/blob/4ff608e9179ed85dd7031e820be7d03d479ef6b2/ovn-nb.xml#L3403-L3422","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"}],"neutron/services/bgp/helpers.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":34,"context_line":"    def __init__(self):"},{"line_number":35,"context_line":"        self.known_routers \u003d {}"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    @classmethod"},{"line_number":38,"context_line":"    def get_instance(cls):"},{"line_number":39,"context_line":"        if not hasattr(cls, \u0027_instance\u0027):"},{"line_number":40,"context_line":"            cls._instance \u003d cls()"},{"line_number":41,"context_line":"        return cls._instance"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def register_router(self, router_name, mac_prefix):"},{"line_number":44,"context_line":"        self.known_routers[router_name] \u003d Router("}],"source_content_type":"text/x-python","patch_set":4,"id":"fa532da4_907e3de9","line":41,"range":{"start_line":37,"start_character":0,"end_line":41,"end_character":28},"updated":"2025-09-10 09:58:14.000000000","message":"We have a `common.utils.SingletonDecorator` class decorator.\n\nNOTE: these kind of resources must be handled carefully in the test cases. You must reset any reference to this instantiated object. E.g.: https://review.opendev.org/c/openstack/neutron/+/944099/10/neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/extensions/test_placement.py","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"015ecfc728333e49fa44e6584baf2f9fde7c1cf5","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    def __init__(self):"},{"line_number":35,"context_line":"        self.known_routers \u003d {}"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    @classmethod"},{"line_number":38,"context_line":"    def get_instance(cls):"},{"line_number":39,"context_line":"        if not hasattr(cls, \u0027_instance\u0027):"},{"line_number":40,"context_line":"            cls._instance \u003d cls()"},{"line_number":41,"context_line":"        return cls._instance"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def register_router(self, router_name, mac_prefix):"},{"line_number":44,"context_line":"        self.known_routers[router_name] \u003d Router("}],"source_content_type":"text/x-python","patch_set":4,"id":"f85ea67c_5ba157d0","line":41,"range":{"start_line":37,"start_character":0,"end_line":41,"end_character":28},"in_reply_to":"8dbd94b6_54c151cb","updated":"2025-09-10 15:37:24.000000000","message":"I found out I can\u0027t use the SingletonDecorator because the decorator is actually not creating a singleton. The created object is garbage collected if it\u0027s not referenced and I\u0027m not referencing the LrpMacManager anywhere, just getting the instance on demand.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    def __init__(self):"},{"line_number":35,"context_line":"        self.known_routers \u003d {}"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    @classmethod"},{"line_number":38,"context_line":"    def get_instance(cls):"},{"line_number":39,"context_line":"        if not hasattr(cls, \u0027_instance\u0027):"},{"line_number":40,"context_line":"            cls._instance \u003d cls()"},{"line_number":41,"context_line":"        return cls._instance"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    def register_router(self, router_name, mac_prefix):"},{"line_number":44,"context_line":"        self.known_routers[router_name] \u003d Router("}],"source_content_type":"text/x-python","patch_set":4,"id":"8dbd94b6_54c151cb","line":41,"range":{"start_line":37,"start_character":0,"end_line":41,"end_character":28},"in_reply_to":"fa532da4_907e3de9","updated":"2025-09-10 15:12:37.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":43,"context_line":"    def register_router(self, router_name, mac_prefix):"},{"line_number":44,"context_line":"        self.known_routers[router_name] \u003d Router("},{"line_number":45,"context_line":"            mac_prefix\u003dmac_prefix,"},{"line_number":46,"context_line":"            max_mac_index\u003d255 ** (MAC_BYTES - len(mac_prefix.split(\u0027:\u0027))) - 1,"},{"line_number":47,"context_line":"            remaining_bytes\u003dMAC_BYTES - len(mac_prefix.split(\u0027:\u0027)),"},{"line_number":48,"context_line":"        )"},{"line_number":49,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"746546b2_5f74a74c","line":46,"range":{"start_line":46,"start_character":26,"end_line":46,"end_character":77},"updated":"2025-09-10 09:58:14.000000000","message":"A private method explaining the rationale of this will help to understand why this is needed.","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    def register_router(self, router_name, mac_prefix):"},{"line_number":44,"context_line":"        self.known_routers[router_name] \u003d Router("},{"line_number":45,"context_line":"            mac_prefix\u003dmac_prefix,"},{"line_number":46,"context_line":"            max_mac_index\u003d255 ** (MAC_BYTES - len(mac_prefix.split(\u0027:\u0027))) - 1,"},{"line_number":47,"context_line":"            remaining_bytes\u003dMAC_BYTES - len(mac_prefix.split(\u0027:\u0027)),"},{"line_number":48,"context_line":"        )"},{"line_number":49,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"e9e028d2_eba15843","line":46,"range":{"start_line":46,"start_character":26,"end_line":46,"end_character":77},"in_reply_to":"746546b2_5f74a74c","updated":"2025-09-10 15:12:37.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":58,"context_line":"                f\"Index {index} is out of range, maximum is \""},{"line_number":59,"context_line":"                f\"{router.max_mac_index}\")"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        hex_str \u003d f\"{index:0{router.remaining_bytes * 2}x}\""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        hex_bytes \u003d \u0027:\u0027.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        result \u003d f\u0027{router.mac_prefix}:{hex_bytes}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        if not MAC_RE.match(result):"},{"line_number":68,"context_line":"            raise ValueError(f\"Invalid MAC address: {result}\")"}],"source_content_type":"text/x-python","patch_set":4,"id":"a0fe0e9e_4373ea45","line":65,"range":{"start_line":61,"start_character":8,"end_line":65,"end_character":51},"updated":"2025-09-10 09:58:14.000000000","message":"Please, add a comment of what are you doing here. Something like\n``\nmac_prefix \u003d \"aa:bb:cc\", index \u003d 1\n--\u003e result \u003d \"aa:bb:cc:00:00:01\"\n``","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":58,"context_line":"                f\"Index {index} is out of range, maximum is \""},{"line_number":59,"context_line":"                f\"{router.max_mac_index}\")"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        hex_str \u003d f\"{index:0{router.remaining_bytes * 2}x}\""},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        hex_bytes \u003d \u0027:\u0027.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        result \u003d f\u0027{router.mac_prefix}:{hex_bytes}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        if not MAC_RE.match(result):"},{"line_number":68,"context_line":"            raise ValueError(f\"Invalid MAC address: {result}\")"}],"source_content_type":"text/x-python","patch_set":4,"id":"b7d8d069_e4c01b43","line":65,"range":{"start_line":61,"start_character":8,"end_line":65,"end_character":51},"in_reply_to":"a0fe0e9e_4373ea45","updated":"2025-09-10 15:12:37.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        result \u003d f\u0027{router.mac_prefix}:{hex_bytes}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        if not MAC_RE.match(result):"},{"line_number":68,"context_line":"            raise ValueError(f\"Invalid MAC address: {result}\")"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        return result"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"e000249d_2a5e3cb8","line":68,"range":{"start_line":67,"start_character":8,"end_line":68,"end_character":62},"updated":"2025-09-10 09:58:14.000000000","message":"Here you can use `netaddr.EUI(result)` (that will raise `netaddr.core.AddrFormatError` in case of error)  and then return `neutron_lib.api.converters.convert_to_sanitized_mac_address`, that will return a xx:xx:xx:xx:xx:xx string (lower cases always)","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        result \u003d f\u0027{router.mac_prefix}:{hex_bytes}\u0027"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"        if not MAC_RE.match(result):"},{"line_number":68,"context_line":"            raise ValueError(f\"Invalid MAC address: {result}\")"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        return result"},{"line_number":71,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"f3e82858_b99462aa","line":68,"range":{"start_line":67,"start_character":8,"end_line":68,"end_character":62},"in_reply_to":"e000249d_2a5e3cb8","updated":"2025-09-10 15:12:37.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":true,"context_lines":[{"line_number":22,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class Router:"},{"line_number":26,"context_line":"    MAC_BYTES \u003d 6"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __init__(self, mac_prefix):"}],"source_content_type":"text/x-python","patch_set":16,"id":"02b396ca_eb4e8bf9","line":25,"updated":"2025-12-09 19:58:58.000000000","message":"nit: more like `BgpRouterMac` class or `BgpRouterMacPrefix`. When I read `Router` I was expecting an actual router implementation :)","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cc76735b31bd5003abc347088eac55c81b47d17","unresolved":false,"context_lines":[{"line_number":22,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"class Router:"},{"line_number":26,"context_line":"    MAC_BYTES \u003d 6"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __init__(self, mac_prefix):"}],"source_content_type":"text/x-python","patch_set":16,"id":"862f6b6d_c86de2e0","line":25,"in_reply_to":"02b396ca_eb4e8bf9","updated":"2025-12-09 22:38:58.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":true,"context_lines":[{"line_number":26,"context_line":"    MAC_BYTES \u003d 6"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __init__(self, mac_prefix):"},{"line_number":29,"context_line":"        remaining_bytes \u003d self.MAC_BYTES - len(mac_prefix.split(\u0027:\u0027))"},{"line_number":30,"context_line":"        self.mac_prefix \u003d mac_prefix"},{"line_number":31,"context_line":"        self.max_mac_index \u003d self.calculate_max_mac_generated(remaining_bytes)"},{"line_number":32,"context_line":"        self.remaining_bytes \u003d remaining_bytes"}],"source_content_type":"text/x-python","patch_set":16,"id":"df7d5c3f_5ff05be4","line":29,"updated":"2025-12-09 19:58:58.000000000","message":"I think you should guard this little more, since the `bgp_mac_base` is user configurable. Someone can pass you \"bad prefix\" e.g. 00:01:02:03:04:05:06:07. which will yield negative `remaining_bytes`\n\nAlso(probably overkill), but if the string does not contain `:`, things will not compute properly.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cc76735b31bd5003abc347088eac55c81b47d17","unresolved":false,"context_lines":[{"line_number":26,"context_line":"    MAC_BYTES \u003d 6"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"    def __init__(self, mac_prefix):"},{"line_number":29,"context_line":"        remaining_bytes \u003d self.MAC_BYTES - len(mac_prefix.split(\u0027:\u0027))"},{"line_number":30,"context_line":"        self.mac_prefix \u003d mac_prefix"},{"line_number":31,"context_line":"        self.max_mac_index \u003d self.calculate_max_mac_generated(remaining_bytes)"},{"line_number":32,"context_line":"        self.remaining_bytes \u003d remaining_bytes"}],"source_content_type":"text/x-python","patch_set":16,"id":"d89d9ad4_f9497b4c","line":29,"in_reply_to":"df7d5c3f_5ff05be4","updated":"2025-12-09 22:38:58.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":104,"context_line":""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"def get_hcg_name(chassis_uuid):"},{"line_number":107,"context_line":"    return f\u0027bgp-hcg-{chassis_uuid}\u0027"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def get_chassis_router_name(chassis_uuid):"}],"source_content_type":"text/x-python","patch_set":16,"id":"f57abea1_142553d0","line":107,"updated":"2025-12-09 16:09:41.000000000","message":"The calling functions correctly pass the chassis name, but I think the attribute should be chassis_name as the uuid can change just when rebooting a compute node and I\u0027d hate to see someone get confused. Or just pass in a Chassis object and grab the name internally.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":104,"context_line":""},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"def get_hcg_name(chassis_uuid):"},{"line_number":107,"context_line":"    return f\u0027bgp-hcg-{chassis_uuid}\u0027"},{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def get_chassis_router_name(chassis_uuid):"}],"source_content_type":"text/x-python","patch_set":16,"id":"a8ad6e79_f41bf175","line":107,"in_reply_to":"f57abea1_142553d0","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"238a9ad42ad742d975aad6e3baabbdc5bc7c8b48","unresolved":true,"context_lines":[{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def get_chassis_router_name(chassis_uuid):"},{"line_number":111,"context_line":"    return f\u0027bgp-lr-{chassis_uuid}\u0027"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"def get_chassis_index(chassis):"}],"source_content_type":"text/x-python","patch_set":16,"id":"be6b3f17_1e11c5ef","line":111,"updated":"2025-12-09 16:09:41.000000000","message":"Same.","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"ea379e41b58ba687104154daf30e8bf8e6c74aa8","unresolved":false,"context_lines":[{"line_number":108,"context_line":""},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"def get_chassis_router_name(chassis_uuid):"},{"line_number":111,"context_line":"    return f\u0027bgp-lr-{chassis_uuid}\u0027"},{"line_number":112,"context_line":""},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"def get_chassis_index(chassis):"}],"source_content_type":"text/x-python","patch_set":16,"id":"54ddcbcb_b93fdb8f","line":111,"in_reply_to":"be6b3f17_1e11c5ef","updated":"2025-12-09 18:55:25.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":34271,"name":"Miro Tomaska","display_name":"Miro Tomaska","email":"mtomaska@redhat.com","username":"mtomaska"},"change_message_id":"44f64d3f601181c69c2d567750cdab65d439555a","unresolved":true,"context_lines":[{"line_number":115,"context_line":"    try:"},{"line_number":116,"context_line":"        return int(chassis.external_ids[constants.OVN_BGP_CHASSIS_INDEX_KEY])"},{"line_number":117,"context_line":"    except (KeyError, ValueError):"},{"line_number":118,"context_line":"        msg \u003d (f\"Chassis {chassis.name} has no index, cannot create \""},{"line_number":119,"context_line":"               \"chassis resources\")"},{"line_number":120,"context_line":"        LOG.error(msg)"},{"line_number":121,"context_line":"        # TODO(jlibosva): Use resource types for custom exceptions"},{"line_number":122,"context_line":"        raise exceptions.ReconcileError(msg)"}],"source_content_type":"text/x-python","patch_set":16,"id":"d4fc92e4_0c47c47e","line":119,"range":{"start_line":118,"start_character":4,"end_line":119,"end_character":35},"updated":"2025-12-09 19:58:58.000000000","message":"nit: As far as this method is concern, it just tries to retrieve the chassis index and it does not create any resources. So the error message is little misleading, but I know what you mean...\nMaybe:\n```\nmsg \u003d (f\"Chassis {chassis.name} is missing required index. \"\n       \"Chassis index must be set for proper BGP router indexing.\")\n```","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"4cc76735b31bd5003abc347088eac55c81b47d17","unresolved":false,"context_lines":[{"line_number":115,"context_line":"    try:"},{"line_number":116,"context_line":"        return int(chassis.external_ids[constants.OVN_BGP_CHASSIS_INDEX_KEY])"},{"line_number":117,"context_line":"    except (KeyError, ValueError):"},{"line_number":118,"context_line":"        msg \u003d (f\"Chassis {chassis.name} has no index, cannot create \""},{"line_number":119,"context_line":"               \"chassis resources\")"},{"line_number":120,"context_line":"        LOG.error(msg)"},{"line_number":121,"context_line":"        # TODO(jlibosva): Use resource types for custom exceptions"},{"line_number":122,"context_line":"        raise exceptions.ReconcileError(msg)"}],"source_content_type":"text/x-python","patch_set":16,"id":"4d847e73_93e180cd","line":119,"range":{"start_line":118,"start_character":4,"end_line":119,"end_character":35},"in_reply_to":"d4fc92e4_0c47c47e","updated":"2025-12-09 22:38:58.000000000","message":"Done","commit_id":"cd291d397a8b6ad16114cb43195f874bc923ae27"}],"neutron/tests/functional/services/bgp/__init__.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"f146447bdd89faf06d55ebd68ee6549e9c26f9b6","unresolved":true,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class BaseBgpIDLTestCase(n_base.BaseLoggingTestCase):"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def setUp(self):"},{"line_number":38,"context_line":"        ovn_conf.register_opts()"},{"line_number":39,"context_line":"        bgp_config.register_opts(cfg.CONF)"}],"source_content_type":"text/x-python","patch_set":4,"id":"4a9a996d_d3236d9e","line":36,"updated":"2025-09-10 09:58:14.000000000","message":"Maybe you should add `schemas\u003d[]` here","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"d8128fc35df6f367f0cc33231ee7e7dd57e44a66","unresolved":false,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class BaseBgpIDLTestCase(n_base.BaseLoggingTestCase):"},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"    def setUp(self):"},{"line_number":38,"context_line":"        ovn_conf.register_opts()"},{"line_number":39,"context_line":"        bgp_config.register_opts(cfg.CONF)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3b6e1ebe_24fcc200","line":36,"in_reply_to":"4a9a996d_d3236d9e","updated":"2025-09-10 15:12:37.000000000","message":"Done","commit_id":"48b70a32e66620c1dd9e6d01494b73efbfe77baf"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"400e0b96b7530af7c9e048a26bf090d1eb6b6c07","unresolved":true,"context_lines":[{"line_number":96,"context_line":"            name, [\u0027geneve\u0027], ip).execute(check_error\u003dTrue)"},{"line_number":97,"context_line":""},{"line_number":98,"context_line":"        nb_cfg_timestamp \u003d timeutils.utcnow_ts() * 1000"},{"line_number":99,"context_line":"        self.sb_api.db_create("},{"line_number":100,"context_line":"            \u0027Chassis_Private\u0027, name\u003dname,"},{"line_number":101,"context_line":"            chassis\u003dchassis.uuid, nb_cfg_timestamp\u003dnb_cfg_timestamp,"},{"line_number":102,"context_line":"            external_ids\u003dexternal_ids"}],"source_content_type":"text/x-python","patch_set":19,"id":"1b9ae2ad_0fd46f1a","line":99,"updated":"2025-12-11 21:56:36.000000000","message":"nit Could do this by storing the cmd and returning the cmd.result, or doing\n\n```\nwith self.sb_api.transaction(check_error\u003dTrue) as txn:\n    dbcmd \u003d txn.add(self.api.db_create(...)\n\nreturn dbcmd.result```\n\nto avoid the second txn to list the rows.","commit_id":"c6b2c1d61247a2cdd84d804ba7d29886fce28b25"}],"tox.ini":[{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"b343c2f24bd5fa1919fb12e06a97a58442f8e20a","unresolved":true,"context_lines":[{"line_number":15,"context_line":"  OS_STDOUT_CAPTURE\u003d{env:OS_STDOUT_CAPTURE:true}"},{"line_number":16,"context_line":"  OS_STDERR_CAPTURE\u003d{env:OS_STDERR_CAPTURE:true}"},{"line_number":17,"context_line":"  OS_TEST_TIMEOUT\u003d{env:OS_TEST_TIMEOUT:180}"},{"line_number":18,"context_line":"  PYTHONWARNINGS\u003dignore::DeprecationWarning,ignore::DeprecationWarning:distutils,ignore::DeprecationWarning:site"},{"line_number":19,"context_line":"passenv \u003d TRACE_FAILONLY"},{"line_number":20,"context_line":"  GENERATE_HASHES"},{"line_number":21,"context_line":"  http_proxy"}],"source_content_type":"text/x-properties","patch_set":1,"id":"7876a4db_d44c79e1","line":18,"updated":"2025-09-05 20:14:59.000000000","message":"I didn\u0027t want to push this","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"37b942d6821332d86f9d0bda045dd1515b95f078","unresolved":false,"context_lines":[{"line_number":15,"context_line":"  OS_STDOUT_CAPTURE\u003d{env:OS_STDOUT_CAPTURE:true}"},{"line_number":16,"context_line":"  OS_STDERR_CAPTURE\u003d{env:OS_STDERR_CAPTURE:true}"},{"line_number":17,"context_line":"  OS_TEST_TIMEOUT\u003d{env:OS_TEST_TIMEOUT:180}"},{"line_number":18,"context_line":"  PYTHONWARNINGS\u003dignore::DeprecationWarning,ignore::DeprecationWarning:distutils,ignore::DeprecationWarning:site"},{"line_number":19,"context_line":"passenv \u003d TRACE_FAILONLY"},{"line_number":20,"context_line":"  GENERATE_HASHES"},{"line_number":21,"context_line":"  http_proxy"}],"source_content_type":"text/x-properties","patch_set":1,"id":"e05b801f_05971e74","line":18,"in_reply_to":"7876a4db_d44c79e1","updated":"2025-09-09 16:24:26.000000000","message":"Done","commit_id":"f865dd95589f754df5df269fa4c633d4dc510cb1"}]}
