)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":5948,"name":"Oleg Bondarev","email":"obondarev@mirantis.com","username":"obondarev"},"change_message_id":"a30d52d8d16c77798f9bb00d512bf291d90fb517","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Delete the DVR port record on the node when the router is deleted from the node"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Remove the last VM under one router in one host, the ml2_distributed_port_bindings and ml2_port_binding_levels will remain the record.  So if VMs under one router had spread on many hosts, and router (router ports) still exists, even there is only one VM under it, the binding entries will still be equal to amount of hosts where this router resided before. The result is a large amount of redundant data in the database, even if some nodes are no longer in the cluster, there are still records for that node."},{"line_number":10,"context_line":""},{"line_number":11,"context_line":"Closes-Bug: #1976439"},{"line_number":12,"context_line":"Change-Id: I320ac2306e0f25ff933d8271203e192486062d61"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"78ff649e_594d6c1c","line":9,"updated":"2022-06-29 12:55:41.000000000","message":"Please describe not only bug, the fix as well.","commit_id":"90e1e927918eb04225617c6e1f6e706b62dc1c29"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":5948,"name":"Oleg Bondarev","email":"obondarev@mirantis.com","username":"obondarev"},"change_message_id":"121c1adb445da0dddd881877c7adc47749863fca","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"1a63f3df_15f68d0b","updated":"2022-06-09 06:58:28.000000000","message":"Please consider adding some test coverage for this fix. Also are we sure proper bindings/levels are recreated when a new VM related to the same DVR router is spawned on the same host?","commit_id":"a83b1549739d5c285b66be4592997774d0ae2982"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"c2c0d1f416d6f862fd6eec34ce080ca04b07681d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"0b71d94d_536fe284","updated":"2022-07-07 07:30:55.000000000","message":"Looks good to me, thanks.","commit_id":"4a61dcb2da3009471f0b2f7acf231d5869f877a7"}],"neutron/db/l3_dvrscheduler_db.py":[{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"4307bdb92a050da369a124bf4aff4fd297560f19","unresolved":true,"context_lines":[{"line_number":283,"context_line":"                      [n_const.DEVICE_OWNER_DVR_INTERFACE]}"},{"line_number":284,"context_line":"        int_ports \u003d self._core_plugin.get_ports("},{"line_number":285,"context_line":"            context.elevated(), filters\u003dfilter_rtr)"},{"line_number":286,"context_line":"        for port in int_ports:"},{"line_number":287,"context_line":"            dvr_binding \u003d (ml2_db."},{"line_number":288,"context_line":"                           get_distributed_port_binding_by_host("},{"line_number":289,"context_line":"                               context, port[\u0027id\u0027], port_host))"},{"line_number":290,"context_line":"            if dvr_binding:"},{"line_number":291,"context_line":"                # unbind this port from router"},{"line_number":292,"context_line":"                dvr_binding[\u0027router_id\u0027] \u003d None"},{"line_number":293,"context_line":"                dvr_binding.update(dvr_binding)"},{"line_number":294,"context_line":""},{"line_number":295,"context_line":"    def _get_active_l3_agent_routers_sync_data(self, context, host, agent,"},{"line_number":296,"context_line":"                                               router_ids):"},{"line_number":297,"context_line":"        if extensions.is_extension_supported("}],"source_content_type":"text/x-python","patch_set":2,"id":"65d9e9a8_1e14c613","line":294,"range":{"start_line":286,"start_character":0,"end_line":294,"end_character":0},"updated":"2022-06-15 01:01:23.000000000","message":"This is root cause of the bug. Because these DB actions have no context writer which will actually update nothing duing the following `delete_distributed_port_binding_if_stale`.","commit_id":"e163ae5ee4782ebbd330c569f56e4b8a745c0aa9"}],"neutron/plugins/ml2/db.py":[{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":115,"context_line":"                    filter_by(port_id\u003dport_id, host\u003dhost).one())"},{"line_number":116,"context_line":""},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"def delete_distributed_port_binding_and_binding_level_if_stale("},{"line_number":119,"context_line":"        context, port_id, host):"},{"line_number":120,"context_line":"    with db_api.CONTEXT_WRITER.using(context):"},{"line_number":121,"context_line":"        binding \u003d ("},{"line_number":122,"context_line":"            context.session.query(models.DistributedPortBinding)."}],"source_content_type":"text/x-python","patch_set":3,"id":"a46dede6_031f00b5","line":119,"range":{"start_line":118,"start_character":0,"end_line":119,"end_character":32},"updated":"2022-06-29 03:50:08.000000000","message":"nit: IMO, we can keep the function name.","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":122,"context_line":"            context.session.query(models.DistributedPortBinding)."},{"line_number":123,"context_line":"            filter(models.DistributedPortBinding.port_id.startswith(port_id),"},{"line_number":124,"context_line":"                   models.DistributedPortBinding.host \u003d\u003d host).first())"},{"line_number":125,"context_line":"        if binding.router_id or binding.status !\u003d n_const.PORT_STATUS_DOWN:"},{"line_number":126,"context_line":"            return"},{"line_number":127,"context_line":"        context.session.delete(binding)"},{"line_number":128,"context_line":"        levels \u003d ("},{"line_number":129,"context_line":"            context.session.query(models.PortBindingLevel)."}],"source_content_type":"text/x-python","patch_set":3,"id":"855d8545_1bdcbf3a","line":126,"range":{"start_line":125,"start_character":0,"end_line":126,"end_character":18},"updated":"2022-06-29 03:50:08.000000000","message":"Put this if condition outside the transaction looks better than current place, becase in those cases we can save some DB query. So can this funcion be:\n\n```\ndef delete_distributed_port_binding_if_stale(context, binding, port_id):\n    if not binding.router_id and binding.status \u003d\u003d n_const.PORT_STATUS_DOWN:\n        with db_api.context_manager.writer.using(context):\n            LOG.debug(\"Distributed port: Deleting binding %s\", binding)\n            context.session.delete(binding)\n            for bindlv in (context.session.query(models.PortBindingLevel).\n                      filter_by(port_id\u003dport_id, host\u003dbinding.host)):\n                context.session.delete(bindlv)\n            LOG.debug(\"For port %(port_id)s, host %(host)s, \"\n                      \"cleared binding levels\",\n                      {\u0027port_id\u0027: port_id,\n                       \u0027host\u0027: binding.host})\n```","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":132,"context_line":"        context.session.delete(levels)"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"def unbind_distributed_port_binding_by_host(context, port_id, host):"},{"line_number":136,"context_line":"    with db_api.CONTEXT_WRITER.using(context):"},{"line_number":137,"context_line":"        binding \u003d ("},{"line_number":138,"context_line":"            context.session.query(models.DistributedPortBinding)."}],"source_content_type":"text/x-python","patch_set":3,"id":"ddd18c65_83f2d2d9","line":135,"range":{"start_line":135,"start_character":4,"end_line":135,"end_character":10},"updated":"2022-06-29 03:50:08.000000000","message":"There is ``get_distributed_port_binding_by_host`` in line 265, so can this be ``update_distributed_port_binding_by_host``? And we can add a router_id to the param to it, then user can pass None or a real router_id to this function.","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":137,"context_line":"        binding \u003d ("},{"line_number":138,"context_line":"            context.session.query(models.DistributedPortBinding)."},{"line_number":139,"context_line":"            filter(models.DistributedPortBinding.port_id.startswith(port_id),"},{"line_number":140,"context_line":"                   models.DistributedPortBinding.host \u003d\u003d host).first())"},{"line_number":141,"context_line":"        if binding:"},{"line_number":142,"context_line":"            # unbind this port from router"},{"line_number":143,"context_line":"            binding[\u0027router_id\u0027] \u003d None"}],"source_content_type":"text/x-python","patch_set":3,"id":"8bdacd80_3dc1b598","line":140,"range":{"start_line":140,"start_character":62,"end_line":140,"end_character":70},"updated":"2022-06-29 03:50:08.000000000","message":"Can we use all() here to aviod some corner case?","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":138,"context_line":"            context.session.query(models.DistributedPortBinding)."},{"line_number":139,"context_line":"            filter(models.DistributedPortBinding.port_id.startswith(port_id),"},{"line_number":140,"context_line":"                   models.DistributedPortBinding.host \u003d\u003d host).first())"},{"line_number":141,"context_line":"        if binding:"},{"line_number":142,"context_line":"            # unbind this port from router"},{"line_number":143,"context_line":"            binding[\u0027router_id\u0027] \u003d None"},{"line_number":144,"context_line":"            binding.update(binding)"}],"source_content_type":"text/x-python","patch_set":3,"id":"39a00163_59658273","line":141,"range":{"start_line":141,"start_character":8,"end_line":141,"end_character":19},"updated":"2022-06-29 03:50:08.000000000","message":"for binding in bindings or []:","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":140,"context_line":"                   models.DistributedPortBinding.host \u003d\u003d host).first())"},{"line_number":141,"context_line":"        if binding:"},{"line_number":142,"context_line":"            # unbind this port from router"},{"line_number":143,"context_line":"            binding[\u0027router_id\u0027] \u003d None"},{"line_number":144,"context_line":"            binding.update(binding)"},{"line_number":145,"context_line":"        else:"},{"line_number":146,"context_line":"            LOG.debug(\"No binding for distributed port %(port_id)s with host \""}],"source_content_type":"text/x-python","patch_set":3,"id":"0da805f6_da961dd0","line":143,"range":{"start_line":143,"start_character":12,"end_line":143,"end_character":39},"updated":"2022-06-29 03:50:08.000000000","message":"binding[\u0027router_id\u0027] \u003d router_id or None","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":144,"context_line":"            binding.update(binding)"},{"line_number":145,"context_line":"        else:"},{"line_number":146,"context_line":"            LOG.debug(\"No binding for distributed port %(port_id)s with host \""},{"line_number":147,"context_line":"                      \"%(host)s\", {\u0027port_id\u0027: port_id, \u0027host\u0027: host})"},{"line_number":148,"context_line":""},{"line_number":149,"context_line":""},{"line_number":150,"context_line":"def get_port(context, port_id):"}],"source_content_type":"text/x-python","patch_set":3,"id":"7874d72c_7293b450","line":147,"updated":"2022-06-29 03:50:08.000000000","message":"So this function can be:\n```\ndef update_distributed_port_binding_by_host(context, port_id, host, router_id):\n    with db_api.context_manager.writer.using(context):\n        bindings \u003d (context.session.query(models.DistributedPortBinding).\n            filter(models.DistributedPortBinding.port_id.startswith(port_id),\n                   models.DistributedPortBinding.host \u003d\u003d host).all())\n        for bind in bindings or []:\n            bind[\u0027router_id\u0027] \u003d router_id or None\n            bind.update(bind)\n```","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"59a5330fc20ef9b673cc490249cdf9ffd0d18642","unresolved":true,"context_lines":[{"line_number":262,"context_line":"    return final_status"},{"line_number":263,"context_line":""},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"def get_distributed_port_binding_by_host(context, port_id, host):"},{"line_number":266,"context_line":"    with db_api.CONTEXT_READER.using(context):"},{"line_number":267,"context_line":"        binding \u003d ("},{"line_number":268,"context_line":"            context.session.query(models.DistributedPortBinding)."}],"source_content_type":"text/x-python","patch_set":3,"id":"9c621785_0f462437","line":265,"range":{"start_line":265,"start_character":0,"end_line":265,"end_character":65},"updated":"2022-06-29 03:50:08.000000000","message":"Follow-up to Line 135.","commit_id":"f447a0b73f8fde9bb110c18e6f536852d567ca68"}],"neutron/plugins/ml2/plugin.py":[{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"4307bdb92a050da369a124bf4aff4fd297560f19","unresolved":true,"context_lines":[{"line_number":2369,"context_line":"                                 states\u003d(original_port, port,)))"},{"line_number":2370,"context_line":""},{"line_number":2371,"context_line":"        if port[\u0027device_owner\u0027] \u003d\u003d const.DEVICE_OWNER_DVR_INTERFACE:"},{"line_number":2372,"context_line":"            if binding.status \u003d\u003d const.PORT_STATUS_DOWN:"},{"line_number":2373,"context_line":"                db.clear_binding_levels(context, port_id, host)"},{"line_number":2374,"context_line":"                binding.router_id \u003d None"},{"line_number":2375,"context_line":"            db.delete_distributed_port_binding_if_stale(context, binding)"},{"line_number":2376,"context_line":""},{"line_number":2377,"context_line":"        return port[\u0027id\u0027]"},{"line_number":2378,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"76c3bd04_e176b1c2","line":2375,"range":{"start_line":2372,"start_character":0,"end_line":2375,"end_character":73},"updated":"2022-06-15 01:01:23.000000000","message":"All these actions should be run in one transaction.","commit_id":"e163ae5ee4782ebbd330c569f56e4b8a745c0aa9"}],"neutron/plugins/ml2/rpc.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"6251baca91d8dfa600f7754370a33e015f6e81af","unresolved":true,"context_lines":[{"line_number":372,"context_line":"        if (port[\u0027device_owner\u0027] \u003d\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":373,"context_line":"                not refresh_tunnels):"},{"line_number":374,"context_line":"            return"},{"line_number":375,"context_line":"        port_context \u003d plugin.get_bound_port_context("},{"line_number":376,"context_line":"                rpc_context, port_id, host)"},{"line_number":377,"context_line":"        if not port_context:"},{"line_number":378,"context_line":"            # port deleted"}],"source_content_type":"text/x-python","patch_set":2,"id":"14110206_fabef2bb","line":375,"range":{"start_line":375,"start_character":8,"end_line":375,"end_character":53},"updated":"2022-06-10 11:07:50.000000000","message":"Is this related to this bug?","commit_id":"e163ae5ee4782ebbd330c569f56e4b8a745c0aa9"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"fd4464ea74aea090d79444ecfed80debfdb8e006","unresolved":true,"context_lines":[{"line_number":372,"context_line":"        if (port[\u0027device_owner\u0027] \u003d\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":373,"context_line":"                not refresh_tunnels):"},{"line_number":374,"context_line":"            return"},{"line_number":375,"context_line":"        port_context \u003d plugin.get_bound_port_context("},{"line_number":376,"context_line":"                rpc_context, port_id, host)"},{"line_number":377,"context_line":"        if not port_context:"},{"line_number":378,"context_line":"            # port deleted"}],"source_content_type":"text/x-python","patch_set":2,"id":"8706bf1d_a86ba84c","line":375,"range":{"start_line":375,"start_character":8,"end_line":375,"end_character":53},"in_reply_to":"14110206_fabef2bb","updated":"2022-06-29 08:51:10.000000000","message":"++\nThis is not addressed, this looks like not related to the bug.","commit_id":"e163ae5ee4782ebbd330c569f56e4b8a745c0aa9"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"8b11bcd7f4452a286ad7e79dad908a33a1bcd71e","unresolved":true,"context_lines":[{"line_number":372,"context_line":"        if (port[\u0027device_owner\u0027] \u003d\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":373,"context_line":"                not refresh_tunnels):"},{"line_number":374,"context_line":"            return"},{"line_number":375,"context_line":"        port_context \u003d plugin.get_bound_port_context("},{"line_number":376,"context_line":"                rpc_context, port_id, host)"},{"line_number":377,"context_line":"        if not port_context:"},{"line_number":378,"context_line":"            # port deleted"},{"line_number":379,"context_line":"            return"},{"line_number":380,"context_line":"        port \u003d port_context.current"},{"line_number":381,"context_line":"        if (port[\u0027device_owner\u0027] !\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":382,"context_line":"                status \u003d\u003d n_const.PORT_STATUS_ACTIVE and"}],"source_content_type":"text/x-python","patch_set":8,"id":"630b6ac2_2b50d1ee","line":379,"range":{"start_line":375,"start_character":0,"end_line":379,"end_character":18},"updated":"2022-07-07 07:32:03.000000000","message":"Sorry, why these code moves are still needed?","commit_id":"4a61dcb2da3009471f0b2f7acf231d5869f877a7"},{"author":{"_account_id":9531,"name":"liuyulong","display_name":"LIU Yulong","email":"i@liuyulong.me","username":"LIU-Yulong"},"change_message_id":"abfdd89535e94978d7f2cff1e48ed23cc01fc284","unresolved":true,"context_lines":[{"line_number":372,"context_line":"        if (port[\u0027device_owner\u0027] \u003d\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":373,"context_line":"                not refresh_tunnels):"},{"line_number":374,"context_line":"            return"},{"line_number":375,"context_line":"        port_context \u003d plugin.get_bound_port_context("},{"line_number":376,"context_line":"                rpc_context, port_id, host)"},{"line_number":377,"context_line":"        if not port_context:"},{"line_number":378,"context_line":"            # port deleted"},{"line_number":379,"context_line":"            return"},{"line_number":380,"context_line":"        port \u003d port_context.current"},{"line_number":381,"context_line":"        if (port[\u0027device_owner\u0027] !\u003d n_const.DEVICE_OWNER_DVR_INTERFACE and"},{"line_number":382,"context_line":"                status \u003d\u003d n_const.PORT_STATUS_ACTIVE and"}],"source_content_type":"text/x-python","patch_set":8,"id":"ca0b73bd_abdb88c3","line":379,"range":{"start_line":375,"start_character":0,"end_line":379,"end_character":18},"in_reply_to":"630b6ac2_2b50d1ee","updated":"2022-08-10 00:58:47.000000000","message":"I\u0027ve reverted these lines.","commit_id":"4a61dcb2da3009471f0b2f7acf231d5869f877a7"}]}
