)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"cf2905be8d6915021121672a9b1284f216c9af3f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"4264d4a1_8dea5f93","updated":"2026-04-21 23:58:42.000000000","message":"I\u0027m fine with the concept just a couple of comments.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":5890,"name":"Doug Goldstein","email":"cardoe@cardoe.com","username":"cardoe"},"change_message_id":"73011654d8bf9f7e5fc42f860d7034d3b41a8aee","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":1,"id":"511c7ca2_9e2eae00","updated":"2026-05-08 01:03:31.000000000","message":"So reading through the comments, I\u0027m unsure of next steps to proceed here. This is something we carry down stream because like Julia said, sometimes binding cannot safely proceed and we need to pump the brakes.\n\nUltimately the error for us bubbles up into Nova and they like to wrap these with user friendly messages that don\u0027t give away details so that\u0027s the step after we get this.\n\nEven though I\u0027ll work with Nova, my interest is in the non-VM case.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"}],"neutron/plugins/ml2/common/exceptions.py":[{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"cf2905be8d6915021121672a9b1284f216c9af3f","unresolved":true,"context_lines":[{"line_number":42,"context_line":"                \"service plugin %(service_plugin)s not found.\")"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"class PortBindingError(exceptions.NeutronException):"},{"line_number":46,"context_line":"    \"\"\"Mechanism driver has determined port binding is impossible."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    This exception can be raised by a mechanism driver during"}],"source_content_type":"text/x-python","patch_set":1,"id":"95935f66_004a8568","line":45,"updated":"2026-04-21 23:58:42.000000000","message":"This exact exception already exists in neutron-lib at neutron-lib/exceptions:\n\nclass PortBindingError(NeutronException):\n    message \u003d _(\"Binding for port %(port_id)s on host %(host)s could not be \"\n                \"created or updated.\")\n\nWe do already have the port ID and host here, so maybe that works? Just does not have a space for driver name.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"df6c19ae07555059530eb44edca4df1a8de3b876","unresolved":true,"context_lines":[{"line_number":42,"context_line":"                \"service plugin %(service_plugin)s not found.\")"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"class PortBindingError(exceptions.NeutronException):"},{"line_number":46,"context_line":"    \"\"\"Mechanism driver has determined port binding is impossible."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    This exception can be raised by a mechanism driver during"}],"source_content_type":"text/x-python","patch_set":1,"id":"2fc30b73_342bf511","line":45,"in_reply_to":"95935f66_004a8568","updated":"2026-04-28 23:58:01.000000000","message":"fair, and yay for claude not finding it. Anyhow, we have the port ID, but no real host to speak of there. I mean, we could go extract it from the binding info, but but its just immaterial to the actual issue since the easy to discover location of the data would be on the baremetal node\u0027s last_error field or node_history data, and not the logs.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"}],"neutron/plugins/ml2/managers.py":[{"author":{"_account_id":16688,"name":"Rodolfo Alonso","email":"ralonsoh@redhat.com","username":"rodolfo-alonso-hernandez"},"change_message_id":"083c891e1a0263d2a635d020dbce99d11a6f9fef","unresolved":true,"context_lines":[{"line_number":958,"context_line":"                                   \u0027vif_details\u0027: binding.vif_details,"},{"line_number":959,"context_line":"                                   \u0027binding_levels\u0027: context.binding_levels})"},{"line_number":960,"context_line":"                        return True"},{"line_number":961,"context_line":"            except ml2_exc.PortBindingError:"},{"line_number":962,"context_line":"                LOG.error("},{"line_number":963,"context_line":"                    \"Mechanism driver %s determined that port \""},{"line_number":964,"context_line":"                    \"binding cannot succeed, aborting binding\","}],"source_content_type":"text/x-python","patch_set":1,"id":"848247d9_57bee9e4","line":961,"range":{"start_line":961,"start_character":27,"end_line":961,"end_character":43},"updated":"2026-04-23 10:10:33.000000000","message":"First of all, the exception `PortBindingError` could only happen when live-migrating. That\u0027s another case that should be handled, but maybe not related to Ironic.\n\nIn a port creation and binding, it is called `Ml2plugin.update_port` --\u003e `_bind_port_if_needed` --\u003e \u003cmech_driver\u003e.`bind_port`. In this code the exception `PortBindingError` is not raised.\n\nI would need to check in deep the HPB but if, as done here, we return `False`, we\u0027ll undo the upper bindings. But the point here is a way to define \"something\" that really stops the binding. As commented in the etherpad and in the bug, the `_bind_port_level` is a loop for all available mech drivers and none of them exits the loop/method if it cannot bind the port. So we need a good reason to say that a port, once treated by a specific driver, cannot be bound by itself and any other configured driver.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"731f0bdeb5061f22b3bc0b43e04744bea158ec46","unresolved":true,"context_lines":[{"line_number":958,"context_line":"                                   \u0027vif_details\u0027: binding.vif_details,"},{"line_number":959,"context_line":"                                   \u0027binding_levels\u0027: context.binding_levels})"},{"line_number":960,"context_line":"                        return True"},{"line_number":961,"context_line":"            except ml2_exc.PortBindingError:"},{"line_number":962,"context_line":"                LOG.error("},{"line_number":963,"context_line":"                    \"Mechanism driver %s determined that port \""},{"line_number":964,"context_line":"                    \"binding cannot succeed, aborting binding\","}],"source_content_type":"text/x-python","patch_set":1,"id":"104d877a_cfc058a4","line":961,"range":{"start_line":961,"start_character":27,"end_line":961,"end_character":43},"in_reply_to":"5f6e5423_f010483e","updated":"2026-04-29 05:06:43.000000000","message":"so then why not define an exception which aborts all the way instead of just returning false? I think the basic challenge here is that this is a recursive function as well. I think the only way then is to catch the exception in each method and then re-raise all the way back to the original bind_port.\n\nBut even then, it feels a bit like perfection because the eventual port deletion should wipe everything out even if its in a partial state.\n\nI guess the thing that feels odd here is a hyper-focus on VM networking flows where at a higher level when on the baremetal side its still managed and eventually unwound. At least a mixed state does sort of make it more possible to debug if a driver raising an exception leaves things as they were to be actually investigated. At least with the ML2 drivers Ironic manages, we can log quite a bit and make it clear albeit only really discoverable via logs. At the end of the day, we just to hit the breaks so we can discover there is a problem when an exception gets raised internally.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"df6c19ae07555059530eb44edca4df1a8de3b876","unresolved":true,"context_lines":[{"line_number":958,"context_line":"                                   \u0027vif_details\u0027: binding.vif_details,"},{"line_number":959,"context_line":"                                   \u0027binding_levels\u0027: context.binding_levels})"},{"line_number":960,"context_line":"                        return True"},{"line_number":961,"context_line":"            except ml2_exc.PortBindingError:"},{"line_number":962,"context_line":"                LOG.error("},{"line_number":963,"context_line":"                    \"Mechanism driver %s determined that port \""},{"line_number":964,"context_line":"                    \"binding cannot succeed, aborting binding\","}],"source_content_type":"text/x-python","patch_set":1,"id":"85b21f5c_d9e4dee3","line":961,"range":{"start_line":961,"start_character":27,"end_line":961,"end_character":43},"in_reply_to":"848247d9_57bee9e4","updated":"2026-04-28 23:58:01.000000000","message":"So a new exception perhaps? I mean, the world is way more than just VMs, but the name at least fits. The original context behind that name, maybe no longer fits.\n\nThe reality is we do need something which says \"as a driver, I know this is impossible to continue binding regardless of driver\" PortBindingImpossibleError ?","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"873f4028635dbe804a1dd4981c9eb20f543c3fb3","unresolved":true,"context_lines":[{"line_number":958,"context_line":"                                   \u0027vif_details\u0027: binding.vif_details,"},{"line_number":959,"context_line":"                                   \u0027binding_levels\u0027: context.binding_levels})"},{"line_number":960,"context_line":"                        return True"},{"line_number":961,"context_line":"            except ml2_exc.PortBindingError:"},{"line_number":962,"context_line":"                LOG.error("},{"line_number":963,"context_line":"                    \"Mechanism driver %s determined that port \""},{"line_number":964,"context_line":"                    \"binding cannot succeed, aborting binding\","}],"source_content_type":"text/x-python","patch_set":1,"id":"5f6e5423_f010483e","line":961,"range":{"start_line":961,"start_character":27,"end_line":961,"end_character":43},"in_reply_to":"85b21f5c_d9e4dee3","updated":"2026-04-29 01:57:32.000000000","message":"This is the path I would focus on based on Rodolfo\u0027s comment, seems like there could be a case to be made for stopping completely perhaps.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"cf2905be8d6915021121672a9b1284f216c9af3f","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            except Exception:"},{"line_number":968,"context_line":"                LOG.exception(\"Mechanism driver %s failed in \""},{"line_number":969,"context_line":"                              \"bind_port\","},{"line_number":970,"context_line":"                              driver.name)"},{"line_number":971,"context_line":""},{"line_number":972,"context_line":"    def _infer_driver_from_allocation(self, context):"},{"line_number":973,"context_line":"        \"\"\"Choose mechanism driver as implied by allocation in placement."}],"source_content_type":"text/x-python","patch_set":1,"id":"7af8858e_91801b2b","line":970,"updated":"2026-04-21 23:58:42.000000000","message":"The one thing I can\u0027t figure out is why there isn\u0027t a \u0027return False\u0027 here, outside of the loop. Food for thought for reviewers.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":11655,"name":"Julia Kreger","email":"juliaashleykreger@gmail.com","username":"jkreger","status":"Flying to the moon with a Jetpack!"},"change_message_id":"df6c19ae07555059530eb44edca4df1a8de3b876","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            except Exception:"},{"line_number":968,"context_line":"                LOG.exception(\"Mechanism driver %s failed in \""},{"line_number":969,"context_line":"                              \"bind_port\","},{"line_number":970,"context_line":"                              driver.name)"},{"line_number":971,"context_line":""},{"line_number":972,"context_line":"    def _infer_driver_from_allocation(self, context):"},{"line_number":973,"context_line":"        \"\"\"Choose mechanism driver as implied by allocation in placement."}],"source_content_type":"text/x-python","patch_set":1,"id":"b955c473_b1d44704","line":970,"in_reply_to":"7af8858e_91801b2b","updated":"2026-04-28 23:58:01.000000000","message":"I think it boils down to the base model which is to always try to succeed and assume something might make it work eventually. Depending on the plugin base class, if its agent driven, That code may still run in some cases, but that is far outside the problem space I\u0027ve focused on, I only know the agent mixin has also clouded perceptions in ml2 drivers and the expectation shifts to ensure it in the end.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"},{"author":{"_account_id":1131,"name":"Brian Haley","email":"haleyb.dev@gmail.com","username":"brian-haley"},"change_message_id":"873f4028635dbe804a1dd4981c9eb20f543c3fb3","unresolved":true,"context_lines":[{"line_number":967,"context_line":"            except Exception:"},{"line_number":968,"context_line":"                LOG.exception(\"Mechanism driver %s failed in \""},{"line_number":969,"context_line":"                              \"bind_port\","},{"line_number":970,"context_line":"                              driver.name)"},{"line_number":971,"context_line":""},{"line_number":972,"context_line":"    def _infer_driver_from_allocation(self, context):"},{"line_number":973,"context_line":"        \"\"\"Choose mechanism driver as implied by allocation in placement."}],"source_content_type":"text/x-python","patch_set":1,"id":"49825eeb_aec57253","line":970,"in_reply_to":"b955c473_b1d44704","updated":"2026-04-29 01:57:32.000000000","message":"Well, I can fix this later, callers are treating the return value as a boolean and None is False in that case, probably why it\u0027s never been noticed.","commit_id":"a17c5dd51079c0949e58cb1ab221f452100bfb6b"}]}
