)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"f46599c10f41a58b015296015d99fd245b2be4b7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"83c66516_32a5efbe","updated":"2026-01-21 16:09:44.000000000","message":"LGTM. We can investigate the agent_api usage in tests at a later date.","commit_id":"ac9618d4e09d3a8605ea75c0388883c0ee4deeec"}],"neutron/agent/ovn/extensions/bgp/__init__.py":[{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"eeaa886f6299e4e675ef5db86bee15e8b3776ea6","unresolved":true,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def create_bgp_bridge(self, bridge_name):"},{"line_number":66,"context_line":"        bgp_bridge \u003d bridge.BGPChassisBridge(self, bridge_name)"},{"line_number":67,"context_line":"        self.bgp_bridges[bridge_name] \u003d bgp_bridge"},{"line_number":68,"context_line":"        return bgp_bridge"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def configure_bgp_bridge_mappings("}],"source_content_type":"text/x-python","patch_set":4,"id":"5105b5b2_189f63fd","line":67,"updated":"2025-12-11 11:58:55.000000000","message":"I am not sure I understand this code and the comment in L28-L35. That comment says that values of the self.bgp_bridges islist of the IPNetwork objects, but here you put instance of the BGPChassisBridge there. What am I missing there?","commit_id":"ccb9ea63c1993ecac996abc8de7119281e66bf8d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"cce4322e0ba964073728eadab01138f653e4f9fa","unresolved":true,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def create_bgp_bridge(self, bridge_name):"},{"line_number":66,"context_line":"        bgp_bridge \u003d bridge.BGPChassisBridge(self, bridge_name)"},{"line_number":67,"context_line":"        self.bgp_bridges[bridge_name] \u003d bgp_bridge"},{"line_number":68,"context_line":"        return bgp_bridge"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def configure_bgp_bridge_mappings("}],"source_content_type":"text/x-python","patch_set":4,"id":"537e00ca_7945bf6e","line":67,"in_reply_to":"5105b5b2_189f63fd","updated":"2025-12-17 16:25:35.000000000","message":"The comment is old from the first implementation, thanks! good catch","commit_id":"ccb9ea63c1993ecac996abc8de7119281e66bf8d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"469af6fe40630ac7b11b6d2a4ef987b24a46299e","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def create_bgp_bridge(self, bridge_name):"},{"line_number":66,"context_line":"        bgp_bridge \u003d bridge.BGPChassisBridge(self, bridge_name)"},{"line_number":67,"context_line":"        self.bgp_bridges[bridge_name] \u003d bgp_bridge"},{"line_number":68,"context_line":"        return bgp_bridge"},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"    def configure_bgp_bridge_mappings("}],"source_content_type":"text/x-python","patch_set":4,"id":"e17f4a83_97b32510","line":67,"in_reply_to":"537e00ca_7945bf6e","updated":"2026-01-02 20:42:11.000000000","message":"Done","commit_id":"ccb9ea63c1993ecac996abc8de7119281e66bf8d"}],"neutron/agent/ovn/extensions/bgp/bridge.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"8119d7760b32ec99a740004c093ae89944885cc4","unresolved":true,"context_lines":[{"line_number":43,"context_line":"    physical interface connected to a BGP peer, typically a leaf switch."},{"line_number":44,"context_line":"    \"\"\""},{"line_number":45,"context_line":"    def __str__(self):"},{"line_number":46,"context_line":"        return f\"BGPChassisBridge(name\u003d{self.name}, ips\u003d{self.ips})\""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    __repr__ \u003d __str__"}],"source_content_type":"text/x-python","patch_set":2,"id":"23809e22_1d995a31","line":46,"range":{"start_line":46,"start_character":57,"end_line":46,"end_character":65},"updated":"2025-11-05 15:10:22.000000000","message":"Where is this variable coming? I don\u0027t see it in `BGPChassisBridge` nor `Bridge`","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"acd1be8ae469b4a0ad9971cd70c9e3551142a2e4","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    physical interface connected to a BGP peer, typically a leaf switch."},{"line_number":44,"context_line":"    \"\"\""},{"line_number":45,"context_line":"    def __str__(self):"},{"line_number":46,"context_line":"        return f\"BGPChassisBridge(name\u003d{self.name}, ips\u003d{self.ips})\""},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    __repr__ \u003d __str__"}],"source_content_type":"text/x-python","patch_set":2,"id":"78780810_275bebff","line":46,"range":{"start_line":46,"start_character":57,"end_line":46,"end_character":65},"in_reply_to":"23809e22_1d995a31","updated":"2025-11-06 20:32:48.000000000","message":"Right, it\u0027s when I tried to split big patches into smaller pieces and forgot it here.","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"}],"neutron/agent/ovn/extensions/bgp/events.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"8119d7760b32ec99a740004c093ae89944885cc4","unresolved":true,"context_lines":[{"line_number":87,"context_line":"    @staticmethod"},{"line_number":88,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":89,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":90,"context_line":"        if len(ovs_entries) !\u003d 1:"},{"line_number":91,"context_line":"            LOG.error("},{"line_number":92,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"},{"line_number":93,"context_line":"            return []"}],"source_content_type":"text/x-python","patch_set":2,"id":"65179cbd_e210cf29","line":90,"range":{"start_line":90,"start_character":8,"end_line":90,"end_character":33},"updated":"2025-11-05 15:10:22.000000000","message":"nit: is that possible? Just asking","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"acd1be8ae469b4a0ad9971cd70c9e3551142a2e4","unresolved":false,"context_lines":[{"line_number":87,"context_line":"    @staticmethod"},{"line_number":88,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":89,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":90,"context_line":"        if len(ovs_entries) !\u003d 1:"},{"line_number":91,"context_line":"            LOG.error("},{"line_number":92,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"},{"line_number":93,"context_line":"            return []"}],"source_content_type":"text/x-python","patch_set":2,"id":"2f4a7e99_63540bc5","line":90,"range":{"start_line":90,"start_character":8,"end_line":90,"end_character":33},"in_reply_to":"65179cbd_e210cf29","updated":"2025-11-06 20:32:48.000000000","message":"It shouldn\u0027t be possible but wanted to be defensive. Maybe I should not return on L93 and use the first item and move on.","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"},{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"8119d7760b32ec99a740004c093ae89944885cc4","unresolved":true,"context_lines":[{"line_number":113,"context_line":"    @staticmethod"},{"line_number":114,"context_line":"    def _nic_iface_added(row, old):"},{"line_number":115,"context_line":"        added_ports \u003d set(row.ports) - set(old.ports)"},{"line_number":116,"context_line":"        return any(port.interfaces[0].type \u003d\u003d \u0027\u0027 for port in added_ports)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    def match_fn(self, event, row, old):"},{"line_number":119,"context_line":"        if not super().match_fn(event, row, old):"}],"source_content_type":"text/x-python","patch_set":2,"id":"75b3c900_582c21c5","line":116,"range":{"start_line":116,"start_character":46,"end_line":116,"end_character":48},"updated":"2025-11-05 15:10:22.000000000","message":"This could be \u0027\u0027 and `system` (https://manpages.ubuntu.com/manpages/bionic//man5/ovs-vswitchd.conf.db.5.html#interface%20table).\n\nI would also add a note here about `type\u003ddpdk`","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"0817461e4e808c981952e1044caf17b10dd557e7","unresolved":false,"context_lines":[{"line_number":113,"context_line":"    @staticmethod"},{"line_number":114,"context_line":"    def _nic_iface_added(row, old):"},{"line_number":115,"context_line":"        added_ports \u003d set(row.ports) - set(old.ports)"},{"line_number":116,"context_line":"        return any(port.interfaces[0].type \u003d\u003d \u0027\u0027 for port in added_ports)"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    def match_fn(self, event, row, old):"},{"line_number":119,"context_line":"        if not super().match_fn(event, row, old):"}],"source_content_type":"text/x-python","patch_set":2,"id":"126104d9_1dfe6f82","line":116,"range":{"start_line":116,"start_character":46,"end_line":116,"end_character":48},"in_reply_to":"75b3c900_582c21c5","updated":"2025-12-03 15:06:37.000000000","message":"Done","commit_id":"45f0fc40bda2a7b4c743f1f99cdf779acc9a109a"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"dfb4dff8f30b0e0acf640d2dcc3ac9e686725773","unresolved":true,"context_lines":[{"line_number":75,"context_line":"            bgp_peer_bridges, ovn_bridge_mappings)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"class NewBgpBridgeEvent(BGPAgentEvent):"},{"line_number":79,"context_line":"    EVENTS \u003d (BGPAgentEvent.ROW_CREATE, BGPAgentEvent.ROW_UPDATE,)"},{"line_number":80,"context_line":"    TABLE \u003d \u0027Bridge\u0027"},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"a89dbcfb_ba877f26","line":78,"updated":"2026-01-20 19:46:00.000000000","message":"Do we ever need to worry about events where a bgp bridge is removed?","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bb39b70176fee095678b1f39f15c6f8fde919ae0","unresolved":true,"context_lines":[{"line_number":75,"context_line":"            bgp_peer_bridges, ovn_bridge_mappings)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"class NewBgpBridgeEvent(BGPAgentEvent):"},{"line_number":79,"context_line":"    EVENTS \u003d (BGPAgentEvent.ROW_CREATE, BGPAgentEvent.ROW_UPDATE,)"},{"line_number":80,"context_line":"    TABLE \u003d \u0027Bridge\u0027"},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"a9f19fce_73516961","line":78,"in_reply_to":"a89dbcfb_ba877f26","updated":"2026-01-20 20:45:12.000000000","message":"Yes, we\u0027ll need to implement that and an event on the server side that tears down the logical switch with the localnet","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"f46599c10f41a58b015296015d99fd245b2be4b7","unresolved":false,"context_lines":[{"line_number":75,"context_line":"            bgp_peer_bridges, ovn_bridge_mappings)"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"class NewBgpBridgeEvent(BGPAgentEvent):"},{"line_number":79,"context_line":"    EVENTS \u003d (BGPAgentEvent.ROW_CREATE, BGPAgentEvent.ROW_UPDATE,)"},{"line_number":80,"context_line":"    TABLE \u003d \u0027Bridge\u0027"},{"line_number":81,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"b53de2ca_14f5adf3","line":78,"in_reply_to":"a9f19fce_73516961","updated":"2026-01-21 16:09:44.000000000","message":"Got it","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"dfb4dff8f30b0e0acf640d2dcc3ac9e686725773","unresolved":true,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    @staticmethod"},{"line_number":83,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":84,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":85,"context_line":"        if len(ovs_entries) \u003e 1:"},{"line_number":86,"context_line":"            LOG.error("},{"line_number":87,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"}],"source_content_type":"text/x-python","patch_set":7,"id":"6add9629_1b967f85","line":84,"updated":"2026-01-20 19:46:00.000000000","message":"Outside of a Command, it\u0027s generally preferable to access data through the api so data is wrapped in a read-only txn (though we often fail to do so). I think this method could just be:\n```\ndef _get_bgp_bridges(self):\n    ext_ids \u003d self.agent_api.ovs_idl.db_get(\n        \"Open_vSwitch\", \".\", \"external_ids\").execute(check_error\u003dTrue)\n    try:\n        return ext_ids[constants.AGENT_BGP_PEER_BRIDGES].split(\",\")\n    except KeyError:\n        return []\n```\nif the other staticmethods that are only called internally drop their static-ness (otherwise you could keep passing the internal row._idl)","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bb39b70176fee095678b1f39f15c6f8fde919ae0","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    @staticmethod"},{"line_number":83,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":84,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":85,"context_line":"        if len(ovs_entries) \u003e 1:"},{"line_number":86,"context_line":"            LOG.error("},{"line_number":87,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"}],"source_content_type":"text/x-python","patch_set":7,"id":"a8c706c4_a5c9ebf9","line":84,"in_reply_to":"6add9629_1b967f85","updated":"2026-01-20 20:45:12.000000000","message":"Done, however I did not remove the staticmethods because we may not have access to the agent_api yet when we\u0027re processing events after starting the agent, so we use `row._idl` instead","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"6417734885aa77a6d6d1f14a071415bdd9dfdbc8","unresolved":false,"context_lines":[{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    @staticmethod"},{"line_number":83,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":84,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":85,"context_line":"        if len(ovs_entries) \u003e 1:"},{"line_number":86,"context_line":"            LOG.error("},{"line_number":87,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"}],"source_content_type":"text/x-python","patch_set":7,"id":"f9a0fa95_5c15f337","line":84,"in_reply_to":"a8c706c4_a5c9ebf9","updated":"2026-01-20 21:53:24.000000000","message":"I\u0027ll put a comment there","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":5756,"name":"Terry Wilson","email":"twilson@redhat.com","username":"otherwiseguy"},"change_message_id":"dfb4dff8f30b0e0acf640d2dcc3ac9e686725773","unresolved":true,"context_lines":[{"line_number":82,"context_line":"    @staticmethod"},{"line_number":83,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":84,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":85,"context_line":"        if len(ovs_entries) \u003e 1:"},{"line_number":86,"context_line":"            LOG.error("},{"line_number":87,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"},{"line_number":88,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":7,"id":"2aee1c49_c9db0bcc","line":85,"updated":"2026-01-20 19:46:00.000000000","message":"Just FYI, this checks for something that should be impossible. Open_vSwitch table is defined to have only 1 row via maxRows\u003d1 in the schema. If the above changes are made this wouldn\u0027t be here anyway.","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"},{"author":{"_account_id":8655,"name":"Jakub Libosvar","email":"libosvar@redhat.com","username":"jlibosva"},"change_message_id":"bb39b70176fee095678b1f39f15c6f8fde919ae0","unresolved":false,"context_lines":[{"line_number":82,"context_line":"    @staticmethod"},{"line_number":83,"context_line":"    def _get_bgp_bridges(idl):"},{"line_number":84,"context_line":"        ovs_entries \u003d list(idl.tables[\u0027Open_vSwitch\u0027].rows.values())"},{"line_number":85,"context_line":"        if len(ovs_entries) \u003e 1:"},{"line_number":86,"context_line":"            LOG.error("},{"line_number":87,"context_line":"                \"Expected 1 Open_vSwitch entry, got %s\", len(ovs_entries))"},{"line_number":88,"context_line":"        try:"}],"source_content_type":"text/x-python","patch_set":7,"id":"61d4fd80_1eebf545","line":85,"in_reply_to":"2aee1c49_c9db0bcc","updated":"2026-01-20 20:45:12.000000000","message":"Done","commit_id":"a014c0de63924331b3feb70223c488275d5b7d2d"}]}
