)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This plumbs in the neutron API client side code for creating port"},{"line_number":10,"context_line":"bindings to the destination host during a live migration."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"The port binding extension API calls are based on the extension definition:"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"I431be79975f6fc371822038ed4acdf02e7b8e99b"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":8,"id":"bf659307_d7dcfd47","line":12,"range":{"start_line":12,"start_character":64,"end_line":12,"end_character":74},"updated":"2018-03-26 23:42:04.000000000","message":"wrap","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This plumbs in the neutron API client side code for creating port"},{"line_number":10,"context_line":"bindings to the destination host during a live migration."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"The port binding extension API calls are based on the extension definition:"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"I431be79975f6fc371822038ed4acdf02e7b8e99b"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":12,"id":"bf659307_ed53ad6b","line":12,"range":{"start_line":12,"start_character":72,"end_line":12,"end_character":75},"updated":"2018-04-04 20:34:21.000000000","message":"!","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This plumbs in the neutron API client side code for creating port"},{"line_number":10,"context_line":"bindings to the destination host during a live migration."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"The port binding extension API calls are based on the extension definition:"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"I431be79975f6fc371822038ed4acdf02e7b8e99b"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":18,"id":"5f7c97a3_1c02a770","line":12,"range":{"start_line":12,"start_character":71,"end_line":12,"end_character":75},"updated":"2018-06-18 12:40:11.000000000","message":"nit: long line","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"36a791dd2a24cb5cc19745c636d20cc0999c18c7","unresolved":false,"context_lines":[{"line_number":9,"context_line":"This plumbs in the neutron API client side code for creating port"},{"line_number":10,"context_line":"bindings to the destination host during a live migration."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"The port binding extension API calls are based on the extension definition:"},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"I431be79975f6fc371822038ed4acdf02e7b8e99b"},{"line_number":15,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":18,"id":"5f7c97a3_b74aa058","line":12,"range":{"start_line":12,"start_character":71,"end_line":12,"end_character":75},"in_reply_to":"5f7c97a3_1c02a770","updated":"2018-06-18 21:42:18.000000000","message":"Done","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"}],"nova/network/base_api.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":385,"context_line":""},{"line_number":386,"context_line":"    def bind_ports_to_host(self, context, instance, host,"},{"line_number":387,"context_line":"                           vnic_type\u003dNone, profile\u003dNone):"},{"line_number":388,"context_line":"        \"\"\"Attempts to bind the ports from the instance on the given host"},{"line_number":389,"context_line":""},{"line_number":390,"context_line":"        If the ports are already actively bound to another host, like the"},{"line_number":391,"context_line":"        source host during live migration, then the new port bindings will"}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_77edf1ed","line":388,"updated":"2018-03-26 23:42:04.000000000","message":".","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"}],"nova/network/neutronv2/api.py":[{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"5e891d870fa9326192ed53cf7b0dee5fbb186cdc","unresolved":false,"context_lines":[{"line_number":1124,"context_line":"        :param dest_host: the destination host on which to bind the ports which"},{"line_number":1125,"context_line":"                          are attached to the instance"},{"line_number":1126,"context_line":"        :param vnic_type: optional vnic type string for the destination host"},{"line_number":1127,"context_line":"                          port binding (defaults to \"normal\")"},{"line_number":1128,"context_line":"        :param profile: optional vif profile dict for the destination host port"},{"line_number":1129,"context_line":"                        binding"},{"line_number":1130,"context_line":"        :raises: PortBindingFailed if any of the ports failed to be bound to"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff82abbf_aef13597","line":1127,"range":{"start_line":1127,"start_character":39,"end_line":1127,"end_character":61},"updated":"2017-11-30 00:22:04.000000000","message":"am that is the default in neutron for new port but if the vnic_type is not passed when create a destination binding it should default to the same value as the source node not normal.\n\nsee line 40 of https://review.openstack.org/#/c/414251/33/neutron/services/portbindings_extended/plugin.py","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"22313a14185d82bbf895c6ec45cb8dc16895162a","unresolved":false,"context_lines":[{"line_number":1124,"context_line":"        :param dest_host: the destination host on which to bind the ports which"},{"line_number":1125,"context_line":"                          are attached to the instance"},{"line_number":1126,"context_line":"        :param vnic_type: optional vnic type string for the destination host"},{"line_number":1127,"context_line":"                          port binding (defaults to \"normal\")"},{"line_number":1128,"context_line":"        :param profile: optional vif profile dict for the destination host port"},{"line_number":1129,"context_line":"                        binding"},{"line_number":1130,"context_line":"        :raises: PortBindingFailed if any of the ports failed to be bound to"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_448f6674","line":1127,"range":{"start_line":1127,"start_character":39,"end_line":1127,"end_character":61},"in_reply_to":"ff82abbf_aef13597","updated":"2018-02-22 19:56:35.000000000","message":"\u003e it should default to the same value as the source node not normal.\n\nThis is all handled in neutron, right? So I should just remove this \"defaults to normal\" part of the docstring.","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"5e891d870fa9326192ed53cf7b0dee5fbb186cdc","unresolved":false,"context_lines":[{"line_number":1155,"context_line":"        # port that is bound to the resulting binding so we can rollback in"},{"line_number":1156,"context_line":"        # the event of a failure, or return the results if everything is OK."},{"line_number":1157,"context_line":"        binding \u003d dict(host_id\u003ddest_host)"},{"line_number":1158,"context_line":"        if vnic_type:"},{"line_number":1159,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1160,"context_line":"        if profile:"},{"line_number":1161,"context_line":"            binding[\u0027profile\u0027] \u003d profile"},{"line_number":1162,"context_line":"        data \u003d dict(binding\u003dbinding)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff82abbf_ceb11946","line":1159,"range":{"start_line":1158,"start_character":8,"end_line":1159,"end_character":44},"updated":"2017-11-30 00:22:04.000000000","message":"looking at neutron lib the vnic_type field is changable on the neutron port \n\nhttps://github.com/openstack/neutron-lib/blob/e0cc5efb74b23120a3456e99aaf7c8934b2a0bdd/neutron_lib/api/definitions/portbindings.py#L168-L172\n\nso unless they have someother check to prevent it being chnaged once the port is bound it could consiverable be different then what the vm booted with.\n\nis the intent that we will set the vnic_type back to the vnic_type the port originally had when the vm was booted.\nif so this is good to have if not this is likely not needed.\n\nin general it should be assumed that changing the vnic type may change how the interface is presented within the guest so therefor it is not safe to do during a live migration.\n\nthat said for libvirt/kvm the default vif model is virtio which will be translated to a virtio-net-pci device on the qemu commandline.\n\nso if the source was vnic type normal it may be safe to change to vnic type virtio-forworder.\n\nvnic type macvtap might work too but im more skeptical.\n\ngoing form vnic type direct to say vnic type normal will likely applications or perhaps the kernel in the guest to crash. that said nova does not support livemigration with sriov or sriov atach/detach so it would proably explode before we got that far.\n\nfor completeness we might want to support setting this value but we may want to consider  intoducing a check in the caller of this fuction which would raise an exception fail fast if we detect it has chagned for the current vnic type.","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a68f6c1208aa5ceab9f82a6b5a89d8dd4f625fa0","unresolved":false,"context_lines":[{"line_number":1155,"context_line":"        # port that is bound to the resulting binding so we can rollback in"},{"line_number":1156,"context_line":"        # the event of a failure, or return the results if everything is OK."},{"line_number":1157,"context_line":"        binding \u003d dict(host_id\u003ddest_host)"},{"line_number":1158,"context_line":"        if vnic_type:"},{"line_number":1159,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1160,"context_line":"        if profile:"},{"line_number":1161,"context_line":"            binding[\u0027profile\u0027] \u003d profile"},{"line_number":1162,"context_line":"        data \u003d dict(binding\u003dbinding)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_648b82bf","line":1159,"range":{"start_line":1158,"start_character":8,"end_line":1159,"end_character":44},"in_reply_to":"3fa0c359_84756e66","updated":"2018-02-22 21:14:01.000000000","message":"If you\u0027re just saying that someone could change this out of band from nova using the networking API directly, and nova could have stale information, then, well, I guess we\u0027re f\u0027ed. That would be like changing the type on a volume in Cinder and Cinder not telling nova about it (which is why we have the swap volume API in nova).","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"22313a14185d82bbf895c6ec45cb8dc16895162a","unresolved":false,"context_lines":[{"line_number":1155,"context_line":"        # port that is bound to the resulting binding so we can rollback in"},{"line_number":1156,"context_line":"        # the event of a failure, or return the results if everything is OK."},{"line_number":1157,"context_line":"        binding \u003d dict(host_id\u003ddest_host)"},{"line_number":1158,"context_line":"        if vnic_type:"},{"line_number":1159,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1160,"context_line":"        if profile:"},{"line_number":1161,"context_line":"            binding[\u0027profile\u0027] \u003d profile"},{"line_number":1162,"context_line":"        data \u003d dict(binding\u003dbinding)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_84756e66","line":1159,"range":{"start_line":1158,"start_character":8,"end_line":1159,"end_character":44},"in_reply_to":"ff82abbf_ceb11946","updated":"2018-02-22 19:56:35.000000000","message":"Sean, you\u0027re speaking a whole other language to me here. But:\n\n\u003e in general it should be assumed that changing the vnic type may change how the interface is presented within the guest so therefor it is not safe to do during a live migration.\n\nI thought one of the main points of supporting the port binding API during live migration was so we could also change types during the live migration, i.e. migrate from an OVS to LB or OVN backend and vice versa?\n\nSee the 2nd bullet here:\n\nhttps://specs.openstack.org/openstack/nova-specs/specs/queens/approved/neutron-new-port-binding-api.html#problem-description\n\nAnd the 3rd use case:\n\nhttps://specs.openstack.org/openstack/nova-specs/specs/queens/approved/neutron-new-port-binding-api.html#use-cases","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"5e891d870fa9326192ed53cf7b0dee5fbb186cdc","unresolved":false,"context_lines":[{"line_number":1157,"context_line":"        binding \u003d dict(host_id\u003ddest_host)"},{"line_number":1158,"context_line":"        if vnic_type:"},{"line_number":1159,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1160,"context_line":"        if profile:"},{"line_number":1161,"context_line":"            binding[\u0027profile\u0027] \u003d profile"},{"line_number":1162,"context_line":"        data \u003d dict(binding\u003dbinding)"},{"line_number":1163,"context_line":""},{"line_number":1164,"context_line":"        bindings_by_port_id \u003d {}"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff82abbf_ae7e15ac","line":1161,"range":{"start_line":1160,"start_character":8,"end_line":1161,"end_character":40},"updated":"2017-11-30 00:22:04.000000000","message":"similar to the above the binding profile is also mutable.\nnova only uses it for one thing, sriov passthough.\nwhen you create a neutron port of vnict type\"direct\",\"macvtap\",\"direct_physical\" or \"virtio_forworder\" nova will set the binding profile to contain the pci adress, vendor id and product id of the passthough device so that the neutron sriovnicaget can use this info to wire up the vf/pf.\n\n\nif in the future we support live migration with sriov style devices we will need to update the value with the device detail for the destination host but since nova is not the only thing that can update the binding profile.\ni.e. it allows put in the api https://github.com/openstack/neutron-lib/blob/e0cc5efb74b23120a3456e99aaf7c8934b2a0bdd/neutron_lib/api/definitions/portbindings.py#L177-L181\n\nthat means the caller of this fuction needs to first retrive the current profile form neutron first and then merge the profile with our updates before we write it back to neutron wehn we create the binding. can we document this in the docstring on line 1128.","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"22313a14185d82bbf895c6ec45cb8dc16895162a","unresolved":false,"context_lines":[{"line_number":1157,"context_line":"        binding \u003d dict(host_id\u003ddest_host)"},{"line_number":1158,"context_line":"        if vnic_type:"},{"line_number":1159,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1160,"context_line":"        if profile:"},{"line_number":1161,"context_line":"            binding[\u0027profile\u0027] \u003d profile"},{"line_number":1162,"context_line":"        data \u003d dict(binding\u003dbinding)"},{"line_number":1163,"context_line":""},{"line_number":1164,"context_line":"        bindings_by_port_id \u003d {}"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_e484720d","line":1161,"range":{"start_line":1160,"start_character":8,"end_line":1161,"end_character":40},"in_reply_to":"ff82abbf_ae7e15ac","updated":"2018-02-22 19:56:35.000000000","message":"\u003e if in the future we support live migration with sriov style devices\n\nI\u0027m pretty sure that\u0027s something people have complained about us *not* yet supporting for a long time, cfriesen would know the details.\n\n\u003e that means the caller of this fuction needs to first retrive the current profile form neutron first and then merge the profile with our updates before we write it back to neutron wehn we create the binding.\n\nNova builds the network info cache information prior to starting live migration, and we have the heal_instance_info_cache periodic task, so the port binding profile information should already be stored in nova when we start the live migration, so I\u0027m not sure what we actually need here. Yes the caller would have to be sure that it has a recent version of the binding profile so it doesn\u0027t overwrite stuff, but without etags or a generation id on the binding profile, there is really nothing nova can do about a race to update the binding profile from different consumers of the neutron API.","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":11604,"name":"sean mooney","email":"smooney@redhat.com","username":"sean-k-mooney"},"change_message_id":"5e891d870fa9326192ed53cf7b0dee5fbb186cdc","unresolved":false,"context_lines":[{"line_number":1175,"context_line":"                          port_id, dest_host, resp.status_code, resp.text,"},{"line_number":1176,"context_line":"                          instance\u003dinstance)"},{"line_number":1177,"context_line":"                # TODO(mriedem): move this cleanup code to a separate method"},{"line_number":1178,"context_line":"                for rollback_port_id in bindings_by_port_id:"},{"line_number":1179,"context_line":"                    url \u003d \u0027/v2.0/ports/%s/bindings/%s\u0027 % ("},{"line_number":1180,"context_line":"                        rollback_port_id, dest_host)"},{"line_number":1181,"context_line":"                    resp \u003d client.delete(url, raise_exc\u003dFalse)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff82abbf_29dbdf4e","line":1178,"range":{"start_line":1178,"start_character":16,"end_line":1178,"end_character":59},"updated":"2017-11-30 00:22:04.000000000","message":"hum i had expect this to iterate over the values of the dict instead of the keys but it works so i guess its fine.\n\ni was going to suggest bindings_by_port_id.keys() but i guess not using .keys() is more pythonic even if its unintuitive at first.","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"e75ddd138b720f824d95d8aa7ee05cdfc979cc8d","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"                        rollback_port_id, dest_host)"},{"line_number":1181,"context_line":"                    resp \u003d client.delete(url, raise_exc\u003dFalse)"},{"line_number":1182,"context_line":"                    if resp.status_code \u003e\u003d 400 and resp.status_code !\u003d 404:"},{"line_number":1183,"context_line":"                        LOG.warning(\u0027Failed to remove binding for port %s on \u0027"},{"line_number":1184,"context_line":"                                    \u0027host %s: (%s %s)\u0027, rollback_port_id,"},{"line_number":1185,"context_line":"                                    dest_host, resp.status_code, resp.text)"},{"line_number":1186,"context_line":"                raise exception.PortBindingFailed(port_id\u003dport_id)"}],"source_content_type":"text/x-python","patch_set":1,"id":"ff82abbf_925596fc","line":1183,"range":{"start_line":1183,"start_character":28,"end_line":1183,"end_character":35},"updated":"2017-11-28 23:32:58.000000000","message":"include the instance\u003dinstance kwarg here for context","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"22313a14185d82bbf895c6ec45cb8dc16895162a","unresolved":false,"context_lines":[{"line_number":1180,"context_line":"                        rollback_port_id, dest_host)"},{"line_number":1181,"context_line":"                    resp \u003d client.delete(url, raise_exc\u003dFalse)"},{"line_number":1182,"context_line":"                    if resp.status_code \u003e\u003d 400 and resp.status_code !\u003d 404:"},{"line_number":1183,"context_line":"                        LOG.warning(\u0027Failed to remove binding for port %s on \u0027"},{"line_number":1184,"context_line":"                                    \u0027host %s: (%s %s)\u0027, rollback_port_id,"},{"line_number":1185,"context_line":"                                    dest_host, resp.status_code, resp.text)"},{"line_number":1186,"context_line":"                raise exception.PortBindingFailed(port_id\u003dport_id)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3fa0c359_64706241","line":1183,"range":{"start_line":1183,"start_character":28,"end_line":1183,"end_character":35},"in_reply_to":"ff82abbf_925596fc","updated":"2018-02-22 19:56:35.000000000","message":"Done","commit_id":"f50951af013e4fab1778b15baa1e695f890deec3"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a68f6c1208aa5ceab9f82a6b5a89d8dd4f625fa0","unresolved":false,"context_lines":[{"line_number":1156,"context_line":"                        via the networking \"Port Binding\" API so callers that"},{"line_number":1157,"context_line":"                        pass in a profile should ensure they have the latest"},{"line_number":1158,"context_line":"                        version from neutron with their changes merged,"},{"line_number":1159,"context_line":"                        although without etags or a generation id on the"},{"line_number":1160,"context_line":"                        port itself we cannot guarantee the profile is the"},{"line_number":1161,"context_line":"                        \"latest\""},{"line_number":1162,"context_line":"        :raises: PortBindingFailed if any of the ports failed to be bound to"},{"line_number":1163,"context_line":"                 the destination host"},{"line_number":1164,"context_line":"        :returns: dict, keyed by port ID, of a new destination host port"}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa0c359_0a3967a2","line":1161,"range":{"start_line":1159,"start_character":24,"end_line":1161,"end_character":32},"updated":"2018-02-22 21:14:01.000000000","message":"Apparently ports have a revision_number, which is like a generation id:\n\n(3:06:51 PM) mlavalle: mriedem: we have revision number for ports: http://paste.openstack.org/show/682493/\n(3:07:25 PM) mlavalle: revision numbers apply to a number of Neutron resources, ports among them\n(3:09:14 PM) mlavalle: this is the extension definition: https://github.com/openstack/neutron/blob/master/neutron/extensions/revisions.py\n(3:10:17 PM) mlavalle: and this is the plugin that implemenents it: https://github.com/openstack/neutron/blob/master/neutron/services/revisions/revision_plugin.py\n(3:12:38 PM) mriedem: hmm,\n(3:12:43 PM) mlavalle: and if you change the port binding, that is going to revise the port: https://github.com/openstack/neutron/blob/master/neutron/plugins/ml2/models.py#L63\n(3:12:48 PM) mriedem: does that get updated when binding_profile is updated?\n(3:13:00 PM) mriedem: oh nice","commit_id":"ab8f8cfa9c9018a3a7aabb35788dede3f51e104c"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6c7dc5d06cb3609bd725797ad69f147613f39c2e","unresolved":false,"context_lines":[{"line_number":1174,"context_line":"        if not port_ids:"},{"line_number":1175,"context_line":"            # The instance doesn\u0027t have any ports so there is nothing to do."},{"line_number":1176,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1177,"context_line":"            return"},{"line_number":1178,"context_line":""},{"line_number":1179,"context_line":"        # TODO(mriedem): Replace this with using python-neutronclient if/when"},{"line_number":1180,"context_line":"        # the binding-extended support is in there."}],"source_content_type":"text/x-python","patch_set":2,"id":"3fa0c359_ad664dec","line":1177,"updated":"2018-02-22 22:04:52.000000000","message":"This should return an empty dict so conductor doesn\u0027t need to worry about checking for None.","commit_id":"ab8f8cfa9c9018a3a7aabb35788dede3f51e104c"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"da5cc0154a6353b22a77d4ec89d4e13929c68b80","unresolved":false,"context_lines":[{"line_number":1203,"context_line":"            else:"},{"line_number":1204,"context_line":"                # Something failed, so log the error and rollback any"},{"line_number":1205,"context_line":"                # successful bindings."},{"line_number":1206,"context_line":"                LOG.error(\u0027Binding failed for port %s and host %s. \u0027"},{"line_number":1207,"context_line":"                          \u0027Error: (%s %s)\u0027,"},{"line_number":1208,"context_line":"                          port_id, dest_host, resp.status_code, resp.text,"},{"line_number":1209,"context_line":"                          instance\u003dinstance)"}],"source_content_type":"text/x-python","patch_set":3,"id":"df7087c5_237363b3","line":1206,"updated":"2018-03-13 15:34:04.000000000","message":"Getting a 400 error:\n\nhttp://logs.openstack.org/73/552173/1/check/legacy-tempest-dsvm-multinode-live-migration/b073f08/logs/screen-n-super-cond.txt.gz?level\u003dTRACE#_Mar_12_23_58_36_252039\n\nMar 12 23:58:36.252039 ubuntu-xenial-rax-dfw-0002912498 nova-conductor[29779]: ERROR nova.network.neutronv2.api [None req-806addb4-7547-4df1-8d7a-0b3c9e9b13cb tempest-LiveAutoBlockMigrationV225Test-1556915662 tempest-LiveAutoBlockMigrationV225Test-1556915662] [instance: b093da27-37f0-49da-a2c2-d66cffced86a] Binding failed for port f8890e4c-6cb5-4c24-b352-af4510f0db55 and host ubuntu-xenial-rax-dfw-0002912501. Error: (400 {\"NeutronError\": {\"message\": \"Unrecognized attribute(s) \u0027host_id\u0027\", \"type\": \"HTTPBadRequest\", \"detail\": \"\"}})\n\nI guess it\u0027s \u0027host\u0027 rather than \u0027host_id\u0027 which is what the spec said:\n\nhttps://github.com/openstack/neutron-lib/blob/master/neutron_lib/api/definitions/portbindings_extended.py#L57\n\nhttps://specs.openstack.org/openstack/neutron-specs/specs/backlog/pike/portbinding_information_for_nova.html#create-binding","commit_id":"710eb92c6ed99945aa12b8cfe68c22f5331ff596"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6a88e5c78eadc63aae7ff02805076b8714ba9a90","unresolved":false,"context_lines":[{"line_number":1131,"context_line":"        self._refresh_neutron_extensions_cache(context)"},{"line_number":1132,"context_line":"        return constants.PORT_BINDING_EXTENDED in self.extensions"},{"line_number":1133,"context_line":""},{"line_number":1134,"context_line":"    def bind_ports_to_destination_host(self, context, instance, dest_host,"},{"line_number":1135,"context_line":"                                       vnic_type\u003dNone, profile\u003dNone):"},{"line_number":1136,"context_line":"        \"\"\"Attempts to bind the ports from the instance on the destination host"},{"line_number":1137,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"df7087c5_bfc448f6","line":1134,"range":{"start_line":1134,"start_character":8,"end_line":1134,"end_character":38},"updated":"2018-03-14 16:27:23.000000000","message":"This method name is a bit specific for something that is really pretty generic, so maybe it should just be \"bind_ports_to_host\". Whether it\u0027s a destination host or not doesn\u0027t really matter, and in a sense couples it to it\u0027s intended usage in certain operations, like live migration.","commit_id":"6ac6eb77520a391af87139c6a579445d4042e0c4"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"81b6c451220872a9fca97df42a1e4ad34e097d08","unresolved":false,"context_lines":[{"line_number":1131,"context_line":"        self._refresh_neutron_extensions_cache(context)"},{"line_number":1132,"context_line":"        return constants.PORT_BINDING_EXTENDED in self.extensions"},{"line_number":1133,"context_line":""},{"line_number":1134,"context_line":"    def bind_ports_to_destination_host(self, context, instance, dest_host,"},{"line_number":1135,"context_line":"                                       vnic_type\u003dNone, profile\u003dNone):"},{"line_number":1136,"context_line":"        \"\"\"Attempts to bind the ports from the instance on the destination host"},{"line_number":1137,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"df7087c5_69cc7634","line":1134,"range":{"start_line":1134,"start_character":8,"end_line":1134,"end_character":38},"in_reply_to":"df7087c5_bfc448f6","updated":"2018-03-16 18:36:09.000000000","message":"Done","commit_id":"6ac6eb77520a391af87139c6a579445d4042e0c4"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"6ff3a6586f72f43ffb1a3ec57cac9a358f5db535","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        In the event of an error, any ports which were successfully bound to"},{"line_number":1148,"context_line":"        the host should have those host bindings removed from the ports."},{"line_number":1149,"context_line":""},{"line_number":1150,"context_line":"        This method should not be used if \"supports_port_binding_extension\""},{"line_number":1151,"context_line":"        returns False."},{"line_number":1152,"context_line":""},{"line_number":1153,"context_line":"        :param context: the user request context"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf659307_8f94428d","line":1150,"updated":"2018-03-26 12:33:19.000000000","message":"Hum... This method has a strong dependency with port binding extension. I think we should have a check inside the function and raise an exception if not present.\n\nThe problem is our design about how we handle extension, we should extend the API for each extension instead of adding methods.","commit_id":"e15816767d977d0b3769014eb4a46572c52e5f54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"b2e303c9cbbbc3a6390b08595e6bf28ef0836c45","unresolved":false,"context_lines":[{"line_number":1147,"context_line":"        In the event of an error, any ports which were successfully bound to"},{"line_number":1148,"context_line":"        the host should have those host bindings removed from the ports."},{"line_number":1149,"context_line":""},{"line_number":1150,"context_line":"        This method should not be used if \"supports_port_binding_extension\""},{"line_number":1151,"context_line":"        returns False."},{"line_number":1152,"context_line":""},{"line_number":1153,"context_line":"        :param context: the user request context"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf659307_40a91779","line":1150,"in_reply_to":"bf659307_8f94428d","updated":"2018-03-26 13:50:08.000000000","message":"If we raise an exception out of this method, then every caller has to handle that and do whatever other logic we have today. I\u0027m not a big fan of exception-based flow control which is likely why I did it this way (if you look at the conductor patch toward the end of the series that relies on this). Also, I\u0027m trying to follow a similar pattern for the volume multiattach logic in the controller services (nova-api for multiattach, where we check the new-style bdm.attachment_id).","commit_id":"e15816767d977d0b3769014eb4a46572c52e5f54"},{"author":{"_account_id":7730,"name":"Sahid Orentino Ferdjaoui","email":"sahid.ferdjaoui@industrialdiscipline.com","username":"sahid"},"change_message_id":"6ff3a6586f72f43ffb1a3ec57cac9a358f5db535","unresolved":false,"context_lines":[{"line_number":1174,"context_line":"                  binding dict per port that was bound"},{"line_number":1175,"context_line":"        \"\"\""},{"line_number":1176,"context_line":"        # Get the current ports off the instance."},{"line_number":1177,"context_line":"        # TODO(mriedem): Should we get the latest from neutron instead of our"},{"line_number":1178,"context_line":"        # cache?"},{"line_number":1179,"context_line":"        network_info \u003d instance.get_network_info()"},{"line_number":1180,"context_line":"        port_ids \u003d [vif[\u0027id\u0027] for vif in network_info]"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf659307_af5b4685","line":1177,"updated":"2018-03-26 12:33:19.000000000","message":"Yeah that looks important to ensure that we run with updated data.","commit_id":"e15816767d977d0b3769014eb4a46572c52e5f54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5ac5fc37ea8b22572fddc1afaea45b9e985e4c82","unresolved":false,"context_lines":[{"line_number":1174,"context_line":"                  binding dict per port that was bound"},{"line_number":1175,"context_line":"        \"\"\""},{"line_number":1176,"context_line":"        # Get the current ports off the instance."},{"line_number":1177,"context_line":"        # TODO(mriedem): Should we get the latest from neutron instead of our"},{"line_number":1178,"context_line":"        # cache?"},{"line_number":1179,"context_line":"        network_info \u003d instance.get_network_info()"},{"line_number":1180,"context_line":"        port_ids \u003d [vif[\u0027id\u0027] for vif in network_info]"}],"source_content_type":"text/x-python","patch_set":7,"id":"bf659307_5ac33fee","line":1177,"in_reply_to":"bf659307_af5b4685","updated":"2018-03-27 01:01:45.000000000","message":"But that argument can be made everywhere really, and if so, then what is the point in our cache? If you think of the network info cache for ports the same way as BDMs, they are really the same thing - nova\u0027s internal store for modeling something that\u0027s actually in another service. We don\u0027t refresh BDMs nearly as much as we do ports, so I\u0027m inclined to just leave this unless it becomes a problem.","commit_id":"e15816767d977d0b3769014eb4a46572c52e5f54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"daac824c8d5c647a8e240b2dd12756b6d9e010db","unresolved":false,"context_lines":[{"line_number":1200,"context_line":"        for port_id in port_ids:"},{"line_number":1201,"context_line":"            resp \u003d client.post(\u0027/ports/%s/bindings\u0027 % port_id, data)"},{"line_number":1202,"context_line":"            if resp:"},{"line_number":1203,"context_line":"                bindings_by_port_id[port_id] \u003d resp.json()[\u0027binding\u0027]"},{"line_number":1204,"context_line":"            else:"},{"line_number":1205,"context_line":"                # Something failed, so log the error and rollback any"},{"line_number":1206,"context_line":"                # successful bindings."}],"source_content_type":"text/x-python","patch_set":7,"id":"bf659307_26d19c55","line":1203,"range":{"start_line":1203,"start_character":52,"end_line":1203,"end_character":58},"updated":"2018-03-26 14:16:13.000000000","message":"This goes away now since we\u0027re using neutronclient:\n\nhttp://logs.openstack.org/73/552173/7/check/legacy-tempest-dsvm-multinode-live-migration/2ce0f4e/logs/screen-n-super-cond.txt.gz?level\u003dTRACE#_Mar_26_02_02_45_406676\n\nMar 26 02:02:45.411889 ubuntu-xenial-rax-iad-0003181552 nova-conductor[30124]: ERROR nova.conductor.manager   File \"/opt/stack/new/nova/nova/network/neutronv2/api.py\", line 1225, in bind_ports_to_host\nMar 26 02:02:45.412174 ubuntu-xenial-rax-iad-0003181552 nova-conductor[30124]: ERROR nova.conductor.manager     bindings_by_port_id[port_id] \u003d resp.json()[\u0027binding\u0027]\nMar 26 02:02:45.412461 ubuntu-xenial-rax-iad-0003181552 nova-conductor[30124]: ERROR nova.conductor.manager AttributeError: \u0027_DictWithMeta\u0027 object has no attribute \u0027json\u0027\nMar 26 02:02:45.412728 ubuntu-xenial-rax-iad-0003181552 nova-conductor[30124]: ERROR nova.conductor.manager","commit_id":"e15816767d977d0b3769014eb4a46572c52e5f54"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":1199,"context_line":"        bindings_by_port_id \u003d {}"},{"line_number":1200,"context_line":"        for port_id in port_ids:"},{"line_number":1201,"context_line":"            resp \u003d client.post(\u0027/ports/%s/bindings\u0027 % port_id, data)"},{"line_number":1202,"context_line":"            if resp:"},{"line_number":1203,"context_line":"                bindings_by_port_id[port_id] \u003d resp[\u0027binding\u0027]"},{"line_number":1204,"context_line":"            else:"},{"line_number":1205,"context_line":"                # Something failed, so log the error and rollback any"}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_57f30d9f","line":1202,"range":{"start_line":1202,"start_character":15,"end_line":1202,"end_character":19},"updated":"2018-03-26 23:42:04.000000000","message":"As we found out earlier, this is not a Response, but is a decoded version of the response payload.\n\nPawing through the neutron client code, I\u0027m pretty sure .post will raise an exception on failure.","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5ac5fc37ea8b22572fddc1afaea45b9e985e4c82","unresolved":false,"context_lines":[{"line_number":1199,"context_line":"        bindings_by_port_id \u003d {}"},{"line_number":1200,"context_line":"        for port_id in port_ids:"},{"line_number":1201,"context_line":"            resp \u003d client.post(\u0027/ports/%s/bindings\u0027 % port_id, data)"},{"line_number":1202,"context_line":"            if resp:"},{"line_number":1203,"context_line":"                bindings_by_port_id[port_id] \u003d resp[\u0027binding\u0027]"},{"line_number":1204,"context_line":"            else:"},{"line_number":1205,"context_line":"                # Something failed, so log the error and rollback any"}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_c002f609","line":1202,"range":{"start_line":1202,"start_character":15,"end_line":1202,"end_character":19},"in_reply_to":"bf659307_57f30d9f","updated":"2018-03-27 01:01:45.000000000","message":"\u003e As we found out earlier, this is not a Response, but is a decoded\n \u003e version of the response payload.\n \u003e \n \u003e Pawing through the neutron client code, I\u0027m pretty sure .post will\n \u003e raise an exception on failure.\n\nUgh, well that sucks, and gives me half a mind to want to go back to just using KSA for this so I can control the error flow and just check status codes.","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":1208,"context_line":"                          \u0027Error: (%s %s)\u0027,"},{"line_number":1209,"context_line":"                          port_id, host, resp.status_code, resp.text,"},{"line_number":1210,"context_line":"                          instance\u003dinstance)"},{"line_number":1211,"context_line":"                # TODO(mriedem): move this cleanup code to a separate method"},{"line_number":1212,"context_line":"                for rollback_port_id in bindings_by_port_id:"},{"line_number":1213,"context_line":"                    url \u003d \u0027/ports/%s/bindings/%s\u0027 % (rollback_port_id, host)"},{"line_number":1214,"context_line":"                    resp \u003d client.delete(url)"}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_97944546","line":1211,"range":{"start_line":1211,"start_character":18,"end_line":1211,"end_character":76},"updated":"2018-03-26 23:42:04.000000000","message":"Or use taskflow :)","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"962576404974064b26919072f9ec9a7ba3494705","unresolved":false,"context_lines":[{"line_number":1220,"context_line":""},{"line_number":1221,"context_line":"        bindings_by_port_id \u003d {}"},{"line_number":1222,"context_line":"        for port_id in port_ids:"},{"line_number":1223,"context_line":"            resp \u003d client.post(\u0027/ports/%s/bindings\u0027 % port_id,"},{"line_number":1224,"context_line":"                               json\u003ddata, raise_exc\u003dFalse)"},{"line_number":1225,"context_line":"            if resp:"},{"line_number":1226,"context_line":"                bindings_by_port_id[port_id] \u003d resp.json()[\u0027binding\u0027]"}],"source_content_type":"text/x-python","patch_set":10,"id":"bf659307_70da624b","line":1223,"updated":"2018-03-30 23:29:37.000000000","message":"Need to prefix with /v2.0/","commit_id":"68e1f32609a530b2228c521dcf40ea9a9df039d3"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"9d1f7ea012eecaab676b24c516453e3c40006773","unresolved":false,"context_lines":[{"line_number":203,"context_line":"        existing auth_token in the context (the user token)."},{"line_number":204,"context_line":"    :returns: keystoneauth1 Adapter object"},{"line_number":205,"context_line":"    \"\"\""},{"line_number":206,"context_line":"    # Assume that these globals are already set from earlier get_client usage."},{"line_number":207,"context_line":"    global _ADMIN_AUTH"},{"line_number":208,"context_line":"    global _SESSION"},{"line_number":209,"context_line":"    if admin:"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_76433714","line":206,"range":{"start_line":206,"start_character":4,"end_line":206,"end_character":78},"updated":"2018-03-31 17:09:08.000000000","message":"That seems dangerous.  Prefer to factor out L142-162 to common code.","commit_id":"7f28034b4b4643a62ea6f8fac7af1a8d3341fdaf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"ace48a190543d699e21d5ff5ffff6eb70d3143ea","unresolved":false,"context_lines":[{"line_number":203,"context_line":"        existing auth_token in the context (the user token)."},{"line_number":204,"context_line":"    :returns: keystoneauth1 Adapter object"},{"line_number":205,"context_line":"    \"\"\""},{"line_number":206,"context_line":"    # Assume that these globals are already set from earlier get_client usage."},{"line_number":207,"context_line":"    global _ADMIN_AUTH"},{"line_number":208,"context_line":"    global _SESSION"},{"line_number":209,"context_line":"    if admin:"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_c28efd77","line":206,"range":{"start_line":206,"start_character":4,"end_line":206,"end_character":78},"in_reply_to":"bf659307_76433714","updated":"2018-04-01 14:13:21.000000000","message":"Will refactor.","commit_id":"7f28034b4b4643a62ea6f8fac7af1a8d3341fdaf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3b9fb2395086b6177a67567798fd7145d53d5814","unresolved":false,"context_lines":[{"line_number":203,"context_line":"        existing auth_token in the context (the user token)."},{"line_number":204,"context_line":"    :returns: keystoneauth1 Adapter object"},{"line_number":205,"context_line":"    \"\"\""},{"line_number":206,"context_line":"    # Assume that these globals are already set from earlier get_client usage."},{"line_number":207,"context_line":"    global _ADMIN_AUTH"},{"line_number":208,"context_line":"    global _SESSION"},{"line_number":209,"context_line":"    if admin:"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_aa8a8260","line":206,"range":{"start_line":206,"start_character":4,"end_line":206,"end_character":78},"in_reply_to":"bf659307_c28efd77","updated":"2018-04-04 14:25:54.000000000","message":"Done","commit_id":"7f28034b4b4643a62ea6f8fac7af1a8d3341fdaf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":134,"context_line":"        return wrapper"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"def _get_auth_plugin(context, admin\u003dFalse):"},{"line_number":138,"context_line":"    # NOTE(dprince): In the case where no auth_token is present we allow use of"},{"line_number":139,"context_line":"    # neutron admin tenant credentials if it is an admin context.  This is to"},{"line_number":140,"context_line":"    # support some services (metadata API) where an admin context is used"},{"line_number":141,"context_line":"    # without an auth token."},{"line_number":142,"context_line":"    global _ADMIN_AUTH"},{"line_number":143,"context_line":"    if admin or (context.is_admin and not context.auth_token):"},{"line_number":144,"context_line":"        if not _ADMIN_AUTH:"},{"line_number":145,"context_line":"            _ADMIN_AUTH \u003d _load_auth_plugin(CONF)"},{"line_number":146,"context_line":"        return _ADMIN_AUTH"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    if context.auth_token:"},{"line_number":149,"context_line":"        return service_auth.get_auth_plugin(context)"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # We did not get a user token and we should not be using"},{"line_number":152,"context_line":"    # an admin token so log an error"},{"line_number":153,"context_line":"    raise exception.Unauthorized()"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"def _get_session():"}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_2d0c4593","line":153,"range":{"start_line":137,"start_character":0,"end_line":153,"end_character":34},"updated":"2018-04-04 20:34:21.000000000","message":"we\u0027re starting to do this frequently enough that we should move it to utils.  Any reason _ADMIN_AUTH couldn\u0027t be globally global?","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"43db889de2a3df501a3249218b7a82326a6dcd53","unresolved":false,"context_lines":[{"line_number":134,"context_line":"        return wrapper"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"def _get_auth_plugin(context, admin\u003dFalse):"},{"line_number":138,"context_line":"    # NOTE(dprince): In the case where no auth_token is present we allow use of"},{"line_number":139,"context_line":"    # neutron admin tenant credentials if it is an admin context.  This is to"},{"line_number":140,"context_line":"    # support some services (metadata API) where an admin context is used"},{"line_number":141,"context_line":"    # without an auth token."},{"line_number":142,"context_line":"    global _ADMIN_AUTH"},{"line_number":143,"context_line":"    if admin or (context.is_admin and not context.auth_token):"},{"line_number":144,"context_line":"        if not _ADMIN_AUTH:"},{"line_number":145,"context_line":"            _ADMIN_AUTH \u003d _load_auth_plugin(CONF)"},{"line_number":146,"context_line":"        return _ADMIN_AUTH"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    if context.auth_token:"},{"line_number":149,"context_line":"        return service_auth.get_auth_plugin(context)"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # We did not get a user token and we should not be using"},{"line_number":152,"context_line":"    # an admin token so log an error"},{"line_number":153,"context_line":"    raise exception.Unauthorized()"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"def _get_session():"}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_d5b3cb4c","line":153,"range":{"start_line":137,"start_character":0,"end_line":153,"end_character":34},"in_reply_to":"bf659307_2d0c4593","updated":"2018-04-04 22:06:25.000000000","message":"Because in this case it\u0027s specific to the [network] section of the config file, right?","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"3ec9dc6b1e6a4b9062b0947337202496e125b093","unresolved":false,"context_lines":[{"line_number":134,"context_line":"        return wrapper"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"def _get_auth_plugin(context, admin\u003dFalse):"},{"line_number":138,"context_line":"    # NOTE(dprince): In the case where no auth_token is present we allow use of"},{"line_number":139,"context_line":"    # neutron admin tenant credentials if it is an admin context.  This is to"},{"line_number":140,"context_line":"    # support some services (metadata API) where an admin context is used"},{"line_number":141,"context_line":"    # without an auth token."},{"line_number":142,"context_line":"    global _ADMIN_AUTH"},{"line_number":143,"context_line":"    if admin or (context.is_admin and not context.auth_token):"},{"line_number":144,"context_line":"        if not _ADMIN_AUTH:"},{"line_number":145,"context_line":"            _ADMIN_AUTH \u003d _load_auth_plugin(CONF)"},{"line_number":146,"context_line":"        return _ADMIN_AUTH"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    if context.auth_token:"},{"line_number":149,"context_line":"        return service_auth.get_auth_plugin(context)"},{"line_number":150,"context_line":""},{"line_number":151,"context_line":"    # We did not get a user token and we should not be using"},{"line_number":152,"context_line":"    # an admin token so log an error"},{"line_number":153,"context_line":"    raise exception.Unauthorized()"},{"line_number":154,"context_line":""},{"line_number":155,"context_line":""},{"line_number":156,"context_line":"def _get_session():"}],"source_content_type":"text/x-python","patch_set":12,"id":"5f7c97a3_91083827","line":153,"range":{"start_line":137,"start_character":0,"end_line":153,"end_character":34},"in_reply_to":"bf659307_d5b3cb4c","updated":"2018-06-13 12:54:22.000000000","message":"Yup, I see that now.  Ignore April me.  (Definitely don\u0027t make a global dict, keyed by conf section, of admin auth plugins.)","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":210,"context_line":"    session \u003d _get_session()"},{"line_number":211,"context_line":"    client \u003d utils.get_ksa_adapter("},{"line_number":212,"context_line":"        \u0027network\u0027, ksa_auth\u003dauth_plugin, ksa_session\u003dsession)"},{"line_number":213,"context_line":"    client.additional_headers \u003d {\u0027accept\u0027: \u0027application/json\u0027}"},{"line_number":214,"context_line":"    return client"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_2dcf652a","line":213,"range":{"start_line":213,"start_character":4,"end_line":213,"end_character":29},"updated":"2018-04-04 20:34:21.000000000","message":"mm, maybe get_ksa_adapter needs to take kwargs.","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":1205,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1206,"context_line":"            return"},{"line_number":1207,"context_line":""},{"line_number":1208,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1209,"context_line":""},{"line_number":1210,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1211,"context_line":"        # port that is bound to the resulting binding so we can rollback in"}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_4dd419be","line":1208,"range":{"start_line":1208,"start_character":8,"end_line":1208,"end_character":53},"updated":"2018-04-04 20:34:21.000000000","message":"Weird (but harmless) that this is done here rather than after the next chunk.","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":1235,"context_line":"                    url \u003d \u0027/v2.0/ports/%s/bindings/%s\u0027 % ("},{"line_number":1236,"context_line":"                        rollback_port_id, host)"},{"line_number":1237,"context_line":"                    resp \u003d client.delete(url, raise_exc\u003dFalse)"},{"line_number":1238,"context_line":"                    if resp.status_code \u003e\u003d 400 and resp.status_code !\u003d 404:"},{"line_number":1239,"context_line":"                        LOG.warning(\u0027Failed to remove binding for port %s on \u0027"},{"line_number":1240,"context_line":"                                    \u0027host %s: (%s %s)\u0027, rollback_port_id,"},{"line_number":1241,"context_line":"                                    host, resp.status_code, resp.text,"}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_6deebd8c","line":1238,"range":{"start_line":1238,"start_character":23,"end_line":1238,"end_character":46},"updated":"2018-04-04 20:34:21.000000000","message":"or just `resp`","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":1213,"context_line":"        if not port_ids:"},{"line_number":1214,"context_line":"            # The instance doesn\u0027t have any ports so there is nothing to do."},{"line_number":1215,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1216,"context_line":"            return"},{"line_number":1217,"context_line":""},{"line_number":1218,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1219,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_d03ad3c2","line":1216,"updated":"2018-06-18 12:40:11.000000000","message":"I think {} would be a more natural return value as this function promise to return the bindings for each port of the instance.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"36a791dd2a24cb5cc19745c636d20cc0999c18c7","unresolved":false,"context_lines":[{"line_number":1213,"context_line":"        if not port_ids:"},{"line_number":1214,"context_line":"            # The instance doesn\u0027t have any ports so there is nothing to do."},{"line_number":1215,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1216,"context_line":"            return"},{"line_number":1217,"context_line":""},{"line_number":1218,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1219,"context_line":""}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_d7e95c19","line":1216,"in_reply_to":"5f7c97a3_d03ad3c2","updated":"2018-06-18 21:42:18.000000000","message":"Yeah, just an oversight, and I actually thought I was handling None in conductor where this is called but apparently I\u0027m not:\n\nhttps://review.openstack.org/#/c/522537/28/nova/conductor/tasks/live_migrate.py@278","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":1215,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1216,"context_line":"            return"},{"line_number":1217,"context_line":""},{"line_number":1218,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1219,"context_line":""},{"line_number":1220,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1221,"context_line":"        # port that is bound to the resulting binding so we can rollback in"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_7ce15b9b","line":1218,"updated":"2018-06-18 12:40:11.000000000","message":"I would put a TODO here to change this to a get_client call when the neutron python binding support binding to host.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e1cf4cc0c826ff0124800740f5f329340c295cb3","unresolved":false,"context_lines":[{"line_number":1215,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1216,"context_line":"            return"},{"line_number":1217,"context_line":""},{"line_number":1218,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1219,"context_line":""},{"line_number":1220,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1221,"context_line":"        # port that is bound to the resulting binding so we can rollback in"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_b5c4ae42","line":1218,"in_reply_to":"5f7c97a3_3771b078","updated":"2018-06-20 10:55:38.000000000","message":"OK, then I misunderstood the commit message. I felt that it is a temporary solution. But I can accept that we start using KSA everywhere to have less dependencies.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"36a791dd2a24cb5cc19745c636d20cc0999c18c7","unresolved":false,"context_lines":[{"line_number":1215,"context_line":"            LOG.debug(\u0027Instance does not have any ports.\u0027, instance\u003dinstance)"},{"line_number":1216,"context_line":"            return"},{"line_number":1217,"context_line":""},{"line_number":1218,"context_line":"        client \u003d _get_ksa_client(context, admin\u003dTrue)"},{"line_number":1219,"context_line":""},{"line_number":1220,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1221,"context_line":"        # port that is bound to the resulting binding so we can rollback in"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_3771b078","line":1218,"in_reply_to":"5f7c97a3_7ce15b9b","updated":"2018-06-18 21:42:18.000000000","message":"I\u0027m not really sure we should do that, since it would be nice to just use pure requests using KSA if we can, then we limit our dependency on python-neutronclient (or other SDK) changes. Some would argue this is the long-term direction we should be going with all calls to other services, we just did it purely with Placement to start.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":1220,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1221,"context_line":"        # port that is bound to the resulting binding so we can rollback in"},{"line_number":1222,"context_line":"        # the event of a failure, or return the results if everything is OK."},{"line_number":1223,"context_line":"        binding \u003d dict(host\u003dhost)"},{"line_number":1224,"context_line":"        if vnic_type:"},{"line_number":1225,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1226,"context_line":"        if profile:"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_3c2e83ab","line":1223,"range":{"start_line":1223,"start_character":8,"end_line":1223,"end_character":33},"updated":"2018-06-18 12:40:11.000000000","message":"based on the spec [1] this should be \n\n    binding \u003d dict(host_id\u003dhost)\n\n[1] https://specs.openstack.org/openstack/neutron-specs/specs/pike/portbinding_information_for_nova.html#create-binding\n\n[later]\n\nBut based on the implementation it is \u0027host\u0027\n\nhttps://review.openstack.org/#/c/484389/8/neutron_lib/api/definitions/portbindings_extended.py@58","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"36a791dd2a24cb5cc19745c636d20cc0999c18c7","unresolved":false,"context_lines":[{"line_number":1220,"context_line":"        # Now bind each port to the destination host and keep track of each"},{"line_number":1221,"context_line":"        # port that is bound to the resulting binding so we can rollback in"},{"line_number":1222,"context_line":"        # the event of a failure, or return the results if everything is OK."},{"line_number":1223,"context_line":"        binding \u003d dict(host\u003dhost)"},{"line_number":1224,"context_line":"        if vnic_type:"},{"line_number":1225,"context_line":"            binding[\u0027vnic_type\u0027] \u003d vnic_type"},{"line_number":1226,"context_line":"        if profile:"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_970f64df","line":1223,"range":{"start_line":1223,"start_character":8,"end_line":1223,"end_character":33},"in_reply_to":"5f7c97a3_3c2e83ab","updated":"2018-06-18 21:42:18.000000000","message":"Yup, the spec is outdated and I ran into this exact issue during testing the stack.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":1240,"context_line":"                          \u0027Error: (%s %s)\u0027,"},{"line_number":1241,"context_line":"                          port_id, host, resp.status_code, resp.text,"},{"line_number":1242,"context_line":"                          instance\u003dinstance)"},{"line_number":1243,"context_line":"                # TODO(mriedem): move this cleanup code to a separate method"},{"line_number":1244,"context_line":"                for rollback_port_id in bindings_by_port_id:"},{"line_number":1245,"context_line":"                    url \u003d \u0027/v2.0/ports/%s/bindings/%s\u0027 % ("},{"line_number":1246,"context_line":"                        rollback_port_id, host)"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_fc100b5c","line":1243,"updated":"2018-06-18 12:40:11.000000000","message":"+1","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"}],"nova/tests/unit/network/test_neutronv2.py":[{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":5338,"context_line":"        client_mock \u003d mock.patch("},{"line_number":5339,"context_line":"            \u0027nova.network.neutronv2.api.get_client\u0027).start()"},{"line_number":5340,"context_line":"        client_mock.return_value \u003d self.client"},{"line_number":5341,"context_line":"        self.addCleanup(client_mock.stop)"},{"line_number":5342,"context_line":""},{"line_number":5343,"context_line":"    def test_bind_ports_to_host_no_ports(self):"},{"line_number":5344,"context_line":"        self.assertIsNone("}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_77c2d135","line":5341,"range":{"start_line":5341,"start_character":8,"end_line":5341,"end_character":41},"updated":"2018-03-26 23:42:04.000000000","message":"This will call automocked method stop() on client_mock, which will succeed silently, but isn\u0027t what you want.  You need to stop the patcher instead.\n\n client_patch \u003d mock.patch(\u0027nova....get_client\u0027)\n client_mock \u003d client_patch.start()\n self.addCleanup(client_patch.stop)","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"5ac5fc37ea8b22572fddc1afaea45b9e985e4c82","unresolved":false,"context_lines":[{"line_number":5338,"context_line":"        client_mock \u003d mock.patch("},{"line_number":5339,"context_line":"            \u0027nova.network.neutronv2.api.get_client\u0027).start()"},{"line_number":5340,"context_line":"        client_mock.return_value \u003d self.client"},{"line_number":5341,"context_line":"        self.addCleanup(client_mock.stop)"},{"line_number":5342,"context_line":""},{"line_number":5343,"context_line":"    def test_bind_ports_to_host_no_ports(self):"},{"line_number":5344,"context_line":"        self.assertIsNone("}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_c02bd67f","line":5341,"range":{"start_line":5341,"start_character":8,"end_line":5341,"end_character":41},"in_reply_to":"bf659307_77c2d135","updated":"2018-03-27 01:01:45.000000000","message":"Yeah good catch, except the cleanup needs to be added before the start() on the patcher.","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"a9f0bf3e6268ce8261cecf8e8769d03521bf4ab4","unresolved":false,"context_lines":[{"line_number":5338,"context_line":"        client_mock \u003d mock.patch("},{"line_number":5339,"context_line":"            \u0027nova.network.neutronv2.api.get_client\u0027).start()"},{"line_number":5340,"context_line":"        client_mock.return_value \u003d self.client"},{"line_number":5341,"context_line":"        self.addCleanup(client_mock.stop)"},{"line_number":5342,"context_line":""},{"line_number":5343,"context_line":"    def test_bind_ports_to_host_no_ports(self):"},{"line_number":5344,"context_line":"        self.assertIsNone("}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_90c29d33","line":5341,"range":{"start_line":5341,"start_character":8,"end_line":5341,"end_character":41},"in_reply_to":"bf659307_c02bd67f","updated":"2018-03-30 14:19:01.000000000","message":"Actually this goes away when I revert back to using KSA.","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"4d915d11482fb887414a4c213508efca34157a2b","unresolved":false,"context_lines":[{"line_number":5375,"context_line":"        def fake_post(url, *args, **kwargs):"},{"line_number":5376,"context_line":"            if uuids.ok in url:"},{"line_number":5377,"context_line":"                # TODO(mriedem): Move"},{"line_number":5378,"context_line":"                # nova.tests.unit.test_identity.FakeResponse into common code"},{"line_number":5379,"context_line":"                # and re-use that here."},{"line_number":5380,"context_line":"                mock_response \u003d mock.MagicMock(status_code\u003d200)"},{"line_number":5381,"context_line":"                try:"}],"source_content_type":"text/x-python","patch_set":8,"id":"bf659307_77f09191","line":5378,"range":{"start_line":5378,"start_character":18,"end_line":5378,"end_character":61},"updated":"2018-03-26 23:42:04.000000000","message":"Not a response.","commit_id":"1b03a84f9787885b75a66b99910a4aead4833892"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"a630c4d9af59645c98a38256a5d00cdd0ed9cebe","unresolved":false,"context_lines":[{"line_number":5373,"context_line":""},{"line_number":5374,"context_line":"        def fake_post(url, *args, **kwargs):"},{"line_number":5375,"context_line":"            if uuids.ok in url:"},{"line_number":5376,"context_line":"                # TODO(mriedem): Move"},{"line_number":5377,"context_line":"                # nova.tests.unit.test_identity.FakeResponse into common code"},{"line_number":5378,"context_line":"                # and re-use that here."},{"line_number":5379,"context_line":"                mock_response \u003d mock.MagicMock(status_code\u003d200)"},{"line_number":5380,"context_line":"                mock_response.json.return_value \u003d {"},{"line_number":5381,"context_line":"                    \u0027binding\u0027: {\u0027host\u0027: \u0027fake-host\u0027}}"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_54910b46","line":5378,"range":{"start_line":5376,"start_character":0,"end_line":5378,"end_character":39},"updated":"2018-04-04 13:16:23.000000000","message":"https://review.openstack.org/#/c/556551/ is merged now","commit_id":"7f28034b4b4643a62ea6f8fac7af1a8d3341fdaf"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3b9fb2395086b6177a67567798fd7145d53d5814","unresolved":false,"context_lines":[{"line_number":5373,"context_line":""},{"line_number":5374,"context_line":"        def fake_post(url, *args, **kwargs):"},{"line_number":5375,"context_line":"            if uuids.ok in url:"},{"line_number":5376,"context_line":"                # TODO(mriedem): Move"},{"line_number":5377,"context_line":"                # nova.tests.unit.test_identity.FakeResponse into common code"},{"line_number":5378,"context_line":"                # and re-use that here."},{"line_number":5379,"context_line":"                mock_response \u003d mock.MagicMock(status_code\u003d200)"},{"line_number":5380,"context_line":"                mock_response.json.return_value \u003d {"},{"line_number":5381,"context_line":"                    \u0027binding\u0027: {\u0027host\u0027: \u0027fake-host\u0027}}"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_0aca8e9f","line":5378,"range":{"start_line":5376,"start_character":0,"end_line":5378,"end_character":39},"in_reply_to":"bf659307_54910b46","updated":"2018-04-04 14:25:54.000000000","message":"Will update.","commit_id":"7f28034b4b4643a62ea6f8fac7af1a8d3341fdaf"},{"author":{"_account_id":14070,"name":"Eric Fried","email":"openstack@fried.cc","username":"efried"},"change_message_id":"c42168f54108ab12fef5a4c0659565d253afde2c","unresolved":false,"context_lines":[{"line_number":5356,"context_line":"        mock_client.return_value.post.return_value \u003d resp"},{"line_number":5357,"context_line":"        result \u003d self.api.bind_ports_to_host("},{"line_number":5358,"context_line":"            ctxt, inst, \u0027fake-host\u0027, \u0027normal\u0027, {\u0027foo\u0027: \u0027bar\u0027})"},{"line_number":5359,"context_line":"        self.assertEqual(1, mock_client.return_value.post.call_count)"},{"line_number":5360,"context_line":"        self.assertDictEqual({uuids.port: binding[\u0027binding\u0027]}, result)"},{"line_number":5361,"context_line":""},{"line_number":5362,"context_line":"    @mock.patch(\u0027nova.network.neutronv2.api._get_ksa_client\u0027)"}],"source_content_type":"text/x-python","patch_set":12,"id":"bf659307_adfb7545","line":5359,"range":{"start_line":5359,"start_character":0,"end_line":5359,"end_character":69},"updated":"2018-04-04 20:34:21.000000000","message":"These tests could be asserting the call args.","commit_id":"f3a71c0744c548032cf5e7e9c9ab9254cd529815"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":5343,"context_line":"    def test_bind_ports_to_host_no_ports(self):"},{"line_number":5344,"context_line":"        self.assertIsNone("},{"line_number":5345,"context_line":"            self.api.bind_ports_to_host("},{"line_number":5346,"context_line":"                mock.sentinel.context, objects.Instance(info_cache\u003dNone),"},{"line_number":5347,"context_line":"                \u0027fake-host\u0027))"},{"line_number":5348,"context_line":""},{"line_number":5349,"context_line":"    @mock.patch(\u0027nova.network.neutronv2.api._get_ksa_client\u0027)"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_10804b46","line":5346,"range":{"start_line":5346,"start_character":56,"end_line":5346,"end_character":71},"updated":"2018-06-18 12:40:11.000000000","message":"When there is no ports attached to the instance the instance.info_cache still has a NetworkInfo value. What you are testing here is some seemingly weird case of get_network_info() that returns an empty NetworkInfo if the instance.info_cache is not populated.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":9708,"name":"Balazs Gibizer","display_name":"gibi","email":"gibizer@gmail.com","username":"gibi"},"change_message_id":"e8f95fc80407f50438686e37dcea410ac85a26e9","unresolved":false,"context_lines":[{"line_number":5344,"context_line":"        self.assertIsNone("},{"line_number":5345,"context_line":"            self.api.bind_ports_to_host("},{"line_number":5346,"context_line":"                mock.sentinel.context, objects.Instance(info_cache\u003dNone),"},{"line_number":5347,"context_line":"                \u0027fake-host\u0027))"},{"line_number":5348,"context_line":""},{"line_number":5349,"context_line":"    @mock.patch(\u0027nova.network.neutronv2.api._get_ksa_client\u0027)"},{"line_number":5350,"context_line":"    def test_bind_ports_to_host(self, mock_client):"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_10728bae","line":5347,"updated":"2018-06-18 12:40:11.000000000","message":"nit: you could assert that no ksa adapter is made so your short circuit works.","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"36a791dd2a24cb5cc19745c636d20cc0999c18c7","unresolved":false,"context_lines":[{"line_number":5344,"context_line":"        self.assertIsNone("},{"line_number":5345,"context_line":"            self.api.bind_ports_to_host("},{"line_number":5346,"context_line":"                mock.sentinel.context, objects.Instance(info_cache\u003dNone),"},{"line_number":5347,"context_line":"                \u0027fake-host\u0027))"},{"line_number":5348,"context_line":""},{"line_number":5349,"context_line":"    @mock.patch(\u0027nova.network.neutronv2.api._get_ksa_client\u0027)"},{"line_number":5350,"context_line":"    def test_bind_ports_to_host(self, mock_client):"}],"source_content_type":"text/x-python","patch_set":18,"id":"5f7c97a3_371f700a","line":5347,"in_reply_to":"5f7c97a3_10728bae","updated":"2018-06-18 21:42:18.000000000","message":"Done","commit_id":"9ca5069a8754ed4954108411c137283b3e5d7051"}]}
