)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"bbb23b3ac12ed144cd2c8d9cf1d3c0ddd37d2c7c","unresolved":false,"context_lines":[{"line_number":20,"context_line":"Spec available at:"},{"line_number":21,"context_line":"http://specs.openstack.org/openstack/ironic-specs/specs/liberty/"},{"line_number":22,"context_line":"ironic-ml2-integration.html"},{"line_number":23,"context_line":"Note: this is an initial draft only and is still work in progress."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Partial-bug: #1526403"},{"line_number":26,"context_line":"DocImpact"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":40,"id":"1a7b0d38_07a0a09e","line":23,"updated":"2015-12-23 14:50:59.000000000","message":"ditto should be removed.","commit_id":"2c659a20183df308c1bacc8c6b4fa638e7f60395"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"59358abd55645ac261a7f176d2536583fbb23ff5","unresolved":false,"context_lines":[{"line_number":20,"context_line":"Spec available at:"},{"line_number":21,"context_line":"http://specs.openstack.org/openstack/ironic-specs/specs/liberty/"},{"line_number":22,"context_line":"ironic-ml2-integration.html"},{"line_number":23,"context_line":"Note: this is an initial draft only and is still work in progress."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Partial-bug: #1526403"},{"line_number":26,"context_line":"DocImpact"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":40,"id":"1a7b0d38_67334063","line":23,"in_reply_to":"1a7b0d38_07a0a09e","updated":"2016-01-05 17:48:32.000000000","message":"Done","commit_id":"2c659a20183df308c1bacc8c6b4fa638e7f60395"}],"ironic/common/dhcp_factory.py":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                             \u0027opt_value\u0027: \u0027123.123.123.123\u0027}]"},{"line_number":92,"context_line":"        :param ports: a dict of Neutron port/portgroup dicts"},{"line_number":93,"context_line":"            to update DHCP options on. The port/portgroup dict keys"},{"line_number":94,"context_line":"            should be Ironic port UUIDs, and the values should be"},{"line_number":95,"context_line":"            Neutron port UUIDs, e.g."},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"            ::"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_f2c71f10","line":94,"updated":"2016-01-28 20:49:33.000000000","message":"the portgroup dict keys are ironic portgroup UUIDS right? not port UUIDs?","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":91,"context_line":"                             \u0027opt_value\u0027: \u0027123.123.123.123\u0027}]"},{"line_number":92,"context_line":"        :param ports: a dict of Neutron port/portgroup dicts"},{"line_number":93,"context_line":"            to update DHCP options on. The port/portgroup dict keys"},{"line_number":94,"context_line":"            should be Ironic port UUIDs, and the values should be"},{"line_number":95,"context_line":"            Neutron port UUIDs, e.g."},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"            ::"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_fd9fd64d","line":94,"in_reply_to":"7a5de9d1_f2c71f10","updated":"2016-01-29 22:14:37.000000000","message":"yes portgroup dict keys are ironic portgroups UUIDs","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":92,"context_line":"        :param ports: a dict of Neutron port/portgroup dicts"},{"line_number":93,"context_line":"            to update DHCP options on. The port/portgroup dict keys"},{"line_number":94,"context_line":"            should be Ironic port UUIDs, and the values should be"},{"line_number":95,"context_line":"            Neutron port UUIDs, e.g."},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"            ::"},{"line_number":98,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_c87032df","line":95,"updated":"2016-01-28 20:49:33.000000000","message":"How about\n\na dict with keys \u0027ports\u0027 and \u0027portgroups\u0027 and dicts as values. Each dict has key/value pairs of the form \u003cironic UUID\u003e:\u003cneutron port UUID\u003e. e.g.\n\nOh. Bonus points if you don\u0027t use \u0027neutron\u0027 anywhere since this should be a generalized method.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"            {\u0027ports\u0027: {\u0027port.uuid\u0027: vif.id},"},{"line_number":100,"context_line":"             \u0027portgroups\u0027: {\u0027portgroup.uuid\u0027: vif.id}}"},{"line_number":101,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":102,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        self.provider.update_dhcp_opts(task, dhcp_opts, ports)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_12999b1f","line":101,"updated":"2016-01-28 20:49:33.000000000","message":"The above egs (line 97-100) should probably be indented so it renders properly (even though no one looks at the rendered pages).\n\nAnd I think there should be a blank line above this, to separate it from the example.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":98,"context_line":""},{"line_number":99,"context_line":"            {\u0027ports\u0027: {\u0027port.uuid\u0027: vif.id},"},{"line_number":100,"context_line":"             \u0027portgroups\u0027: {\u0027portgroup.uuid\u0027: vif.id}}"},{"line_number":101,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":102,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":103,"context_line":"        \"\"\""},{"line_number":104,"context_line":"        self.provider.update_dhcp_opts(task, dhcp_opts, ports)"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_fd3b5636","line":101,"in_reply_to":"7a5de9d1_12999b1f","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a2c4503683a4afd44a2093452e08b1e333012f","unresolved":false,"context_lines":[{"line_number":102,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":103,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":104,"context_line":"        \"\"\""},{"line_number":105,"context_line":"        self.provider.update_dhcp_opts(task, dhcp_opts, ports)"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def clean_dhcp(self, task):"},{"line_number":108,"context_line":"        \"\"\"Clean up the DHCP BOOT options for this node."}],"source_content_type":"text/x-python","patch_set":53,"id":"5a5ae5dd_19b1e48f","line":105,"updated":"2016-02-03 22:45:58.000000000","message":"This changes the contents of ports parameter, so may break out of tree dhcp providers. This might be something to be added to a release note in further patches or in this one.","commit_id":"fa98c471c8824f7163530fec95f152a13502cceb"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"3a328a8532356f914d043365f0d9a916b789ab09","unresolved":false,"context_lines":[{"line_number":102,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":103,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":104,"context_line":"        \"\"\""},{"line_number":105,"context_line":"        self.provider.update_dhcp_opts(task, dhcp_opts, ports)"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":"    def clean_dhcp(self, task):"},{"line_number":108,"context_line":"        \"\"\"Clean up the DHCP BOOT options for this node."}],"source_content_type":"text/x-python","patch_set":53,"id":"5a5ae5dd_2c54dcc7","line":105,"in_reply_to":"5a5ae5dd_19b1e48f","updated":"2016-02-08 21:29:11.000000000","message":"Thanks for pointing this out Vladyslav. We discussed in the weekly meeting [1]. Since we don\u0027t make any guarantees about this being a stable API, the decision was to add a reno in [2] and give a heads up in the form of an email to the community [3].\n\n[1] http://eavesdrop.openstack.org/meetings/ironic/2016/ironic.2016-02-08-17.00.log.html#17:17:30\n\n[2] https://review.openstack.org/#/c/206244/\n\n[3] http://lists.openstack.org/pipermail/openstack-dev/2016-February/086109.html","commit_id":"fa98c471c8824f7163530fec95f152a13502cceb"}],"ironic/common/network.py":[{"author":{"_account_id":10343,"name":"Jim Rollenhagen","email":"jim@jimrollenhagen.com","username":"jimrollenhagen"},"change_message_id":"ccbc99a0bd6bc2d7db01b3c4d5bd933a3a0dfb64","unresolved":false,"context_lines":[{"line_number":27,"context_line":"    for portgroup in task.portgroups:"},{"line_number":28,"context_line":"        vif \u003d portgroup.extra.get(\u0027vif_port_id\u0027)"},{"line_number":29,"context_line":"        if vif:"},{"line_number":30,"context_line":"            port_vifs[portgroup.uuid] \u003d vif"},{"line_number":31,"context_line":"    for port in task.ports:"},{"line_number":32,"context_line":"        vif \u003d port.extra.get(\u0027vif_port_id\u0027)"},{"line_number":33,"context_line":"        if vif:"}],"source_content_type":"text/x-python","patch_set":9,"id":"1a4dcd0f_0731470b","line":30,"updated":"2015-08-10 23:38:11.000000000","message":"So this is interesting... in theory this could conflict with a port uuid, since the unique constraint is only on each table. Maybe we should distinguish these somehow?","commit_id":"0f37fce42d7aa25a390183ad7573bebcd20a2395"},{"author":{"_account_id":17270,"name":"Sergii Turivnyi","email":"sturivnyi@mirantis.com","username":"sturivnyi"},"change_message_id":"b30bc57c703e4a672a5036e10a5d851211a2a9f8","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: A dict of the Node\u0027s port and portgroup UUIDs and their"},{"line_number":23,"context_line":"              associated VIFs"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    \"\"\""},{"line_number":26,"context_line":"    port_vifs \u003d {}"},{"line_number":27,"context_line":"    for portgroup in task.portgroups:"}],"source_content_type":"text/x-python","patch_set":37,"id":"fa80f949_c85ee111","line":24,"updated":"2015-11-05 16:56:07.000000000","message":"I think we don\u0027t need empty string at the end of the docstring.","commit_id":"cb90cc3a26174918d80aad75a89e0a9bf7c1d255"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"9d4bb5696c2e0788aed21011e09ea20f16e9ecc8","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: A dict of the Node\u0027s port and portgroup UUIDs and their"},{"line_number":23,"context_line":"              associated VIFs"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    \"\"\""},{"line_number":26,"context_line":"    port_vifs \u003d {}"},{"line_number":27,"context_line":"    for portgroup in task.portgroups:"}],"source_content_type":"text/x-python","patch_set":37,"id":"3a7e1126_4e355644","line":24,"in_reply_to":"fa80f949_c85ee111","updated":"2015-12-17 13:37:53.000000000","message":"Done","commit_id":"cb90cc3a26174918d80aad75a89e0a9bf7c1d255"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"9b206569147664cfe49f19be7f217a1c07e787d3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"ba63e191_f0473875","line":35,"updated":"2016-01-19 20:04:32.000000000","message":"I have to admit, it seems ODD to have one dict that is indexed by UUIDs for ports and/or portgroups. More than ODD, it seems wrong.\n\nAt the very least, it shouldn\u0027t be called port_vifs because that is misleading. \u0027vifs\u0027 is good enough.\n\nThere is no guarantee that a UUID is unique across ports \u0026 portgroups, so that could be a problem. Is the uuid ever used?","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"4ce4f05401ddd09be7b08b46ec1ac483628d8b22","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"9a68dd71_8c67834c","line":35,"in_reply_to":"9a68dd71_45bc6f6c","updated":"2016-01-22 13:56:14.000000000","message":"VIF (virtual interface) \u003d neutron port.\n\nNeutron identifies neutron ports by UUID.\nIronic maps ironic-port to neutron-port by using ironic port extra attribute extra/vif_port_id\u003d\u003cneutron port uuid\u003e.\n\nHere \u0027vif\u0027 is the neutron port uuid.\nhttps://github.com/openstack/ironic/blob/master/ironic/common/network.py#L27\nNeutron doesn\u0027t know anything about ironic. Neutron VIF is the same for ironic-port and ironic-portgroup. That is why I doubt that we should distinguish ironic port and portgroup VIFs.\n\nIf we want to have guarantee on DB level that port and portgroup uuids are unique than we should update DB schema.\nI see two options here:\n\n1) Create additional table called \u0027port_portgroups\u0027 which contains only one column - UUID, that contains UUIDs of both ports and portgroups and a unique constraint on this column. Then we could update \u0027port[group]s\u0027 table UUID column to be foreign key to \u0027port_portgroups\u0027 UUID;\n\n2) Since portgroup is special case of port object, we could store portgroup in the port table except address field (there is a unique constraint on address). Then we could create portgroup table and store address in it (since mac address of portgroup and port may be the same according to:\nhttps://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/Documentation/networking/bonding.txt)\n\nI prefer to not change DB schema as it was approved in the spec: http://specs.openstack.org/openstack/ironic-specs/specs/approved/ironic-ml2-integration.html\nThe easiest way would be to raise an exception if we found a duplicate uuid among port and portgroups (with 2**-128 chance)\n\nfor port in task.ports:\n        vif \u003d port.extra.get(\u0027vif_port_id\u0027)\n        if vif:\n            if vif in port_vifs:\n                raise exception.DuplicateUUIDError(_(\u0027Found duplicate UUID %s among port and portgroups\u0027) % vif)\n            port_vifs[port.uuid] \u003d vif\n    return port_vifs","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":10343,"name":"Jim Rollenhagen","email":"jim@jimrollenhagen.com","username":"jimrollenhagen"},"change_message_id":"98f4a0da0e94230104866fdf57259175b10003a8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"9a68dd71_cf4e713a","line":35,"in_reply_to":"9a68dd71_8c67834c","updated":"2016-01-25 16:13:43.000000000","message":"I think we should return {portgroups: {uuid: vif_id}, ports: {uuid: vif_id}} and be done with it. I do agree this is a bug.","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"750ec2532e8cb096009113063ba72a8cc57af73b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"9a68dd71_8a1f07b6","line":35,"in_reply_to":"9a68dd71_cf4e713a","updated":"2016-01-25 16:35:11.000000000","message":"I am fine with Jim\u0027s proposal if that works for whatever code is using this.\n\nAn alternative is to add a second parameter, to distinguish whether one wants VIFs from ports or portgroups, default is from ports. This alternative won\u0027t return the VIFs from both ports and portgroups though, whereas Jim\u0027s will.\n\nIf you need/want help deciding, let me know and I\u0027ll try to find some time to look into it. Jim is more familiar with this code so I am hoping he knows what he\u0027s talking about :D","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"e0c3679c72cb00065c4739f73460ec4de4191294","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"9a68dd71_45bc6f6c","line":35,"in_reply_to":"9a68dd71_e5ac83ef","updated":"2016-01-20 18:38:44.000000000","message":"wrt 1. How is neutron using this information? Are they using the UUIDs or only the vifs? And if only the VIFs, why is ironic (if ironic is, I don\u0027t know) sending the UUIDs to neutron as well?\n\nwrt 2. I have no problem changing the format everywhere as long as it is backwards compatible.\n\nwrt UUID not being unique. I\u0027m not convinced that \u0027highly unlikely\u0027 is good enough. Also, when creating a port, the user can specify the UUID and I am paranoid where users are concerned; they could accidentally use the same UUID for a portgroup. I don\u0027t think it is a hard problem to deal with ports and portgroups so we should just address it.\n\nIs it the case that all the code that uses the vifs from here, are expecting vifs from either ports or portgroups, or are there cases where the code is only interested in ports?\n\nIf you can provide more information as to when/how this information is being used, I think we should be able to come up with something that will work better than this.","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"38a05af6d02130a6345581895ccf2b8be190c995","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"9a68dd71_e5ac83ef","line":35,"in_reply_to":"ba63e191_41050d78","updated":"2016-01-20 18:22:22.000000000","message":"I doubt that change return value format for get_node_vif_ids() is a good option since:\n1. From Neutron point of view VIF is the same for port and portgroup\n2. We also would need to change format everywhere, where we are using neutron VIFs like https://github.com/openstack/ironic/blob/9427a8c3fd5dfa6eb39be381e16b47e2be1bfd7f/ironic/common/dhcp_factory.py#L95\n\nI\u0027m prefer to update \u0027port_vifs\u0027 variable name to \u0027vifs\u0027 or \u0027neutron_vifs\u0027 in order to avoid confusion here.\nAnd update error message to \u0027Failed to set DHCP BOOT options for any Neutron port on node\u0027\nhttps://github.com/openstack/ironic/blob/f4a7a847b7c3cd1aa43ec600c6d4cd51ed796145/ironic/dhcp/neutron.py#L183\n\nIndeed, UUID is not unique across ports \u0026 portgroups but it is highly unlikely 2**-128 for them to collide.","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"a10e8a9800097fe223fdd7d27d770be5d1c21f6d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":47,"id":"ba63e191_41050d78","line":35,"in_reply_to":"ba63e191_f0473875","updated":"2016-01-19 20:18:25.000000000","message":"I did a quick look at the rest of the patches here. The port UUID is used here and your patches don\u0027t change it:\n1. https://github.com/openstack/ironic/blob/f4a7a847b7c3cd1aa43ec600c6d4cd51ed796145/ironic/dhcp/neutron.py#L178\nThe error message will be incorrect since the uuids are not all ports\n\n2. https://github.com/openstack/ironic/blob/f4a7a847b7c3cd1aa43ec600c6d4cd51ed796145/ironic/dhcp/neutron.py#L255\nHere, it is looking for a port UUID.\n\nWhere do you use these VIFs that are also associated with the portgroups? Maybe we can come up with a better method...","commit_id":"7a427876383f85183ae8674a9949971809e89b0a"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    This function does not handle multi node operations."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: a dict of Node\u0027s neutron ports, where keys are port, portgroups"},{"line_number":23,"context_line":"              and the values are dict of UUIDs and their assosiated VIFs, e.g."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"              ::"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_d203000c","line":22,"updated":"2016-01-28 20:49:33.000000000","message":"s/port, portgroups/\u0027ports\u0027 \u0026 \u0027portgroups\u0027/","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    This function does not handle multi node operations."},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: a dict of Node\u0027s neutron ports, where keys are port, portgroups"},{"line_number":23,"context_line":"              and the values are dict of UUIDs and their assosiated VIFs, e.g."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"              ::"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_bde15e9c","line":22,"in_reply_to":"7a5de9d1_d203000c","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: a dict of Node\u0027s neutron ports, where keys are port, portgroups"},{"line_number":23,"context_line":"              and the values are dict of UUIDs and their assosiated VIFs, e.g."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"              ::"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_121af86e","line":23,"updated":"2016-01-28 20:49:33.000000000","message":"s/assosiated/associated/","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    :param task: a TaskManager instance."},{"line_number":22,"context_line":"    :returns: a dict of Node\u0027s neutron ports, where keys are port, portgroups"},{"line_number":23,"context_line":"              and the values are dict of UUIDs and their assosiated VIFs, e.g."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"              ::"},{"line_number":26,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_9de6e2b2","line":23,"in_reply_to":"7a5de9d1_121af86e","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"}],"ironic/dhcp/base.py":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":84,"context_line":"             \u0027portgroups\u0027: {\u0027portgroup.uuid\u0027: vif.id}}"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":87,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":88,"context_line":"        :raises: FailedToUpdateDHCPOptOnPort"},{"line_number":89,"context_line":"        \"\"\""},{"line_number":90,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_b22d2448","line":87,"updated":"2016-01-28 20:49:33.000000000","message":"however we describe this in dhcp_factory.py, I guess we should copy here.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":84,"context_line":"             \u0027portgroups\u0027: {\u0027portgroup.uuid\u0027: vif.id}}"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"            If the value is None, will get the list of ports/portgroups"},{"line_number":87,"context_line":"            from the Ironic port/portgroup objects."},{"line_number":88,"context_line":"        :raises: FailedToUpdateDHCPOptOnPort"},{"line_number":89,"context_line":"        \"\"\""},{"line_number":90,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_bd7ddeb2","line":87,"in_reply_to":"7a5de9d1_b22d2448","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        :param task: a TaskManager instance."},{"line_number":96,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":97,"context_line":"                  task.ports/task.porgroups"},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def clean_dhcp_opts(self, task):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_b238c4a1","line":97,"updated":"2016-01-28 20:49:33.000000000","message":"s/porgroups/portgroups/\n\nAnd better English would be \"task\u0027s ports and portgroups\".","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        :param task: a TaskManager instance."},{"line_number":96,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":97,"context_line":"                  task.ports/task.porgroups"},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def clean_dhcp_opts(self, task):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_1d13d267","line":97,"in_reply_to":"7a5de9d1_b238c4a1","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        :param task: A TaskManager instance."},{"line_number":96,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":97,"context_line":"            task\u0027s ports and porgroups."},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def clean_dhcp_opts(self, task):"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_c280918d","line":97,"updated":"2016-02-01 19:59:33.000000000","message":"s/porgroups/portgroups/","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        :param task: A TaskManager instance."},{"line_number":96,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":97,"context_line":"            task\u0027s ports and porgroups."},{"line_number":98,"context_line":"        \"\"\""},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"    def clean_dhcp_opts(self, task):"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_2e2fd9f7","line":97,"in_reply_to":"7a5de9d1_c280918d","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"}],"ironic/dhcp/neutron.py":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        \"\"\""},{"line_number":172,"context_line":"        if vifs is None:"},{"line_number":173,"context_line":"            vifs \u003d network.get_node_vif_ids(task)"},{"line_number":174,"context_line":"        if not vifs:"},{"line_number":175,"context_line":"            raise exception.FailedToUpdateDHCPOptOnPort("},{"line_number":176,"context_line":"                _(\"No VIFs found for node %(node)s when attempting \""},{"line_number":177,"context_line":"                  \"to update DHCP BOOT options.\") %"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_f2307c03","line":174,"updated":"2016-01-28 20:49:33.000000000","message":"This probably needs to be changed. because you could have vifs \u003d {\u0027ports\u0027:{}, \u0027portgroups\u0027:{}}","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":171,"context_line":"        \"\"\""},{"line_number":172,"context_line":"        if vifs is None:"},{"line_number":173,"context_line":"            vifs \u003d network.get_node_vif_ids(task)"},{"line_number":174,"context_line":"        if not vifs:"},{"line_number":175,"context_line":"            raise exception.FailedToUpdateDHCPOptOnPort("},{"line_number":176,"context_line":"                _(\"No VIFs found for node %(node)s when attempting \""},{"line_number":177,"context_line":"                  \"to update DHCP BOOT options.\") %"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_0065a5df","line":174,"in_reply_to":"7a5de9d1_f2307c03","updated":"2016-01-29 22:14:37.000000000","message":"you are right","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":185,"context_line":"                self.update_port_dhcp_opts(port_vif, options,"},{"line_number":186,"context_line":"                                           token\u003dtask.context.auth_token)"},{"line_number":187,"context_line":"            except exception.FailedToUpdateDHCPOptOnPort:"},{"line_number":188,"context_line":"                failures.append(port_vif)"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"        if failures:"},{"line_number":191,"context_line":"            if len(failures) \u003d\u003d len(port_vifs + portgroup_vifs):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_327934c9","line":188,"updated":"2016-01-28 20:49:33.000000000","message":"The original code was appending the port_id. This is appending the port_vif. If we really want the port_vif, then item_id is not used at all. So instead of doing the above list(vifs.get().items()), you could do something like\n\nvif_list \u003d [vif for pdict in vifs.values() for vif in pdict.values()]\nfor vif in vif_list:","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":185,"context_line":"                self.update_port_dhcp_opts(port_vif, options,"},{"line_number":186,"context_line":"                                           token\u003dtask.context.auth_token)"},{"line_number":187,"context_line":"            except exception.FailedToUpdateDHCPOptOnPort:"},{"line_number":188,"context_line":"                failures.append(port_vif)"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"        if failures:"},{"line_number":191,"context_line":"            if len(failures) \u003d\u003d len(port_vifs + portgroup_vifs):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_c09b0d71","line":188,"in_reply_to":"7a5de9d1_327934c9","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":250,"context_line":"        :param task: a TaskManager instance."},{"line_number":251,"context_line":"        :param p_obj: Ironic Node\u0027s port/portgroup object."},{"line_number":252,"context_line":"        :param client: Neutron client instance."},{"line_number":253,"context_line":"        :returns: Neutron vif ip address associated with Node\u0027s port/portgroup."},{"line_number":254,"context_line":"        :raises: FailedToGetIPAddressOnPort"},{"line_number":255,"context_line":"        :raises: InvalidIPv4Address"},{"line_number":256,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_7558f632","line":253,"updated":"2016-01-28 20:49:33.000000000","message":"Hmm. I recall thinking when I was reviewing one of the other patches (maybe the one for objects.Portgroup) that maybe one should be subclassed from the other because there was a lot of similarity. Well, I suppose that can be cleaned up later.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        \"\"\""},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        vifs \u003d network.get_node_vif_ids(task)"},{"line_number":259,"context_line":"        if not (vifs.get(\u0027ports\u0027) or vifs.get(\u0027portgroups\u0027)):"},{"line_number":260,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":261,"context_line":"                            \" to get port/portgroup IP address.\"),"},{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_b5eaee0d","line":259,"updated":"2016-01-28 20:49:33.000000000","message":"I\u0027d rather we did vifs[\u0027ports] or vifs[\u0027portgroups\u0027] since network.get_node_vif_ids() should always return a dict with those keys.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":256,"context_line":"        \"\"\""},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        vifs \u003d network.get_node_vif_ids(task)"},{"line_number":259,"context_line":"        if not (vifs.get(\u0027ports\u0027) or vifs.get(\u0027portgroups\u0027)):"},{"line_number":260,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":261,"context_line":"                            \" to get port/portgroup IP address.\"),"},{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_5b3872a0","line":259,"in_reply_to":"7a5de9d1_b5eaee0d","updated":"2016-01-29 22:14:37.000000000","message":"It is not needed, since we can get vif_id directly from portgroup/port object","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            vif \u003d vifs[\u0027ports\u0027][p_obj.uuid]"},{"line_number":266,"context_line":"        else:"},{"line_number":267,"context_line":"            vif \u003d vifs[\u0027portgroups\u0027][p_obj.uuid]"},{"line_number":268,"context_line":""},{"line_number":269,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":270,"context_line":"        return vif_ip_address"},{"line_number":271,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_55cb7a72","line":268,"updated":"2016-01-28 20:49:33.000000000","message":"So I am wondering if I am going crazy. If you have the port or portgroup object, the vif is available in p_obj.extra.get(\u0027vif_port_id\u0027), isn\u0027t it?","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":265,"context_line":"            vif \u003d vifs[\u0027ports\u0027][p_obj.uuid]"},{"line_number":266,"context_line":"        else:"},{"line_number":267,"context_line":"            vif \u003d vifs[\u0027portgroups\u0027][p_obj.uuid]"},{"line_number":268,"context_line":""},{"line_number":269,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":270,"context_line":"        return vif_ip_address"},{"line_number":271,"context_line":""}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_fbd91e84","line":268,"in_reply_to":"7a5de9d1_55cb7a72","updated":"2016-01-29 22:14:37.000000000","message":"you are right, Since we passing port object there is no need to do not needed extra calls. We can get neutron vif_uuid directly from the object.","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":297,"context_line":"                            \" while retrieving IP address on the following\""},{"line_number":298,"context_line":"                            \" ports: %(ports)s, portgroups %(portgroups)s.\"),"},{"line_number":299,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027ports\u0027: failures[\u0027ports\u0027],"},{"line_number":300,"context_line":"                         \u0027portgroups\u0027: failures[\u0027portgroups\u0027]})"},{"line_number":301,"context_line":"        return ip_addresses"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"    def create_cleaning_ports(self, task):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_35fa7e76","line":300,"updated":"2016-01-28 20:49:33.000000000","message":"they need to be failures.get(\u0027ports\u0027) and failures.get(\u0027portgroups\u0027).","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":297,"context_line":"                            \" while retrieving IP address on the following\""},{"line_number":298,"context_line":"                            \" ports: %(ports)s, portgroups %(portgroups)s.\"),"},{"line_number":299,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027ports\u0027: failures[\u0027ports\u0027],"},{"line_number":300,"context_line":"                         \u0027portgroups\u0027: failures[\u0027portgroups\u0027]})"},{"line_number":301,"context_line":"        return ip_addresses"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"    def create_cleaning_ports(self, task):"}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_7cda014e","line":300,"in_reply_to":"7a5de9d1_35fa7e76","updated":"2016-01-29 22:14:37.000000000","message":"right, because there might be situation when there is no key in the dict","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"308baec59a46e42d0cd7c9387fc0235c18c12855","unresolved":false,"context_lines":[{"line_number":298,"context_line":"                            \" ports: %(ports)s, portgroups %(portgroups)s.\"),"},{"line_number":299,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027ports\u0027: failures[\u0027ports\u0027],"},{"line_number":300,"context_line":"                         \u0027portgroups\u0027: failures[\u0027portgroups\u0027]})"},{"line_number":301,"context_line":"        return ip_addresses"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"    def create_cleaning_ports(self, task):"},{"line_number":304,"context_line":"        \"\"\"Create neutron ports for each port on task.node to boot the ramdisk."}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_d51c4a79","line":301,"updated":"2016-01-28 20:49:33.000000000","message":"I\u0027d actually prefer if you had another method eg _get_ip_addresses(self, task, object_list, name) that did all the work similar to the original get_ip_addresses.\n\nget_ip_addresses() would make two calls:\n    addresses \u003d _get_ip_addresses(task, task.ports, \"ports\")\n    addresses +\u003d _get_ip_addresses(task, task.portgroups, \"portgroups\")","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"8efdd9de7a72dd1e5c1efeffd0188c3880397575","unresolved":false,"context_lines":[{"line_number":298,"context_line":"                            \" ports: %(ports)s, portgroups %(portgroups)s.\"),"},{"line_number":299,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027ports\u0027: failures[\u0027ports\u0027],"},{"line_number":300,"context_line":"                         \u0027portgroups\u0027: failures[\u0027portgroups\u0027]})"},{"line_number":301,"context_line":"        return ip_addresses"},{"line_number":302,"context_line":""},{"line_number":303,"context_line":"    def create_cleaning_ports(self, task):"},{"line_number":304,"context_line":"        \"\"\"Create neutron ports for each port on task.node to boot the ramdisk."}],"source_content_type":"text/x-python","patch_set":51,"id":"7a5de9d1_b3c17456","line":301,"in_reply_to":"7a5de9d1_d51c4a79","updated":"2016-01-29 22:14:37.000000000","message":"Done","commit_id":"d5acfba6110bf3610b7e579280c7f4f8cd13523d"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        if not vif:"},{"line_number":260,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":261,"context_line":"                            \" to get port/portgroup IP address.\"),"},{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"},{"line_number":263,"context_line":"            raise exception.FailedToGetIPAddressOnPort(port_id\u003dp_obj.uuid)"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"        vif \u003d p_obj.extra.get(\u0027vif_port_id\u0027)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_bd025ab2","line":262,"updated":"2016-02-01 19:59:33.000000000","message":"would it be useful to also log the object (port/portgroup) uuid? Bonus points for indicating whether it is a port or a portgroup :)","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":259,"context_line":"        if not vif:"},{"line_number":260,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":261,"context_line":"                            \" to get port/portgroup IP address.\"),"},{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"},{"line_number":263,"context_line":"            raise exception.FailedToGetIPAddressOnPort(port_id\u003dp_obj.uuid)"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"        vif \u003d p_obj.extra.get(\u0027vif_port_id\u0027)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_49e6cf45","line":262,"in_reply_to":"7a5de9d1_bd025ab2","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"},{"line_number":263,"context_line":"            raise exception.FailedToGetIPAddressOnPort(port_id\u003dp_obj.uuid)"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"        vif \u003d p_obj.extra.get(\u0027vif_port_id\u0027)"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":268,"context_line":"        return vif_ip_address"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_bdb81a2b","line":265,"updated":"2016-02-01 19:59:33.000000000","message":"You don\u0027t need to do this again, it is done at line 258 above.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":262,"context_line":"                        {\u0027node\u0027: task.node.uuid})"},{"line_number":263,"context_line":"            raise exception.FailedToGetIPAddressOnPort(port_id\u003dp_obj.uuid)"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"        vif \u003d p_obj.extra.get(\u0027vif_port_id\u0027)"},{"line_number":266,"context_line":""},{"line_number":267,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":268,"context_line":"        return vif_ip_address"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_c9b2bf06","line":265,"in_reply_to":"7a5de9d1_bdb81a2b","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":268,"context_line":"        return vif_ip_address"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def _get_ip_addresses(self, task, p_obj, client):"},{"line_number":271,"context_line":"        \"\"\"Get IP addresses for all ports/portgroups."},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        :param task: a TaskManager instance."}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_dd1ab6c5","line":270,"updated":"2016-02-01 19:59:33.000000000","message":"p_obj makes it seem like one object. How about p_list or pobj_list? (both are yucky but clearer I think)","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":267,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"},{"line_number":268,"context_line":"        return vif_ip_address"},{"line_number":269,"context_line":""},{"line_number":270,"context_line":"    def _get_ip_addresses(self, task, p_obj, client):"},{"line_number":271,"context_line":"        \"\"\"Get IP addresses for all ports/portgroups."},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        :param task: a TaskManager instance."}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_898847c8","line":270,"in_reply_to":"7a5de9d1_dd1ab6c5","updated":"2016-02-03 21:29:03.000000000","message":"pobj_list is good name I think.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":271,"context_line":"        \"\"\"Get IP addresses for all ports/portgroups."},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        :param task: a TaskManager instance."},{"line_number":274,"context_line":"        :param p_obj: List of Ironic Node\u0027s port/portgroup object."},{"line_number":275,"context_line":"        :param client: Neutron client instance."},{"line_number":276,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":277,"context_line":"                  task\u0027s ports/portgroups."}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_9d667e4f","line":274,"updated":"2016-02-01 19:59:33.000000000","message":"how about \u0027list of port or portgroup objects\u0027.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":271,"context_line":"        \"\"\"Get IP addresses for all ports/portgroups."},{"line_number":272,"context_line":""},{"line_number":273,"context_line":"        :param task: a TaskManager instance."},{"line_number":274,"context_line":"        :param p_obj: List of Ironic Node\u0027s port/portgroup object."},{"line_number":275,"context_line":"        :param client: Neutron client instance."},{"line_number":276,"context_line":"        :returns: List of IP addresses associated with"},{"line_number":277,"context_line":"                  task\u0027s ports/portgroups."}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_6902ab0d","line":274,"in_reply_to":"7a5de9d1_9d667e4f","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":291,"context_line":"            if isinstance(p_obj, Port):"},{"line_number":292,"context_line":"                obj_name \u003d \u0027port\u0027"},{"line_number":293,"context_line":"            else:"},{"line_number":294,"context_line":"                obj_name \u003d \u0027portgroup\u0027"},{"line_number":295,"context_line":""},{"line_number":296,"context_line":"            LOG.warning(_LW("},{"line_number":297,"context_line":"                \"Some errors were encountered on node %(node)s \""}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_71d64650","line":294,"updated":"2016-02-01 19:59:33.000000000","message":"maybe they should be \u0027ports\u0027 and \u0027portgroups\u0027. Otherwise the log msg will look something like \u0027.. retrieving IP addresses on the following port: [uuid1, uuid2]\u0027.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":291,"context_line":"            if isinstance(p_obj, Port):"},{"line_number":292,"context_line":"                obj_name \u003d \u0027port\u0027"},{"line_number":293,"context_line":"            else:"},{"line_number":294,"context_line":"                obj_name \u003d \u0027portgroup\u0027"},{"line_number":295,"context_line":""},{"line_number":296,"context_line":"            LOG.warning(_LW("},{"line_number":297,"context_line":"                \"Some errors were encountered on node %(node)s \""}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_1ba9fedf","line":294,"in_reply_to":"7a5de9d1_71d64650","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":295,"context_line":""},{"line_number":296,"context_line":"            LOG.warning(_LW("},{"line_number":297,"context_line":"                \"Some errors were encountered on node %(node)s \""},{"line_number":298,"context_line":"                \"while retrieving IP address on the following \""},{"line_number":299,"context_line":"                \"%(obj_name)s: %(failures)s.\"),"},{"line_number":300,"context_line":"                {\u0027node\u0027: task.node.uuid, \u0027obj_name\u0027: obj_name,"},{"line_number":301,"context_line":"                 \u0027failures\u0027: failures})"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_d1c7fa93","line":298,"updated":"2016-02-01 19:59:33.000000000","message":"s/address/addresses/","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":295,"context_line":""},{"line_number":296,"context_line":"            LOG.warning(_LW("},{"line_number":297,"context_line":"                \"Some errors were encountered on node %(node)s \""},{"line_number":298,"context_line":"                \"while retrieving IP address on the following \""},{"line_number":299,"context_line":"                \"%(obj_name)s: %(failures)s.\"),"},{"line_number":300,"context_line":"                {\u0027node\u0027: task.node.uuid, \u0027obj_name\u0027: obj_name,"},{"line_number":301,"context_line":"                 \u0027failures\u0027: failures})"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_5b869666","line":298,"in_reply_to":"7a5de9d1_d1c7fa93","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a2c4503683a4afd44a2093452e08b1e333012f","unresolved":false,"context_lines":[{"line_number":256,"context_line":"            obj_name \u003d \u0027portgroup\u0027"},{"line_number":257,"context_line":"            if isinstance(p_obj, Port):"},{"line_number":258,"context_line":"                obj_name \u003d \u0027port\u0027"},{"line_number":259,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":260,"context_line":"                            \"to get IP address for %(obj_name)s: %(obj_id).\"),"},{"line_number":261,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027obj_name\u0027: obj_name,"},{"line_number":262,"context_line":"                        \u0027obj_id\u0027: p_obj.uuid})"}],"source_content_type":"text/x-python","patch_set":53,"id":"5a5ae5dd_14276b13","line":259,"updated":"2016-02-03 22:45:58.000000000","message":"This is changed now, so it seems to be smth like:\n\n\"No VIFs found for %(obj_name)s %(obj_id)s of node %(node)s when attempting to get %(obj_name)s\u0027s IP address.\"","commit_id":"fa98c471c8824f7163530fec95f152a13502cceb"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"f06db08c4852efae9328866a8afab151623da39b","unresolved":false,"context_lines":[{"line_number":259,"context_line":"            LOG.warning(_LW(\"No VIFs found for node %(node)s when attempting \""},{"line_number":260,"context_line":"                            \"to get IP address for %(obj_name)s: %(obj_id).\"),"},{"line_number":261,"context_line":"                        {\u0027node\u0027: task.node.uuid, \u0027obj_name\u0027: obj_name,"},{"line_number":262,"context_line":"                        \u0027obj_id\u0027: p_obj.uuid})"},{"line_number":263,"context_line":"            raise exception.FailedToGetIPAddressOnPort(port_id\u003dp_obj.uuid)"},{"line_number":264,"context_line":""},{"line_number":265,"context_line":"        vif_ip_address \u003d self._get_fixed_ip_address(vif, client)"}],"source_content_type":"text/x-python","patch_set":53,"id":"5a5ae5dd_56f3ab0a","line":262,"updated":"2016-02-03 22:02:23.000000000","message":"not sure if you\u0027ll get an error that this isn\u0027t indented enough; it doesn\u0027t look like it is lined up with \u0027node\u0027 above.","commit_id":"fa98c471c8824f7163530fec95f152a13502cceb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"41a2c4503683a4afd44a2093452e08b1e333012f","unresolved":false,"context_lines":[{"line_number":283,"context_line":"                ip_addresses.append(vif_ip_address)"},{"line_number":284,"context_line":"            except (exception.FailedToGetIPAddressOnPort,"},{"line_number":285,"context_line":"                    exception.InvalidIPv4Address):"},{"line_number":286,"context_line":"                    failures.append(obj.uuid)"},{"line_number":287,"context_line":""},{"line_number":288,"context_line":"        if failures:"},{"line_number":289,"context_line":"            obj_name \u003d \u0027portgroups\u0027"}],"source_content_type":"text/x-python","patch_set":53,"id":"5a5ae5dd_54572302","line":286,"updated":"2016-02-03 22:45:58.000000000","message":"overindent","commit_id":"fa98c471c8824f7163530fec95f152a13502cceb"}],"ironic/tests/unit/common/test_network.py":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":37,"context_line":"            result \u003d network.get_node_vif_ids(task)"},{"line_number":38,"context_line":"        self.assertEqual(expected, result)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def test_get_node_vif_ids_no_portgroups(self):"},{"line_number":41,"context_line":"        expected \u003d {\u0027portgroups\u0027: {},"},{"line_number":42,"context_line":"                    \u0027ports\u0027: {}}"},{"line_number":43,"context_line":"        with task_manager.acquire(self.context, self.node.uuid) as task:"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_b1703e41","line":40,"updated":"2016-02-01 19:59:33.000000000","message":"I would be fine if you combined this with the above and called it test_get_node_vif_ids_no_ports_no_portgroups(). But this is OK too.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":37,"context_line":"            result \u003d network.get_node_vif_ids(task)"},{"line_number":38,"context_line":"        self.assertEqual(expected, result)"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    def test_get_node_vif_ids_no_portgroups(self):"},{"line_number":41,"context_line":"        expected \u003d {\u0027portgroups\u0027: {},"},{"line_number":42,"context_line":"                    \u0027ports\u0027: {}}"},{"line_number":43,"context_line":"        with task_manager.acquire(self.context, self.node.uuid) as task:"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_1b133e0f","line":40,"in_reply_to":"7a5de9d1_b1703e41","updated":"2016-02-03 21:29:03.000000000","message":"I think there is no need to duplicate the code.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"}],"ironic/tests/unit/dhcp/test_neutron.py":[{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        }"},{"line_number":271,"context_line":"        fake_client \u003d mock.Mock()"},{"line_number":272,"context_line":"        fake_client.show_port.return_value \u003d {\u0027port\u0027: port_data,"},{"line_number":273,"context_line":"                                              \u0027portgroups\u0027: {}}"},{"line_number":274,"context_line":"        result \u003d api._get_fixed_ip_address(port_id, fake_client)"},{"line_number":275,"context_line":"        self.assertEqual(expected, result)"},{"line_number":276,"context_line":"        fake_client.show_port.assert_called_once_with(port_id)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_dc3dd1c4","line":273,"updated":"2016-02-01 19:59:33.000000000","message":"so the neutron client is going to return a response like this?","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":270,"context_line":"        }"},{"line_number":271,"context_line":"        fake_client \u003d mock.Mock()"},{"line_number":272,"context_line":"        fake_client.show_port.return_value \u003d {\u0027port\u0027: port_data,"},{"line_number":273,"context_line":"                                              \u0027portgroups\u0027: {}}"},{"line_number":274,"context_line":"        result \u003d api._get_fixed_ip_address(port_id, fake_client)"},{"line_number":275,"context_line":"        self.assertEqual(expected, result)"},{"line_number":276,"context_line":"        fake_client.show_port.assert_called_once_with(port_id)"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_bb530a6c","line":273,"in_reply_to":"7a5de9d1_dc3dd1c4","updated":"2016-02-03 21:29:03.000000000","message":"no, I did this mistakenly.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":414,"context_line":"        with task_manager.acquire(self.context, self.node.uuid) as task:"},{"line_number":415,"context_line":"            api \u003d dhcp_factory.DHCPFactory().provider"},{"line_number":416,"context_line":"            result \u003d api._get_ip_addresses(task, [pg], mock.sentinel.client)"},{"line_number":417,"context_line":"        self.assertEqual(expected, result)"},{"line_number":418,"context_line":""},{"line_number":419,"context_line":"    @mock.patch(\u0027ironic.dhcp.neutron.NeutronDHCPApi._get_port_ip_address\u0027)"},{"line_number":420,"context_line":"    def test_get_ip_addresses(self, get_ip_mock):"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_fc244d0d","line":417,"updated":"2016-02-01 19:59:33.000000000","message":"A lot of these tests seem to be copy/paste except for the actual object. Seems like we could have helper functions that eg take a method to create an object, and call them with object_utils.create_test_portgroup and object_utils.create_test_port.\n\nJust a thought though.","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":6618,"name":"Ruby Loo","email":"opensrloo@gmail.com","username":"rloo"},"change_message_id":"6e2b8b1bf9732f1ca4f854f50c234b427735f6b2","unresolved":false,"context_lines":[{"line_number":428,"context_line":"            result \u003d api.get_ip_addresses(task)"},{"line_number":429,"context_line":"            get_ip_mock.assert_called_once_with(task, task.ports[0],"},{"line_number":430,"context_line":"                                                mock.ANY)"},{"line_number":431,"context_line":"        self.assertEqual(expected, result)"},{"line_number":432,"context_line":""},{"line_number":433,"context_line":"    @mock.patch.object(client.Client, \u0027create_port\u0027)"},{"line_number":434,"context_line":"    def test_create_cleaning_ports(self, create_mock):"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_9cc3d937","line":431,"updated":"2016-02-01 19:59:33.000000000","message":"shouldn\u0027t we enhance this test (or add a new one) to show that it handles task.ports and task.portgroups?","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"},{"author":{"_account_id":14525,"name":"Vasyl Saienko","email":"vsaienko@mirantis.com","username":"vsaienko"},"change_message_id":"43c00c2e6d0da402b566e6043292c5b4d00e4585","unresolved":false,"context_lines":[{"line_number":428,"context_line":"            result \u003d api.get_ip_addresses(task)"},{"line_number":429,"context_line":"            get_ip_mock.assert_called_once_with(task, task.ports[0],"},{"line_number":430,"context_line":"                                                mock.ANY)"},{"line_number":431,"context_line":"        self.assertEqual(expected, result)"},{"line_number":432,"context_line":""},{"line_number":433,"context_line":"    @mock.patch.object(client.Client, \u0027create_port\u0027)"},{"line_number":434,"context_line":"    def test_create_cleaning_ports(self, create_mock):"}],"source_content_type":"text/x-python","patch_set":52,"id":"7a5de9d1_342ac7e8","line":431,"in_reply_to":"7a5de9d1_9cc3d937","updated":"2016-02-03 21:29:03.000000000","message":"Done","commit_id":"544de53f6d9ba2eae2b251906ece305e121ee138"}]}
