)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"b1aaebe547a636e6b7a8ed52ab740e83fbc9d723","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"d815d2b2_3d30c126","updated":"2026-04-28 22:56:41.000000000","message":"Looks good. Some naming nits that confused me for a sec, but nothing I\u0027d hold things up over.","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"51258f7f5f77278b48fd4405f2eb3e07849ae59f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"1e61b55a_d1b77e7e","updated":"2026-04-30 06:45:08.000000000","message":"recheck openstack-tox-pep8","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"},{"author":{"_account_id":31291,"name":"Eduardo Olivares","email":"eolivare@redhat.com","username":"eolivare"},"change_message_id":"4c72b5497f4d69d5ba4a43954de2fd9b064cfa21","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"96434f90_b6943fb9","updated":"2026-04-30 13:44:01.000000000","message":"recheck neutron-ovs-grenade-multinode","commit_id":"cce2a2d6b3692d285d2a2f526eb842e8b3114666"}],"neutron/services/bgp/commands.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"095c0139134799433145d9f0de677daed7124f49","unresolved":true,"context_lines":[{"line_number":189,"context_line":"        self.set_columns(self.row_result, **self.columns)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"class HaChasssisGroupDelCommand(nb_cmd.HAChassisGroupDelCommand):"},{"line_number":193,"context_line":"    def __init__(self, api, chassis):"},{"line_number":194,"context_line":"        ha_chassis_group_name \u003d helpers.get_hcg_name(chassis.name)"},{"line_number":195,"context_line":"        super().__init__(api, ha_chassis_group_name, if_exists\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":2,"id":"9276168e_4aa5bdcf","line":192,"range":{"start_line":192,"start_character":11,"end_line":192,"end_character":14},"updated":"2026-04-23 15:04:51.000000000","message":"Please, remove 1 `s`","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a3d5d0d50d87d43e163ef65e015cb054e39f9544","unresolved":false,"context_lines":[{"line_number":189,"context_line":"        self.set_columns(self.row_result, **self.columns)"},{"line_number":190,"context_line":""},{"line_number":191,"context_line":""},{"line_number":192,"context_line":"class HaChasssisGroupDelCommand(nb_cmd.HAChassisGroupDelCommand):"},{"line_number":193,"context_line":"    def __init__(self, api, chassis):"},{"line_number":194,"context_line":"        ha_chassis_group_name \u003d helpers.get_hcg_name(chassis.name)"},{"line_number":195,"context_line":"        super().__init__(api, ha_chassis_group_name, if_exists\u003dTrue)"}],"source_content_type":"text/x-python","patch_set":2,"id":"2231b9b4_c0c5a94e","line":192,"range":{"start_line":192,"start_character":11,"end_line":192,"end_character":14},"in_reply_to":"9276168e_4aa5bdcf","updated":"2026-04-23 22:05:07.000000000","message":"Was written by my snake. Sharp eyes.","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"095c0139134799433145d9f0de677daed7124f49","unresolved":true,"context_lines":[{"line_number":533,"context_line":"            chassis_router_name, main_router_name)"},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"        try:"},{"line_number":536,"context_line":"            lrp_main_row \u003d self.api.lookup("},{"line_number":537,"context_line":"                \u0027Logical_Router_Port\u0027, lrp_main)"},{"line_number":538,"context_line":"            lrp_main_row.ha_chassis_group \u003d []"},{"line_number":539,"context_line":"        except idlutils.RowNotFound:"}],"source_content_type":"text/x-python","patch_set":2,"id":"a262c7ef_6f3e6f0d","line":536,"range":{"start_line":536,"start_character":36,"end_line":536,"end_character":42},"updated":"2026-04-23 15:04:51.000000000","message":"same comment as in L555","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"5da7ca7b2f7835e59a0358a5b5d5ff7ba2050fe2","unresolved":false,"context_lines":[{"line_number":533,"context_line":"            chassis_router_name, main_router_name)"},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"        try:"},{"line_number":536,"context_line":"            lrp_main_row \u003d self.api.lookup("},{"line_number":537,"context_line":"                \u0027Logical_Router_Port\u0027, lrp_main)"},{"line_number":538,"context_line":"            lrp_main_row.ha_chassis_group \u003d []"},{"line_number":539,"context_line":"        except idlutils.RowNotFound:"}],"source_content_type":"text/x-python","patch_set":2,"id":"6ae897d5_18643d00","line":536,"range":{"start_line":536,"start_character":36,"end_line":536,"end_character":42},"in_reply_to":"13f4daf1_039219b2","updated":"2026-04-28 12:59:18.000000000","message":"Done","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a3d5d0d50d87d43e163ef65e015cb054e39f9544","unresolved":true,"context_lines":[{"line_number":533,"context_line":"            chassis_router_name, main_router_name)"},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"        try:"},{"line_number":536,"context_line":"            lrp_main_row \u003d self.api.lookup("},{"line_number":537,"context_line":"                \u0027Logical_Router_Port\u0027, lrp_main)"},{"line_number":538,"context_line":"            lrp_main_row.ha_chassis_group \u003d []"},{"line_number":539,"context_line":"        except idlutils.RowNotFound:"}],"source_content_type":"text/x-python","patch_set":2,"id":"13f4daf1_039219b2","line":536,"range":{"start_line":536,"start_character":36,"end_line":536,"end_character":42},"in_reply_to":"a262c7ef_6f3e6f0d","updated":"2026-04-23 22:05:07.000000000","message":"I\u0027d argue, EAFP is preferable over LBYL with Python https://docs.python.org/3/glossary.html#term-EAFP\n\nIt is more likely the chassis group exists when we do the cleanup so we rarely get to the except block.","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"095c0139134799433145d9f0de677daed7124f49","unresolved":true,"context_lines":[{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def _cleanup_ha_chassis_group(self, txn):"},{"line_number":550,"context_line":"        hcg_name \u003d helpers.get_hcg_name(self.chassis.name)"},{"line_number":551,"context_line":"        try:"},{"line_number":552,"context_line":"            hcg \u003d self.api.lookup("},{"line_number":553,"context_line":"                \u0027HA_Chassis_Group\u0027, hcg_name)"},{"line_number":554,"context_line":"        except idlutils.RowNotFound:"},{"line_number":555,"context_line":"            return"},{"line_number":556,"context_line":"        nb_cmd.HAChassisGroupDelChassisCommand("},{"line_number":557,"context_line":"            self.api, hcg.uuid, self.chassis.name,"},{"line_number":558,"context_line":"            if_exists\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":2,"id":"0d402e42_7d386eee","line":555,"range":{"start_line":551,"start_character":8,"end_line":555,"end_character":18},"updated":"2026-04-23 15:04:51.000000000","message":"nit: `lookup` has kwarg `default`, that could be set to `None`; IMO better to check if hcg is None rather than catching the exception","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a3d5d0d50d87d43e163ef65e015cb054e39f9544","unresolved":true,"context_lines":[{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def _cleanup_ha_chassis_group(self, txn):"},{"line_number":550,"context_line":"        hcg_name \u003d helpers.get_hcg_name(self.chassis.name)"},{"line_number":551,"context_line":"        try:"},{"line_number":552,"context_line":"            hcg \u003d self.api.lookup("},{"line_number":553,"context_line":"                \u0027HA_Chassis_Group\u0027, hcg_name)"},{"line_number":554,"context_line":"        except idlutils.RowNotFound:"},{"line_number":555,"context_line":"            return"},{"line_number":556,"context_line":"        nb_cmd.HAChassisGroupDelChassisCommand("},{"line_number":557,"context_line":"            self.api, hcg.uuid, self.chassis.name,"},{"line_number":558,"context_line":"            if_exists\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":2,"id":"f9a93546_195da1c5","line":555,"range":{"start_line":551,"start_character":8,"end_line":555,"end_character":18},"in_reply_to":"0d402e42_7d386eee","updated":"2026-04-23 22:05:07.000000000","message":"I\u0027d argue, EAFP is preferable over LBYL in python https://docs.python.org/3/glossary.html#term-EAFP\n\nIt is more likely the chassis group exists when we do the cleanup so we rarely get to the except block.","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"5da7ca7b2f7835e59a0358a5b5d5ff7ba2050fe2","unresolved":false,"context_lines":[{"line_number":548,"context_line":""},{"line_number":549,"context_line":"    def _cleanup_ha_chassis_group(self, txn):"},{"line_number":550,"context_line":"        hcg_name \u003d helpers.get_hcg_name(self.chassis.name)"},{"line_number":551,"context_line":"        try:"},{"line_number":552,"context_line":"            hcg \u003d self.api.lookup("},{"line_number":553,"context_line":"                \u0027HA_Chassis_Group\u0027, hcg_name)"},{"line_number":554,"context_line":"        except idlutils.RowNotFound:"},{"line_number":555,"context_line":"            return"},{"line_number":556,"context_line":"        nb_cmd.HAChassisGroupDelChassisCommand("},{"line_number":557,"context_line":"            self.api, hcg.uuid, self.chassis.name,"},{"line_number":558,"context_line":"            if_exists\u003dTrue,"}],"source_content_type":"text/x-python","patch_set":2,"id":"1265764e_55602a7e","line":555,"range":{"start_line":551,"start_character":8,"end_line":555,"end_character":18},"in_reply_to":"f9a93546_195da1c5","updated":"2026-04-28 12:59:18.000000000","message":"This is almost the same due to the implementation of `lookup`. In any case, this is a cosmetic comment, nothing else.","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"b1aaebe547a636e6b7a8ed52ab740e83fbc9d723","unresolved":false,"context_lines":[{"line_number":444,"context_line":"class DeleteChassisPeerCommand(ovs_cmd.BaseCommand):"},{"line_number":445,"context_line":"    def __init__(self, api, chassis, network_name):"},{"line_number":446,"context_line":"        super().__init__(api)"},{"line_number":447,"context_line":"        self.chassis \u003d chassis"},{"line_number":448,"context_line":"        self.network_name \u003d network_name"},{"line_number":449,"context_line":""},{"line_number":450,"context_line":"    def run_idl(self, txn):"}],"source_content_type":"text/x-python","patch_set":3,"id":"4a97a4bc_efc5dad2","line":447,"updated":"2026-04-28 22:56:41.000000000","message":"It is not generally safe to store Rows/RowViews on objects/outside of a transaction. The Row could be deleted or modified by a subsequent read from ovsdb-server in another thread.\n\nThough in this case, it looks like the Chassis row ultimately will come from a DELETE event, so will already be gone on the ovsdb-server and removed from our in-memory copy. So I can\u0027t think of a reason why this should be a problem, even though the row is passed from outside of a Command.run_idl().","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"b1aaebe547a636e6b7a8ed52ab740e83fbc9d723","unresolved":true,"context_lines":[{"line_number":477,"context_line":"        ).run_idl(txn)"},{"line_number":478,"context_line":""},{"line_number":479,"context_line":""},{"line_number":480,"context_line":"class DeleteChassisCommand(ovs_cmd.BaseCommand):"},{"line_number":481,"context_line":"    \"\"\"Deletes all resources related to a chassis"},{"line_number":482,"context_line":""},{"line_number":483,"context_line":"    The command deletes all peer connections, main router policies, LRPs, and"}],"source_content_type":"text/x-python","patch_set":3,"id":"2d2a4032_2b863a08","line":480,"range":{"start_line":480,"start_character":6,"end_line":480,"end_character":26},"updated":"2026-04-28 22:56:41.000000000","message":"nit: DeleteChassisCommand sounds like this command deletes a chassis, which it doesn\u0027t. It\u0027s documented what it actually does, but it took me a sec when I read the reconciler code and saw a function named \"delete_chassis()\" with a comment that said it was \"Deleting chassis %s\" and calling DeleteChassisCommand() and the chassis was already actually deleted. 😉 OnChassisDeleteCommand() or ChassisDeleteCleanupCommand() or something would have made it more immediately clear.","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"}],"neutron/services/bgp/events.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"095c0139134799433145d9f0de677daed7124f49","unresolved":true,"context_lines":[{"line_number":132,"context_line":"                row.options[\u0027router\u0027] !\u003d old.options.get(\u0027router\u0027))"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"class BGPChassisEvent(BGPReconcilerResourceEvent):"},{"line_number":136,"context_line":"    EVENTS \u003d (BGPReconcilerResourceEvent.ROW_CREATE,"},{"line_number":137,"context_line":"              BGPReconcilerResourceEvent.ROW_DELETE)"},{"line_number":138,"context_line":"    RESOURCE \u003d constants.BGPReconcilerResource.CHASSIS"}],"source_content_type":"text/x-python","patch_set":2,"id":"80a9047b_c6c7129c","line":135,"range":{"start_line":135,"start_character":6,"end_line":135,"end_character":21},"updated":"2026-04-23 15:04:51.000000000","message":"That class has no `match_fn`, it will be executed for all chassis. Is that correct?","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"5da7ca7b2f7835e59a0358a5b5d5ff7ba2050fe2","unresolved":false,"context_lines":[{"line_number":132,"context_line":"                row.options[\u0027router\u0027] !\u003d old.options.get(\u0027router\u0027))"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"class BGPChassisEvent(BGPReconcilerResourceEvent):"},{"line_number":136,"context_line":"    EVENTS \u003d (BGPReconcilerResourceEvent.ROW_CREATE,"},{"line_number":137,"context_line":"              BGPReconcilerResourceEvent.ROW_DELETE)"},{"line_number":138,"context_line":"    RESOURCE \u003d constants.BGPReconcilerResource.CHASSIS"}],"source_content_type":"text/x-python","patch_set":2,"id":"ca7307e5_b49802b9","line":135,"range":{"start_line":135,"start_character":6,"end_line":135,"end_character":21},"in_reply_to":"6d491aa7_a5a3bb54","updated":"2026-04-28 12:59:18.000000000","message":"Done","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"a3d5d0d50d87d43e163ef65e015cb054e39f9544","unresolved":true,"context_lines":[{"line_number":132,"context_line":"                row.options[\u0027router\u0027] !\u003d old.options.get(\u0027router\u0027))"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"class BGPChassisEvent(BGPReconcilerResourceEvent):"},{"line_number":136,"context_line":"    EVENTS \u003d (BGPReconcilerResourceEvent.ROW_CREATE,"},{"line_number":137,"context_line":"              BGPReconcilerResourceEvent.ROW_DELETE)"},{"line_number":138,"context_line":"    RESOURCE \u003d constants.BGPReconcilerResource.CHASSIS"}],"source_content_type":"text/x-python","patch_set":2,"id":"6d491aa7_a5a3bb54","line":135,"range":{"start_line":135,"start_character":6,"end_line":135,"end_character":21},"in_reply_to":"80a9047b_c6c7129c","updated":"2026-04-23 22:05:07.000000000","message":"Yes, we want every chassis to set the resources up or tear them down.","commit_id":"b00dd4de2600b03bb8d9f561d22c455a0ecdeb71"}],"neutron/services/bgp/reconciler.py":[{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"b1aaebe547a636e6b7a8ed52ab740e83fbc9d723","unresolved":true,"context_lines":[{"line_number":127,"context_line":"        ).execute(check_error\u003dTrue)"},{"line_number":128,"context_line":""},{"line_number":129,"context_line":"    def delete_chassis(self, chassis):"},{"line_number":130,"context_line":"        LOG.info(\"Deleting chassis %s\", chassis.name)"},{"line_number":131,"context_line":"        commands.DeleteChassisCommand("},{"line_number":132,"context_line":"            self.nb_api,"},{"line_number":133,"context_line":"            chassis,"}],"source_content_type":"text/x-python","patch_set":3,"id":"634f0023_232727c8","line":130,"updated":"2026-04-28 22:56:41.000000000","message":"nit: as previously mentioned, I don\u0027t think we\u0027re actually deleting the chassis--it was already deleted and we are just cleaning up related objects.","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"}],"neutron/tests/functional/services/bgp/test_commands.py":[{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"b1aaebe547a636e6b7a8ed52ab740e83fbc9d723","unresolved":true,"context_lines":[{"line_number":1234,"context_line":"        except idlutils.RowNotFound:"},{"line_number":1235,"context_line":"            pass"},{"line_number":1236,"context_line":""},{"line_number":1237,"context_line":"    def _assert_chassis_gone(self, chassis, peers):"},{"line_number":1238,"context_line":"        chassis_router_name \u003d helpers.get_chassis_router_name("},{"line_number":1239,"context_line":"            chassis.name)"},{"line_number":1240,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"c8d7a121_e6c42838","line":1237,"range":{"start_line":1237,"start_character":8,"end_line":1237,"end_character":28},"updated":"2026-04-28 22:56:41.000000000","message":"nit: same \"we\u0027re looking at things related to chassis and not deleting chassis\" naming nit here and below.","commit_id":"eac04368d18ecb4e338cb2cdc104b93081380b28"}]}
