)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"dd07f8b6303f9c498fb74a0d31fa0ef3f92c0753","unresolved":false,"context_lines":[{"line_number":14,"context_line":"this patch introduces a new assumption on bind_port() implementations."},{"line_number":15,"context_line":"That is an implementation of bind_port() in any mech driver supporting"},{"line_number":16,"context_line":"Guaranteed Minimum Bandwidth bind_port() must not have a non-idempotent"},{"line_number":17,"context_line":"side effect. Because the last biinding level will be redone for a 2nd"},{"line_number":18,"context_line":"time with a narrowed down list of mechanism drivers. And if the 2nd call"},{"line_number":19,"context_line":"does not give the same result as the first all kind of weird things can"},{"line_number":20,"context_line":"happen."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":37,"id":"9fdfeff1_cf136b64","line":17,"range":{"start_line":17,"start_character":30,"end_line":17,"end_character":38},"updated":"2019-02-28 08:51:11.000000000","message":"nitty nit: doble \"i\"","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c36709d54b580cd01ee03ef83bc6b31e74e4ddd8","unresolved":false,"context_lines":[{"line_number":14,"context_line":"this patch introduces a new assumption on bind_port() implementations."},{"line_number":15,"context_line":"That is an implementation of bind_port() in any mech driver supporting"},{"line_number":16,"context_line":"Guaranteed Minimum Bandwidth bind_port() must not have a non-idempotent"},{"line_number":17,"context_line":"side effect. Because the last biinding level will be redone for a 2nd"},{"line_number":18,"context_line":"time with a narrowed down list of mechanism drivers. And if the 2nd call"},{"line_number":19,"context_line":"does not give the same result as the first all kind of weird things can"},{"line_number":20,"context_line":"happen."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":37,"id":"9fdfeff1_86db05eb","line":17,"range":{"start_line":17,"start_character":30,"end_line":17,"end_character":38},"in_reply_to":"9fdfeff1_cf136b64","updated":"2019-02-28 15:05:12.000000000","message":"Done","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"}],"neutron/common/exceptions.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":338,"context_line":""},{"line_number":339,"context_line":"class UnknownResourceProvider(e.BadRequest):"},{"line_number":340,"context_line":"    \"\"\"Resource provider not known by neutron backends.\"\"\""},{"line_number":341,"context_line":"    message \u003d _(\"No such resource provider: %(rsc_provider)s\")"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":""},{"line_number":344,"context_line":"class AmbiguousResponsibilityForResourceProvider(e.NeutronException):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_ab9db909","line":341,"range":{"start_line":341,"start_character":17,"end_line":341,"end_character":43},"updated":"2018-06-26 18:35:31.000000000","message":"I guess this ends up in the Nova log after a bind failure. To avoid misunderstanding I change this to something like \"Resource provider is unknown for Neutron\" as the RP still very likely to exists in Placement as allocation was made successfully there.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":338,"context_line":""},{"line_number":339,"context_line":"class UnknownResourceProvider(e.BadRequest):"},{"line_number":340,"context_line":"    \"\"\"Resource provider not known by neutron backends.\"\"\""},{"line_number":341,"context_line":"    message \u003d _(\"No such resource provider: %(rsc_provider)s\")"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":""},{"line_number":344,"context_line":"class AmbiguousResponsibilityForResourceProvider(e.NeutronException):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_4ba3b2ff","line":341,"range":{"start_line":341,"start_character":17,"end_line":341,"end_character":43},"in_reply_to":"5f7c97a3_ab9db909","updated":"2018-06-27 10:16:02.000000000","message":"Done","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d982bd5dbbda09f5d03cfc7f858225ec206fde9e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"9fdfeff1_e39951d0","updated":"2019-02-06 13:31:01.000000000","message":"Err, I must have madean error during a rebase merge conflict resolution. This file should not be re-added in this change. I guess I must move the two exception classes to neutron-lib.","commit_id":"28eaf1f8de8280ada64feb13e9e5a31cbceb8f0b"}],"neutron/plugins/ml2/driver_context.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":304,"context_line":"        This method is for MechanismManager and is not part of the driver API."},{"line_number":305,"context_line":"        \u0027\u0027\u0027"},{"line_number":306,"context_line":"        self._new_bound_segment \u003d None"},{"line_number":307,"context_line":"        self._binding.vif_type \u003d \u0027unbound\u0027"},{"line_number":308,"context_line":"        self._binding.vif_details \u003d \u0027\u0027"},{"line_number":309,"context_line":"        self._new_port_status \u003d None"},{"line_number":310,"context_line":""},{"line_number":311,"context_line":"    def continue_binding(self, segment_id, next_segments_to_bind):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_eb33b111","line":308,"range":{"start_line":307,"start_character":0,"end_line":308,"end_character":38},"updated":"2018-06-26 18:35:31.000000000","message":"Are these really the initial values we are resetting to? I honestly lost my way to figure it out at InstanceSnapshot","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":304,"context_line":"        This method is for MechanismManager and is not part of the driver API."},{"line_number":305,"context_line":"        \u0027\u0027\u0027"},{"line_number":306,"context_line":"        self._new_bound_segment \u003d None"},{"line_number":307,"context_line":"        self._binding.vif_type \u003d \u0027unbound\u0027"},{"line_number":308,"context_line":"        self._binding.vif_details \u003d \u0027\u0027"},{"line_number":309,"context_line":"        self._new_port_status \u003d None"},{"line_number":310,"context_line":""},{"line_number":311,"context_line":"    def continue_binding(self, segment_id, next_segments_to_bind):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_0ba93adb","line":308,"range":{"start_line":307,"start_character":0,"end_line":308,"end_character":38},"in_reply_to":"5f7c97a3_eb33b111","updated":"2018-06-27 10:16:02.000000000","message":"At least that\u0027s what my debug logging said.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"dd07f8b6303f9c498fb74a0d31fa0ef3f92c0753","unresolved":false,"context_lines":[{"line_number":310,"context_line":"        This method is for MechanismManager and is not part of the driver API."},{"line_number":311,"context_line":"        \u0027\u0027\u0027"},{"line_number":312,"context_line":"        self._new_bound_segment \u003d None"},{"line_number":313,"context_line":"        self._binding.vif_type \u003d \u0027unbound\u0027"},{"line_number":314,"context_line":"        self._binding.vif_details \u003d \u0027\u0027"},{"line_number":315,"context_line":"        self._new_port_status \u003d None"},{"line_number":316,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_b2052c12","line":313,"range":{"start_line":313,"start_character":34,"end_line":313,"end_character":41},"updated":"2019-02-28 08:51:11.000000000","message":"there is constant in https://github.com/openstack/neutron-lib/blob/98764984c9ab722312b89236da2456bc40429987/neutron_lib/api/definitions/portbindings.py#L85","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c36709d54b580cd01ee03ef83bc6b31e74e4ddd8","unresolved":false,"context_lines":[{"line_number":310,"context_line":"        This method is for MechanismManager and is not part of the driver API."},{"line_number":311,"context_line":"        \u0027\u0027\u0027"},{"line_number":312,"context_line":"        self._new_bound_segment \u003d None"},{"line_number":313,"context_line":"        self._binding.vif_type \u003d \u0027unbound\u0027"},{"line_number":314,"context_line":"        self._binding.vif_details \u003d \u0027\u0027"},{"line_number":315,"context_line":"        self._new_port_status \u003d None"},{"line_number":316,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_e69e9104","line":313,"range":{"start_line":313,"start_character":34,"end_line":313,"end_character":41},"in_reply_to":"9fdfeff1_b2052c12","updated":"2019-02-28 15:05:12.000000000","message":"Done","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"}],"neutron/plugins/ml2/drivers/mech_agent.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":147,"context_line":"        host_agents \u003d context._plugin.get_agents("},{"line_number":148,"context_line":"            context._plugin_context,"},{"line_number":149,"context_line":"            filters\u003d{"},{"line_number":150,"context_line":"                \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":151,"context_line":"                \u0027agent_type\u0027: [self.agent_type],"},{"line_number":152,"context_line":"                \u0027admin_state_up\u0027: [True],"},{"line_number":153,"context_line":"                \u0027alive\u0027: [True],"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_86047415","line":150,"updated":"2018-06-26 18:35:31.000000000","message":"We assume that placement + nova binds to a host and allocates the bandwidth from the same host. That seems like a fair assumption.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":147,"context_line":"        host_agents \u003d context._plugin.get_agents("},{"line_number":148,"context_line":"            context._plugin_context,"},{"line_number":149,"context_line":"            filters\u003d{"},{"line_number":150,"context_line":"                \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":151,"context_line":"                \u0027agent_type\u0027: [self.agent_type],"},{"line_number":152,"context_line":"                \u0027admin_state_up\u0027: [True],"},{"line_number":153,"context_line":"                \u0027alive\u0027: [True],"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_8808f090","line":150,"in_reply_to":"5f7c97a3_86047415","updated":"2018-06-27 10:16:02.000000000","message":"Yep.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":149,"context_line":"            filters\u003d{"},{"line_number":150,"context_line":"                \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":151,"context_line":"                \u0027agent_type\u0027: [self.agent_type],"},{"line_number":152,"context_line":"                \u0027admin_state_up\u0027: [True],"},{"line_number":153,"context_line":"                \u0027alive\u0027: [True],"},{"line_number":154,"context_line":"            }"},{"line_number":155,"context_line":"        )"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_660d9833","line":153,"range":{"start_line":152,"start_character":0,"end_line":153,"end_character":32},"updated":"2018-06-26 18:35:31.000000000","message":"These means we filter out disabled or seemingly dead agents. If this filters out the agent that would be responsible for the RP then I think we raise UnknownResourceProvider exception and that is pretty misleading from troubleshooting perspective. Maybe we need to check the admin state and the aliveness of the agent after we know if the agent would be responsible for the RP and if we found that the agent is responsible but disabled/dead then at least log something specific that helps the troubleshooter.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":149,"context_line":"            filters\u003d{"},{"line_number":150,"context_line":"                \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":151,"context_line":"                \u0027agent_type\u0027: [self.agent_type],"},{"line_number":152,"context_line":"                \u0027admin_state_up\u0027: [True],"},{"line_number":153,"context_line":"                \u0027alive\u0027: [True],"},{"line_number":154,"context_line":"            }"},{"line_number":155,"context_line":"        )"},{"line_number":156,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_08f4e085","line":153,"range":{"start_line":152,"start_character":0,"end_line":153,"end_character":32},"in_reply_to":"5f7c97a3_660d9833","updated":"2018-06-27 10:16:02.000000000","message":"Good point. However I think we don\u0027t want to duplicate the handling of dead agents at slightly different times. It seems better not to filter here for alive\u003d\u003dTrue. And leave the logging and erring out to the usual port binding process - which already handles the case when an agent is dead.\n\nOn the other hand I do think we want to filter out admin_state_down agents as if they were not even there. Because that\u0027s the point of disabling an agent.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"6ad9009cd549d781fa6f1530c76c403fd3246767","unresolved":false,"context_lines":[{"line_number":160,"context_line":""},{"line_number":161,"context_line":"        reported \u003d {}"},{"line_number":162,"context_line":"        for agent in host_agents:"},{"line_number":163,"context_line":"            if (\u0027resource_provider_bandwidths\u0027 in agent[\u0027configurations\u0027] and"},{"line_number":164,"context_line":"                    rp in agent[\u0027configurations\u0027]["},{"line_number":165,"context_line":"                        \u0027resource_provider_bandwidths\u0027]):"},{"line_number":166,"context_line":"                reported[agent[\u0027id\u0027]] \u003d agent"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"        if len(reported) \u003d\u003d 1:"},{"line_number":169,"context_line":"            agent \u003d reported.values[0]"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_f7f3819d","line":166,"range":{"start_line":163,"start_character":0,"end_line":166,"end_character":45},"updated":"2018-06-27 12:56:03.000000000","message":"While this change is not technically dependent on the other change (Ib197573e5cdb60ef0db4e7a771c3179bf9d5bb95) that starts reporting resource provider info in the configurations field of the agent heartbeat message, we do depend on the format of the configurations field. Which is not yet finalized.","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"dd07f8b6303f9c498fb74a0d31fa0ef3f92c0753","unresolved":false,"context_lines":[{"line_number":173,"context_line":"            # will be properly logged and handled very soon. That is when"},{"line_number":174,"context_line":"            # trying to bind with a dead agent."},{"line_number":175,"context_line":"        }"},{"line_number":176,"context_line":"        host_agents \u003d context._plugin.get_agents("},{"line_number":177,"context_line":"            context._plugin_context,"},{"line_number":178,"context_line":"            filters\u003dagent_filters,"},{"line_number":179,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_b253ec15","line":176,"updated":"2019-02-28 08:51:11.000000000","message":"nit: You can return here directly","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c36709d54b580cd01ee03ef83bc6b31e74e4ddd8","unresolved":false,"context_lines":[{"line_number":173,"context_line":"            # will be properly logged and handled very soon. That is when"},{"line_number":174,"context_line":"            # trying to bind with a dead agent."},{"line_number":175,"context_line":"        }"},{"line_number":176,"context_line":"        host_agents \u003d context._plugin.get_agents("},{"line_number":177,"context_line":"            context._plugin_context,"},{"line_number":178,"context_line":"            filters\u003dagent_filters,"},{"line_number":179,"context_line":"        )"}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_a6ade931","line":176,"in_reply_to":"9fdfeff1_b253ec15","updated":"2019-02-28 15:05:12.000000000","message":"Done","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"dd07f8b6303f9c498fb74a0d31fa0ef3f92c0753","unresolved":false,"context_lines":[{"line_number":227,"context_line":"                       \u0027rsc_provider\u0027: rp,"},{"line_number":228,"context_line":"                       \u0027agents\u0027: reported.keys()})"},{"line_number":229,"context_line":"            return False"},{"line_number":230,"context_line":"        elif len(reported) \u003c 1:"},{"line_number":231,"context_line":"            # not responsible, must be somebody else"},{"line_number":232,"context_line":"            return False"},{"line_number":233,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_92aa68cf","line":230,"updated":"2019-02-28 08:51:11.000000000","message":"nit: this isn\u0027t necessary, it will always be true if none of above conditions will be true :)","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c36709d54b580cd01ee03ef83bc6b31e74e4ddd8","unresolved":false,"context_lines":[{"line_number":227,"context_line":"                       \u0027rsc_provider\u0027: rp,"},{"line_number":228,"context_line":"                       \u0027agents\u0027: reported.keys()})"},{"line_number":229,"context_line":"            return False"},{"line_number":230,"context_line":"        elif len(reported) \u003c 1:"},{"line_number":231,"context_line":"            # not responsible, must be somebody else"},{"line_number":232,"context_line":"            return False"},{"line_number":233,"context_line":""}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_a62089b1","line":230,"in_reply_to":"9fdfeff1_92aa68cf","updated":"2019-02-28 15:05:12.000000000","message":"Done","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"3837b9466ca8d12ae87c0147ddc806b5d4b5a41b","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                               \"%s mechanism driver!\") % self.agent_type)"},{"line_number":164,"context_line":"        return supported_vnic_types"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def _possible_agents_for_port(self, context):"},{"line_number":167,"context_line":"        agent_filters \u003d {"},{"line_number":168,"context_line":"            \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":169,"context_line":"            \u0027agent_type\u0027: [self.agent_type],"}],"source_content_type":"text/x-python","patch_set":39,"id":"9fdfeff1_fd248962","line":166,"updated":"2019-03-05 08:37:47.000000000","message":"I\u0027m curious how it will work for agent less mechanism drivers, like networking-ovn for example. Did You maybe try something like that?","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"77bd5ad72bb9cf1e115fb167719455710023e8d2","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                               \"%s mechanism driver!\") % self.agent_type)"},{"line_number":164,"context_line":"        return supported_vnic_types"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def _possible_agents_for_port(self, context):"},{"line_number":167,"context_line":"        agent_filters \u003d {"},{"line_number":168,"context_line":"            \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":169,"context_line":"            \u0027agent_type\u0027: [self.agent_type],"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_343c56be","line":166,"in_reply_to":"9fdfeff1_b1ccea8a","updated":"2019-03-08 04:33:33.000000000","message":"In case of agent-less implementations, I guess a driver or a network controller (like ODL) needs to be responsible to maintain a mapping between neutron ports and hosts. binding:profile information is provided via the neutron API, so I think it can be done. It is not specific to placement allocation.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"5849cad384a20982f678e5285ec8649f9c7de4e9","unresolved":false,"context_lines":[{"line_number":163,"context_line":"                               \"%s mechanism driver!\") % self.agent_type)"},{"line_number":164,"context_line":"        return supported_vnic_types"},{"line_number":165,"context_line":""},{"line_number":166,"context_line":"    def _possible_agents_for_port(self, context):"},{"line_number":167,"context_line":"        agent_filters \u003d {"},{"line_number":168,"context_line":"            \u0027host\u0027: [context.current[\u0027binding:host_id\u0027]],"},{"line_number":169,"context_line":"            \u0027agent_type\u0027: [self.agent_type],"}],"source_content_type":"text/x-python","patch_set":39,"id":"9fdfeff1_b1ccea8a","line":166,"in_reply_to":"9fdfeff1_fd248962","updated":"2019-03-05 12:01:09.000000000","message":"No, I didn\u0027t it try agentless mech drivers yet. I\u0027m curious too. In the future we may need to implement this feature for odl, but I don\u0027t see the priorities yet, so I\u0027m not promising this.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"}],"neutron/plugins/ml2/managers.py":[{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"db1284f6163e97a46c37c82b2dab5bd3a8efd4d6","unresolved":false,"context_lines":[{"line_number":775,"context_line":"                       \u0027host\u0027: context.host})"},{"line_number":776,"context_line":"            return False"},{"line_number":777,"context_line":""},{"line_number":778,"context_line":"        # FIXME(bence romsics): This breaks hierarchical port binding."},{"line_number":779,"context_line":"        #"},{"line_number":780,"context_line":"        # Consider: \"In case of hierarchical port binding"},{"line_number":781,"context_line":"        # binding_profile.allocation is meant to drive the binding only on"},{"line_number":782,"context_line":"        # the binding level that represents the closest physical interface"},{"line_number":783,"context_line":"        # to the nova server.\" Link to spec:"},{"line_number":784,"context_line":"        #"},{"line_number":785,"context_line":"        # https://review.openstack.org/#/c/508149/14/specs"},{"line_number":786,"context_line":"        #        /rocky/minimum-bandwidth-allocation-placement-api.rst@582"},{"line_number":787,"context_line":"        #"},{"line_number":788,"context_line":"        # Given an allocation in binding_profile in HPB terms we must"},{"line_number":789,"context_line":"        # restrict the list of mechanism drivers tried. But only on the"},{"line_number":790,"context_line":"        # bottom (last) binding level. To do anything on the bottom (last)"},{"line_number":791,"context_line":"        # binding level we must know that the current level is going to be"},{"line_number":792,"context_line":"        # the last level. How do we do that?"},{"line_number":793,"context_line":"        #"},{"line_number":794,"context_line":"        # The code below affects all binding levels."},{"line_number":795,"context_line":"        if (context.current[\u0027binding:profile\u0027] is not None and"},{"line_number":796,"context_line":"                \u0027allocation\u0027 in context.current[\u0027binding:profile\u0027]):"},{"line_number":797,"context_line":"            drivers \u003d [self._infer_driver_from_allocation(context)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_4d3742b1","line":794,"range":{"start_line":778,"start_character":0,"end_line":794,"end_character":52},"updated":"2018-06-19 14:50:30.000000000","message":"I don\u0027t see a way to implement is_bottom_binding_level().\n\nBut I have a few ideas getting around the problem:\n\n* If we can trust the bind_port() implementations to be side effect free (beyond set_binding and continue_binding) we can change set_binding() to still reject some bindings. Kind of adding a bit of backtracking on top of the current logic.\n\n* We could drive the selection of all binding levels from placement. Of course that would significantly increase the scope of this work. But for a few limited use cases where the last binding level determines all binding levels we could make it simplet. That could work as a temporary solution.","commit_id":"806c0931fb1dabb1bf527017017b8a69a534b3c2"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"7c05b0a83e866c1f46d0c60ce09be38533802be7","unresolved":false,"context_lines":[{"line_number":775,"context_line":"                       \u0027host\u0027: context.host})"},{"line_number":776,"context_line":"            return False"},{"line_number":777,"context_line":""},{"line_number":778,"context_line":"        # FIXME(bence romsics): This breaks hierarchical port binding."},{"line_number":779,"context_line":"        #"},{"line_number":780,"context_line":"        # Consider: \"In case of hierarchical port binding"},{"line_number":781,"context_line":"        # binding_profile.allocation is meant to drive the binding only on"},{"line_number":782,"context_line":"        # the binding level that represents the closest physical interface"},{"line_number":783,"context_line":"        # to the nova server.\" Link to spec:"},{"line_number":784,"context_line":"        #"},{"line_number":785,"context_line":"        # https://review.openstack.org/#/c/508149/14/specs"},{"line_number":786,"context_line":"        #        /rocky/minimum-bandwidth-allocation-placement-api.rst@582"},{"line_number":787,"context_line":"        #"},{"line_number":788,"context_line":"        # Given an allocation in binding_profile in HPB terms we must"},{"line_number":789,"context_line":"        # restrict the list of mechanism drivers tried. But only on the"},{"line_number":790,"context_line":"        # bottom (last) binding level. To do anything on the bottom (last)"},{"line_number":791,"context_line":"        # binding level we must know that the current level is going to be"},{"line_number":792,"context_line":"        # the last level. How do we do that?"},{"line_number":793,"context_line":"        #"},{"line_number":794,"context_line":"        # The code below affects all binding levels."},{"line_number":795,"context_line":"        if (context.current[\u0027binding:profile\u0027] is not None and"},{"line_number":796,"context_line":"                \u0027allocation\u0027 in context.current[\u0027binding:profile\u0027]):"},{"line_number":797,"context_line":"            drivers \u003d [self._infer_driver_from_allocation(context)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"5f7c97a3_5db18fdf","line":794,"range":{"start_line":778,"start_character":0,"end_line":794,"end_character":52},"in_reply_to":"5f7c97a3_4d3742b1","updated":"2018-06-22 10:55:55.000000000","message":"We had a discussion on the networking-qos meeting:\n\nhttp://eavesdrop.openstack.org/meetings/neutron_qos/2018/neutron_qos.2018-06-19-15.00.log.html#l-22\n\nMiguel had another idea that seems to solve the problem. I\u0027ll get to implement it in the next patch set. But despite my previous hopes I will get to work on it only next week.","commit_id":"806c0931fb1dabb1bf527017017b8a69a534b3c2"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":758,"context_line":"                       \u0027vnic_type\u0027: binding.vnic_type,"},{"line_number":759,"context_line":"                       \u0027segments\u0027: context.network.network_segments})"},{"line_number":760,"context_line":""},{"line_number":761,"context_line":"    def _bind_port_level(self, context, level, segments_to_bind,"},{"line_number":762,"context_line":"                         drivers\u003dNone, redoing_bottom\u003dFalse):"},{"line_number":763,"context_line":"        if drivers is None:"},{"line_number":764,"context_line":"            drivers \u003d self.ordered_mech_drivers"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_b04f6568","line":761,"range":{"start_line":761,"start_character":8,"end_line":761,"end_character":24},"updated":"2018-06-26 18:35:31.000000000","message":"Do we have test coverage for the changes in this function?","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":758,"context_line":"                       \u0027vnic_type\u0027: binding.vnic_type,"},{"line_number":759,"context_line":"                       \u0027segments\u0027: context.network.network_segments})"},{"line_number":760,"context_line":""},{"line_number":761,"context_line":"    def _bind_port_level(self, context, level, segments_to_bind,"},{"line_number":762,"context_line":"                         drivers\u003dNone, redoing_bottom\u003dFalse):"},{"line_number":763,"context_line":"        if drivers is None:"},{"line_number":764,"context_line":"            drivers \u003d self.ordered_mech_drivers"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_4b7c1270","line":761,"range":{"start_line":761,"start_character":8,"end_line":761,"end_character":24},"in_reply_to":"5f7c97a3_b04f6568","updated":"2018-06-27 10:16:02.000000000","message":"Not yet. But it\u0027s coming.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":826,"context_line":"                        # called, and that\u0027s already too late. So we must"},{"line_number":827,"context_line":"                        # undo the last binding after set_binding() was called"},{"line_number":828,"context_line":"                        # and redo the last level trying to bind only with a"},{"line_number":829,"context_line":"                        # restricted list of drivers as inferred from the"},{"line_number":830,"context_line":"                        # allocation. In order to undo the binding here we"},{"line_number":831,"context_line":"                        # must also assume that each driver\u0027s bind_port()"},{"line_number":832,"context_line":"                        # implementation is side effect free beyond"},{"line_number":833,"context_line":"                        # calling set_binding()."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_3d832eab","line":830,"range":{"start_line":829,"start_character":26,"end_line":830,"end_character":36},"updated":"2018-06-26 18:35:31.000000000","message":"Is this list ever contains more than one driver?\n\n-- later --\nbased on L864 it is always a list with a single driver so we can be a bit more precise in the description.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":826,"context_line":"                        # called, and that\u0027s already too late. So we must"},{"line_number":827,"context_line":"                        # undo the last binding after set_binding() was called"},{"line_number":828,"context_line":"                        # and redo the last level trying to bind only with a"},{"line_number":829,"context_line":"                        # restricted list of drivers as inferred from the"},{"line_number":830,"context_line":"                        # allocation. In order to undo the binding here we"},{"line_number":831,"context_line":"                        # must also assume that each driver\u0027s bind_port()"},{"line_number":832,"context_line":"                        # implementation is side effect free beyond"},{"line_number":833,"context_line":"                        # calling set_binding()."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_0b45ba14","line":830,"range":{"start_line":829,"start_character":26,"end_line":830,"end_character":36},"in_reply_to":"5f7c97a3_3d832eab","updated":"2018-06-27 10:16:02.000000000","message":"Done","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":860,"context_line":"                            context._unset_binding()"},{"line_number":861,"context_line":"                            self._bind_port_level("},{"line_number":862,"context_line":"                                context, level, segments_to_bind,"},{"line_number":863,"context_line":"                                drivers\u003d[self._infer_driver_from_allocation("},{"line_number":864,"context_line":"                                    context)],"},{"line_number":865,"context_line":"                                redoing_bottom\u003dTrue)"},{"line_number":866,"context_line":""},{"line_number":867,"context_line":"                        # Binding complete."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_bd4e5e93","line":864,"range":{"start_line":863,"start_character":40,"end_line":864,"end_character":45},"updated":"2018-06-26 18:35:31.000000000","message":"yeah, this is always a list with a single driver.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":860,"context_line":"                            context._unset_binding()"},{"line_number":861,"context_line":"                            self._bind_port_level("},{"line_number":862,"context_line":"                                context, level, segments_to_bind,"},{"line_number":863,"context_line":"                                drivers\u003d[self._infer_driver_from_allocation("},{"line_number":864,"context_line":"                                    context)],"},{"line_number":865,"context_line":"                                redoing_bottom\u003dTrue)"},{"line_number":866,"context_line":""},{"line_number":867,"context_line":"                        # Binding complete."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_ab4fe632","line":864,"range":{"start_line":863,"start_character":40,"end_line":864,"end_character":45},"in_reply_to":"5f7c97a3_bd4e5e93","updated":"2018-06-27 10:16:02.000000000","message":"Done","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":907,"context_line":"            LOG.error(\"Failed to bind port %(port)s on host \""},{"line_number":908,"context_line":"                      \"%(host)s allocated on resource provider \""},{"line_number":909,"context_line":"                      \"%(rsc_provider)s, because no mechanism driver \""},{"line_number":910,"context_line":"                      \"reports being responsible and alive\","},{"line_number":911,"context_line":"                      {\u0027port\u0027: context.current[\u0027id\u0027],"},{"line_number":912,"context_line":"                       \u0027host\u0027: context.host,"},{"line_number":913,"context_line":"                       \u0027rsc_provider\u0027: context.current["}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_1d0d123d","line":910,"range":{"start_line":910,"start_character":37,"end_line":910,"end_character":58},"updated":"2018-06-26 18:35:31.000000000","message":"and enabled.\n\nBut we don\u0027t know which is the exact case :/ (e.g. responsible but disabled? nobody is responsible? responsible but dead?)","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":907,"context_line":"            LOG.error(\"Failed to bind port %(port)s on host \""},{"line_number":908,"context_line":"                      \"%(host)s allocated on resource provider \""},{"line_number":909,"context_line":"                      \"%(rsc_provider)s, because no mechanism driver \""},{"line_number":910,"context_line":"                      \"reports being responsible and alive\","},{"line_number":911,"context_line":"                      {\u0027port\u0027: context.current[\u0027id\u0027],"},{"line_number":912,"context_line":"                       \u0027host\u0027: context.host,"},{"line_number":913,"context_line":"                       \u0027rsc_provider\u0027: context.current["}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_6b046ec6","line":910,"range":{"start_line":910,"start_character":37,"end_line":910,"end_character":58},"in_reply_to":"5f7c97a3_1d0d123d","updated":"2018-06-27 10:16:02.000000000","message":"Done","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":27654,"name":"Hongbin Lu","email":"kira034@163.com","username":"hongbin.lu"},"change_message_id":"7f9074f5f66827cb2a5cd6299a03b3236f4d2ea6","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_b28f4921","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"updated":"2018-06-27 22:24:43.000000000","message":"I am not sure if undoing the last binding would be enough. Per my understanding of the spec [1], I guess the worst case is that you need to undo until the top level (if the top level chose the wrong driver to bind at the beginning)?\n\n[1] https://specs.openstack.org/openstack/neutron-specs/specs/kilo/ml2-hierarchical-port-binding.html","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":27654,"name":"Hongbin Lu","email":"kira034@163.com","username":"hongbin.lu"},"change_message_id":"ad0891740920b3b82d5d04b9f9fcedd9f4d10ed0","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_a63354c4","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"in_reply_to":"5f7c97a3_135b75f6","updated":"2018-06-29 18:49:16.000000000","message":"I like the approach of #2, but it somehow appears to be a long-term shoot.\n\nIn short-term, I think what might be better is to define an interface for each driver to tell neutron if it supports minimum bandwidth. Each driver can implement this interface and return true or false. If the interface is not implemented, the base class implementation returns false. If a driver implement this interface and return true, it means that this driver supports minimum bandwidth requirements (i.e. can undo binding, can process binding:profile.allocate and pick the right path to the allocated resource in the host). Then, neutron can detect and handle the incompatible cases, such as minimum bandwidth is required but not supported by drivers.\n\nHowever, this is my personal opinion. It might not make sense since I am not an expert in this domain. You might want to consult with other neutron experts to decide.","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"fbb1268f59344f1bb041e84d1cf116ec1a101108","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_135b75f6","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"in_reply_to":"5f7c97a3_686f6728","updated":"2018-06-29 13:06:58.000000000","message":"You\u0027re right. This change as-it-is breaks the setup you drew.\n\nThinking about what to do with that I see multiple factors:\n\n(1) The HPB setup drawn is actively used by somebody today. In this case we clearly need to come up with a better plan. And I would really like to know about the use case. I can imagine use cases but that\u0027s pure speculation. For example having cheap-and-simple and expensive-and-better switches for different service levels. Or changing switch vendors while expanding a cloud deployment. But I\u0027d like to avoid designing for speculative use cases.\n\nHowever there\u0027s a way out. The guaranteed bandwidth feature will be developed in a way that the admin can turn it on and off. Simply by loading a service plugin or not. When the feature is turned off neutron will not request (placement) resources for a port (no resource_request attr in the port) therefore nova will not send back an allocation to neutron (no binding:profile.allocation). Therefore we are never going to undo a binding.\n\nSo if a user uses HPB like in your drawing, the minimum bandwidth feature will not break HPB when min-bw is turned off. We can document the two use cases being incompatible (until later development).\n\n(2) The HPB setup drawn is a meaningful use case of HPB, but nobody uses it today (yet). Maybe in the future. In that case we can say to them: Please model the different capabilities of switch A and B in placement properly (by resource inventories and traits) and let placement drive binding level 1 (or higher) too.\n\nWhat do you think?","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":27654,"name":"Hongbin Lu","email":"kira034@163.com","username":"hongbin.lu"},"change_message_id":"ccc5ff82ebd16476d9caf8a168c2a4bb960fe666","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_686f6728","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"in_reply_to":"5f7c97a3_9790f6f5","updated":"2018-06-28 18:14:07.000000000","message":"I see. I am totally fine with this approach if it covers the common use cases. Just want to point out a potential edge scenario that might fail the binding (If it is not incorrect or not a practical scenario, feel free to disregard the comment):\n\n                          +-------------+\n                          |             |\n                          | Core Switch |\n                          |             |\n                          +---+-----+---+\n                  VXLAN       |     |       VXLAN\n                  +-----------+     +------------+\n                  |                              |\n           +------+-----+                 +------+-----+\n           |            |                 |            |\n           | Switch A   |                 | Switch B   |\n           |            |                 |            |\n           +---+---+----+                 +---+----+---+\n       VLAN    |   |   VLAN           VLAN    |    |    VLAN\n       +-------+   +----+  +-------------+----+    +------+\n       |                |  |             |                |\n  +----+----+      +----+--+-+      +----+----+      +----+----+\n  |         |      |         |      |         |      |         |\n  | Compute |      | Compute |      | Compute |      | Compute |\n  | Node    |      | Node 2  |      | Node    |      | Node    |\n  |         |      |         |      |         |      |         |\n  +---------+      +---------+      +---------+      +---------+\n\n* Compute node B has two drivers A and B\n* Driver A connects to Switch A\n* Driver B connects to Switch B\n* Switch A and B connects to the core switch\n* The mechanism driver orders is [A, B]\n* binding:profile points to an agent for driver B\n\nThen, the current approach seems to run this way:\n* level 0: core switch\n* level 1: Switch A\n* level 2: Driver A\n* undo binding in level 2\n* redo the binding: cannot bind because switch A is unreachable from driver B\u0027s segment?\n\nThoughts?","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"be6ad8f9da9e5b34559343e97088344c48cbf46c","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_6ae648ea","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"in_reply_to":"5f7c97a3_a63354c4","updated":"2018-07-02 12:12:23.000000000","message":"IMHO it is not possible for a driver to \"pick the right path\". That must be coordinated from MechanismManager. Theoretically we could change HPB to a full backtracking algorithm to always find the right path. However by that we\u0027d be putting even stronger constraints on what bind_port() can do (so it can always be undone while backtracking). Since port binding is not running in a transaction I\u0027d like to avoid an approach like that because of the possible side effects not foreseen.\n\nI\u0027ll advertise this patch for review on the next neutron meeting hoping this\u0027ll get more attention from HPB experts.","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"1709ffae12139246b391c14d5fdc087f55c4066a","unresolved":false,"context_lines":[{"line_number":824,"context_line":"                        # But we cannot tell if a binding level is"},{"line_number":825,"context_line":"                        # the bottom binding level before set_binding()"},{"line_number":826,"context_line":"                        # gets called, and that\u0027s already too late. So we"},{"line_number":827,"context_line":"                        # must undo the last binding after set_binding()"},{"line_number":828,"context_line":"                        # was called and redo the last level trying to"},{"line_number":829,"context_line":"                        # bind only with one driver as inferred from"},{"line_number":830,"context_line":"                        # the allocation. In order to undo the binding"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f7c97a3_9790f6f5","line":827,"range":{"start_line":827,"start_character":40,"end_line":827,"end_character":52},"in_reply_to":"5f7c97a3_b28f4921","updated":"2018-06-28 07:19:51.000000000","message":"I agree that later when we try to support more generic guarantees we are going to have to drive higher binding levels too. However the current scope of the strict-minimum-bw spec is limited to guarantee bw on the closest physical interface. In my mind that quite directly translates to the lowest binding level in HPB. For example we don\u0027t aim to guarantee bw on the leaf switch port or in the switch fabric - that would translate to higher binding levels.\n\nI also see that what we\u0027re proposing here is somewhat limiting the theoretical genericity of HPB (if the choice of drivers on different levels is interdependent). However we had a discussion around this problem on the last qos meeting (starting here: http://eavesdrop.openstack.org/meetings/neutron_qos/2018/neutron_qos.2018-06-19-15.00.log.html#l-22) and this was the best idea we came up with. Also my understanding is that current use cases of HPB hardly use the full theoretical power of HPB.\n\nIf you see a practical HPB use case we would be breaking with this please elaborate.","commit_id":"0522063ee2bc20696aef52769413d062d358433f"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d1553c962eb3477f1517beb9fc0641522f0fbb2b","unresolved":false,"context_lines":[{"line_number":854,"context_line":"                            LOG.debug("},{"line_number":855,"context_line":"                                \"Undo bottom bound level and redo it \""},{"line_number":856,"context_line":"                                \"according to binding_profile.allocation, \""},{"line_number":857,"context_line":"                                \"resource provider uuid: %(rp)s\","},{"line_number":858,"context_line":"                                context.current["},{"line_number":859,"context_line":"                                    \u0027binding:profile\u0027][\u0027allocation\u0027])"},{"line_number":860,"context_line":"                            context._pop_binding_level()"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_c0973a90","line":857,"range":{"start_line":857,"start_character":59,"end_line":857,"end_character":61},"updated":"2018-08-21 14:47:28.000000000","message":"TypeError: not all arguments converted during string formatting","commit_id":"d20771aae2ebdc027b1c6145264aa839e3239baf"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"36935e6f9fced7dc62f43df840f1e057c46af8b2","unresolved":false,"context_lines":[{"line_number":854,"context_line":"                            LOG.debug("},{"line_number":855,"context_line":"                                \"Undo bottom bound level and redo it \""},{"line_number":856,"context_line":"                                \"according to binding_profile.allocation, \""},{"line_number":857,"context_line":"                                \"resource provider uuid: %(rp)s\","},{"line_number":858,"context_line":"                                context.current["},{"line_number":859,"context_line":"                                    \u0027binding:profile\u0027][\u0027allocation\u0027])"},{"line_number":860,"context_line":"                            context._pop_binding_level()"}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_fdc9c950","line":857,"range":{"start_line":857,"start_character":59,"end_line":857,"end_character":61},"in_reply_to":"3f79a3b5_c0973a90","updated":"2018-08-31 12:54:26.000000000","message":"Done","commit_id":"d20771aae2ebdc027b1c6145264aa839e3239baf"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d1553c962eb3477f1517beb9fc0641522f0fbb2b","unresolved":false,"context_lines":[{"line_number":923,"context_line":"                  \"(as inferred from placement allocation) to \""},{"line_number":924,"context_line":"                  \"mechanism driver \u0027%(driver)s\u0027\","},{"line_number":925,"context_line":"                  {\u0027port\u0027: context.current[\u0027id\u0027],"},{"line_number":926,"context_line":"                   \u0027driver\u0027: drivers[0]})"},{"line_number":927,"context_line":""},{"line_number":928,"context_line":"        return drivers[0]"},{"line_number":929,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_e0459616","line":926,"range":{"start_line":926,"start_character":29,"end_line":926,"end_character":39},"updated":"2018-08-21 14:47:28.000000000","message":"drivers[0].name","commit_id":"d20771aae2ebdc027b1c6145264aa839e3239baf"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"36935e6f9fced7dc62f43df840f1e057c46af8b2","unresolved":false,"context_lines":[{"line_number":923,"context_line":"                  \"(as inferred from placement allocation) to \""},{"line_number":924,"context_line":"                  \"mechanism driver \u0027%(driver)s\u0027\","},{"line_number":925,"context_line":"                  {\u0027port\u0027: context.current[\u0027id\u0027],"},{"line_number":926,"context_line":"                   \u0027driver\u0027: drivers[0]})"},{"line_number":927,"context_line":""},{"line_number":928,"context_line":"        return drivers[0]"},{"line_number":929,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"3f79a3b5_9dd8d51e","line":926,"range":{"start_line":926,"start_character":29,"end_line":926,"end_character":39},"in_reply_to":"3f79a3b5_e0459616","updated":"2018-08-31 12:54:26.000000000","message":"Done","commit_id":"d20771aae2ebdc027b1c6145264aa839e3239baf"},{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"dd07f8b6303f9c498fb74a0d31fa0ef3f92c0753","unresolved":false,"context_lines":[{"line_number":813,"context_line":"                                         \u0027lvl\u0027: level + 1})"},{"line_number":814,"context_line":"                            context._pop_binding_level()"},{"line_number":815,"context_line":"                    else:"},{"line_number":816,"context_line":"                        # NOTE(bence romsics): Consider: \"In case of"},{"line_number":817,"context_line":"                        # hierarchical port binding binding_profile.allocation"},{"line_number":818,"context_line":"                        # [decided and sent by Placement and Nova]"},{"line_number":819,"context_line":"                        # is meant to drive the binding only on the binding"}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_b2c8cca7","line":816,"range":{"start_line":816,"start_character":57,"end_line":816,"end_character":58},"updated":"2019-02-28 08:51:11.000000000","message":"nitty nitty nit: not needed :)","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"c36709d54b580cd01ee03ef83bc6b31e74e4ddd8","unresolved":false,"context_lines":[{"line_number":813,"context_line":"                                         \u0027lvl\u0027: level + 1})"},{"line_number":814,"context_line":"                            context._pop_binding_level()"},{"line_number":815,"context_line":"                    else:"},{"line_number":816,"context_line":"                        # NOTE(bence romsics): Consider: \"In case of"},{"line_number":817,"context_line":"                        # hierarchical port binding binding_profile.allocation"},{"line_number":818,"context_line":"                        # [decided and sent by Placement and Nova]"},{"line_number":819,"context_line":"                        # is meant to drive the binding only on the binding"}],"source_content_type":"text/x-python","patch_set":37,"id":"9fdfeff1_a10e332f","line":816,"range":{"start_line":816,"start_character":57,"end_line":816,"end_character":58},"in_reply_to":"9fdfeff1_b2c8cca7","updated":"2019-02-28 15:05:12.000000000","message":"It\u0027s in apostrophes because it\u0027s a quote from the spec. :-)","commit_id":"96e4516da1b0ad21547eca246743298a8eeced43"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"9a0b81d45cbb167074725a64a8ca8770f3f2b95f","unresolved":false,"context_lines":[{"line_number":765,"context_line":""},{"line_number":766,"context_line":"        binding \u003d context._binding"},{"line_number":767,"context_line":"        port_id \u003d context.current[\u0027id\u0027]"},{"line_number":768,"context_line":"        LOG.debug(\"Attempting to bind port %(port)s by drivers %(drivers)s \""},{"line_number":769,"context_line":"                  \"on host %(host)s at level %(level)s using \""},{"line_number":770,"context_line":"                  \"segments %(segments)s\","},{"line_number":771,"context_line":"                  {\u0027port\u0027: port_id,"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_a1060620","line":768,"range":{"start_line":768,"start_character":52,"end_line":768,"end_character":54},"updated":"2019-03-05 21:55:30.000000000","message":"Super nit: with\n\nDon\u0027t do anything unless you roll another patch","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d4723c83923d0a4bfc51ed1b6b21c1b7cb32ff61","unresolved":false,"context_lines":[{"line_number":765,"context_line":""},{"line_number":766,"context_line":"        binding \u003d context._binding"},{"line_number":767,"context_line":"        port_id \u003d context.current[\u0027id\u0027]"},{"line_number":768,"context_line":"        LOG.debug(\"Attempting to bind port %(port)s by drivers %(drivers)s \""},{"line_number":769,"context_line":"                  \"on host %(host)s at level %(level)s using \""},{"line_number":770,"context_line":"                  \"segments %(segments)s\","},{"line_number":771,"context_line":"                  {\u0027port\u0027: port_id,"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_20f68791","line":768,"range":{"start_line":768,"start_character":52,"end_line":768,"end_character":54},"in_reply_to":"5fc1f717_a1060620","updated":"2019-03-06 06:52:57.000000000","message":"ack","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"77bd5ad72bb9cf1e115fb167719455710023e8d2","unresolved":false,"context_lines":[{"line_number":812,"context_line":"                                         \u0027host\u0027: context.host,"},{"line_number":813,"context_line":"                                         \u0027lvl\u0027: level + 1})"},{"line_number":814,"context_line":"                            context._pop_binding_level()"},{"line_number":815,"context_line":"                    else:"},{"line_number":816,"context_line":"                        # NOTE(bence romsics): Consider: \"In case of"},{"line_number":817,"context_line":"                        # hierarchical port binding binding_profile.allocation"},{"line_number":818,"context_line":"                        # [decided and sent by Placement and Nova]"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_94766aa4","line":815,"updated":"2019-03-08 04:33:33.000000000","message":"future improvement: The indent level is too deep now. Hopefully the logic should be a separate function.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"e60f88910962bbb0192c0d2ca6a755dc2ee36b89","unresolved":false,"context_lines":[{"line_number":902,"context_line":""},{"line_number":903,"context_line":"        drivers \u003d []"},{"line_number":904,"context_line":"        for driver in self.ordered_mech_drivers:"},{"line_number":905,"context_line":"            if driver.obj.responsible_for_ports_allocation(context):"},{"line_number":906,"context_line":"                drivers.append(driver)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        if len(drivers) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_d323ecbd","line":905,"range":{"start_line":905,"start_character":15,"end_line":905,"end_character":68},"updated":"2019-03-05 19:19:05.000000000","message":"I doubt this will break other ml2 backends ? its not implemented for any of ml2 driver afaik","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"9e6e76751e3438cf206a18be522e158a4b3c6b56","unresolved":false,"context_lines":[{"line_number":902,"context_line":""},{"line_number":903,"context_line":"        drivers \u003d []"},{"line_number":904,"context_line":"        for driver in self.ordered_mech_drivers:"},{"line_number":905,"context_line":"            if driver.obj.responsible_for_ports_allocation(context):"},{"line_number":906,"context_line":"                drivers.append(driver)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        if len(drivers) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_1b1e5e0c","line":905,"range":{"start_line":905,"start_character":15,"end_line":905,"end_character":68},"in_reply_to":"5fc1f717_a0e117d3","updated":"2019-03-06 07:25:13.000000000","message":"ohk when i reviewed this code I was thinking mostly out of tree drivers inheriting from neutron_lib.plugins.ml2.api.MechanismDriver\nwhich are networking-odl and networking-ovn and missed the neutron-lib part.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"9a0b81d45cbb167074725a64a8ca8770f3f2b95f","unresolved":false,"context_lines":[{"line_number":902,"context_line":""},{"line_number":903,"context_line":"        drivers \u003d []"},{"line_number":904,"context_line":"        for driver in self.ordered_mech_drivers:"},{"line_number":905,"context_line":"            if driver.obj.responsible_for_ports_allocation(context):"},{"line_number":906,"context_line":"                drivers.append(driver)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        if len(drivers) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_dc49b932","line":905,"range":{"start_line":905,"start_character":15,"end_line":905,"end_character":68},"in_reply_to":"5fc1f717_d323ecbd","updated":"2019-03-05 21:55:30.000000000","message":"Well, it is implemented here https://review.openstack.org/#/c/574783/39/neutron/plugins/ml2/drivers/mech_agent.py@181, which makes it implemented in the SimpleAgentMechanismDriverBase class: https://review.openstack.org/#/c/574783/39/neutron/plugins/ml2/drivers/mech_agent.py@235. All the neutron in-tree mechanism driver inherit from this class, along with other mechanism drivers out of the neutron tree: http://codesearch.openstack.org/?q\u003dSimpleAgentMechanismDriverBase\u0026i\u003dnope\u0026files\u003d\u0026repos\u003d","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d4723c83923d0a4bfc51ed1b6b21c1b7cb32ff61","unresolved":false,"context_lines":[{"line_number":902,"context_line":""},{"line_number":903,"context_line":"        drivers \u003d []"},{"line_number":904,"context_line":"        for driver in self.ordered_mech_drivers:"},{"line_number":905,"context_line":"            if driver.obj.responsible_for_ports_allocation(context):"},{"line_number":906,"context_line":"                drivers.append(driver)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        if len(drivers) \u003d\u003d 0:"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_a0e117d3","line":905,"range":{"start_line":905,"start_character":15,"end_line":905,"end_character":68},"in_reply_to":"5fc1f717_dc49b932","updated":"2019-03-06 06:52:57.000000000","message":"I think it should not break other drivers since the method responsible_for_ports_allocation is added to neutron_lib.plugins.ml2.api.MechanismDriver with a concrete, backwards-compatible implementation.\n\nhttps://github.com/openstack/neutron-lib/blob/fc2a81058bfd3ba9fd3501660156c71ff1c8129c/neutron_lib/plugins/ml2/api.py#L429\n\nBut let me know please if I\u0027m missing something.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"}],"neutron/tests/unit/plugins/ml2/drivers/mech_fake_agent.py":[{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"e60f88910962bbb0192c0d2ca6a755dc2ee36b89","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        return dict(agent[\u0027configurations\u0027].get(\u0027interface_mappings\u0027, {}))"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class AnotherFakeAgentMechanismDriver(FakeAgentMechanismDriver):"},{"line_number":66,"context_line":"    pass"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_93580457","line":66,"range":{"start_line":65,"start_character":0,"end_line":66,"end_character":8},"updated":"2019-03-05 19:19:05.000000000","message":"why not use existing FakeAgentMechanismDriver ? all you need is to mock responsible_for_ports_allocation ?","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":17120,"name":"Manjeet Singh Bhatia","email":"manjeet.s.bhatia@intel.com","username":"manjeets"},"change_message_id":"9e6e76751e3438cf206a18be522e158a4b3c6b56","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        return dict(agent[\u0027configurations\u0027].get(\u0027interface_mappings\u0027, {}))"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class AnotherFakeAgentMechanismDriver(FakeAgentMechanismDriver):"},{"line_number":66,"context_line":"    pass"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_9bd7ae24","line":66,"range":{"start_line":65,"start_character":0,"end_line":66,"end_character":8},"in_reply_to":"5fc1f717_00f90b7f","updated":"2019-03-06 07:25:13.000000000","message":"ah strange, but sounds reasonable.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"d4723c83923d0a4bfc51ed1b6b21c1b7cb32ff61","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        return dict(agent[\u0027configurations\u0027].get(\u0027interface_mappings\u0027, {}))"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"class AnotherFakeAgentMechanismDriver(FakeAgentMechanismDriver):"},{"line_number":66,"context_line":"    pass"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_00f90b7f","line":66,"range":{"start_line":65,"start_character":0,"end_line":66,"end_character":8},"in_reply_to":"5fc1f717_93580457","updated":"2019-03-06 06:52:57.000000000","message":"Some of the test logic needs two fake mechanism drivers. IIRC the same driver cannot be loaded twice, therefore I needed the same under a new class and driver name.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"}],"neutron/tests/unit/plugins/ml2/test_managers.py":[{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":78,"context_line":"                               return_value\u003dTrue):"},{"line_number":79,"context_line":"            self.assertEqual("},{"line_number":80,"context_line":"                manager._infer_driver_from_allocation("},{"line_number":81,"context_line":"                    FakePortContext("},{"line_number":82,"context_line":"                        None,"},{"line_number":83,"context_line":"                        None,"},{"line_number":84,"context_line":"                        self.segments_to_bind,"},{"line_number":85,"context_line":"                        profile\u003d{\u0027allocation\u0027: \u0027fake_resource_provider\u0027})"},{"line_number":86,"context_line":"                ).name,"},{"line_number":87,"context_line":"                \u0027fake_agent\u0027"},{"line_number":88,"context_line":"            )"},{"line_number":89,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_b001a506","line":86,"range":{"start_line":81,"start_character":0,"end_line":86,"end_character":17},"updated":"2018-06-26 18:35:31.000000000","message":"if we could move this creation before the assert then the assert would be a bit more readable for me","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":78,"context_line":"                               return_value\u003dTrue):"},{"line_number":79,"context_line":"            self.assertEqual("},{"line_number":80,"context_line":"                manager._infer_driver_from_allocation("},{"line_number":81,"context_line":"                    FakePortContext("},{"line_number":82,"context_line":"                        None,"},{"line_number":83,"context_line":"                        None,"},{"line_number":84,"context_line":"                        self.segments_to_bind,"},{"line_number":85,"context_line":"                        profile\u003d{\u0027allocation\u0027: \u0027fake_resource_provider\u0027})"},{"line_number":86,"context_line":"                ).name,"},{"line_number":87,"context_line":"                \u0027fake_agent\u0027"},{"line_number":88,"context_line":"            )"},{"line_number":89,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_cbf822c2","line":86,"range":{"start_line":81,"start_character":0,"end_line":86,"end_character":17},"in_reply_to":"5f7c97a3_b001a506","updated":"2018-06-27 10:16:02.000000000","message":"Done","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"f717d5d45b95e24f273abe9efcb1c62a93458665","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                    self.segments_to_bind,"},{"line_number":104,"context_line":"                    profile\u003d{\u0027allocation\u0027: \u0027fake_resource_provider\u0027})"},{"line_number":105,"context_line":"            )"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    @mock.patch.object(managers.LOG, \u0027critical\u0027)"},{"line_number":108,"context_line":"    @mock.patch.object(managers.MechanismManager, \u0027_driver_not_loaded\u0027)"},{"line_number":109,"context_line":"    def test__driver_not_found(self, mock_not_loaded, mock_log):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_f02b9d78","line":106,"updated":"2018-06-26 18:35:31.000000000","message":"I suggest to add a test case for ambiguous responsibility.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"},{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"3c69b6688a70e668b58fbfc341df2a77c088d087","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                    self.segments_to_bind,"},{"line_number":104,"context_line":"                    profile\u003d{\u0027allocation\u0027: \u0027fake_resource_provider\u0027})"},{"line_number":105,"context_line":"            )"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    @mock.patch.object(managers.LOG, \u0027critical\u0027)"},{"line_number":108,"context_line":"    @mock.patch.object(managers.MechanismManager, \u0027_driver_not_loaded\u0027)"},{"line_number":109,"context_line":"    def test__driver_not_found(self, mock_not_loaded, mock_log):"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f7c97a3_cb1102fa","line":106,"in_reply_to":"5f7c97a3_f02b9d78","updated":"2018-06-27 10:16:02.000000000","message":"Will do soon.","commit_id":"207c6a819254d91cbb7caf0850cbaebbe289866e"}],"neutron/tests/unit/plugins/ml2/test_port_binding.py":[{"author":{"_account_id":15554,"name":"Bence Romsics","email":"bence.romsics@gmail.com","username":"ebenrom","status":"working for Ericsson, UTC+1 (+DST)"},"change_message_id":"544b74680fc5492d611871ed6bace9f8a4fc62e6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":30,"id":"9fdfeff1_82b7f5d8","line":660,"updated":"2019-02-08 11:21:32.000000000","message":"I hoped to write a positive test too here, but TestMechanismDriver makes that hard. It has some assert logic that remembers previously bound ports (in self.bound_ports and the related asserts in _check_port_context()). That is the exact kind of side effect the undo-redo bind logic introduced in this patch cannot work with. That is when you try to bind a port with an allocation then TestMechanismDriver will bind the port first then will fail to bind the same port at the redo, all because of the memory in self.bound_ports.\n\nI think technically TestMechanismDriver has the wrong assumptions here, and if we want a positive test here, then TestMechanismDriver should be reworked.\n\nI\u0027m not sure if this positive test is that important because we already have a few tests for the successful binding case in the mech_driver unit test source files.","commit_id":"817eada74976f9c5a1a3cc567792ef327d95ad8b"},{"author":{"_account_id":841,"name":"Akihiro Motoki","email":"amotoki@gmail.com","username":"amotoki"},"change_message_id":"77bd5ad72bb9cf1e115fb167719455710023e8d2","unresolved":false,"context_lines":[{"line_number":655,"context_line":""},{"line_number":656,"context_line":"            self.assertEqual(webob.exc.HTTPInternalServerError.code,"},{"line_number":657,"context_line":"                             response.status_int)"},{"line_number":658,"context_line":"            self.assertTrue(exceptions.PortBindingError.__name__ in"},{"line_number":659,"context_line":"                            response.text)"}],"source_content_type":"text/x-python","patch_set":39,"id":"5fc1f717_34d8d67d","line":658,"range":{"start_line":658,"start_character":17,"end_line":658,"end_character":27},"updated":"2019-03-08 04:33:33.000000000","message":"nit: assertIn is recommended.","commit_id":"c55c6d36997248ae0fd62775e0a26c10c5c362e0"}]}
