)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"8e67791ac710d5d13361c4cd1313626ab9e62967","unresolved":false,"context_lines":[{"line_number":16,"context_line":"unplug vifs from portgroups as well as ports."},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"Implements: blueprint ironic-networks-support"},{"line_number":19,"context_line":"DocImpact"},{"line_number":20,"context_line":"Co-Authored-By: Jenny Moorehead (jenny.moorehead@sap.com)"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"Change-Id: Ie0cfd3100d43a55c6eb6b449b75c4f62be5ce2c4"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"1a7b0d38_17c8bc21","line":19,"updated":"2015-12-24 02:27:16.000000000","message":"What is the DocImpact? This likely means we need a reno change in here also.","commit_id":"159d3eac5fd8bb867a6b997cf7467dba79668c9f"}],"nova/tests/unit/virt/ironic/test_client_wrapper.py":[{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"563712b33337bd91c68ecfedc007fecbfbaf2c00","unresolved":false,"context_lines":[{"line_number":103,"context_line":"                    \u0027ironic_url\u0027: CONF.ironic.api_endpoint,"},{"line_number":104,"context_line":"                    \u0027max_retries\u0027: CONF.ironic.api_max_retries,"},{"line_number":105,"context_line":"                    \u0027retry_interval\u0027: CONF.ironic.api_retry_interval,"},{"line_number":106,"context_line":"                    \u0027os_ironic_api_version\u0027: \u00271.8\u0027,"},{"line_number":107,"context_line":"                    \u0027os_cacert\u0027: \u0027fake-cafile\u0027,"},{"line_number":108,"context_line":"                    \u0027ca_file\u0027: \u0027fake-cafile\u0027}"},{"line_number":109,"context_line":"        mock_ir_cli.assert_called_once_with(CONF.ironic.api_version,"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_73408036","line":106,"updated":"2016-06-27 18:11:57.000000000","message":"The version also needs to be modified.","commit_id":"cfb1fbf6619d2f3d8108e0f2d41e7f7c92a8ce05"}],"nova/tests/unit/virt/ironic/test_driver.py":[{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"563712b33337bd91c68ecfedc007fecbfbaf2c00","unresolved":false,"context_lines":[{"line_number":815,"context_line":"                                                   node\u003dnode.uuid)"},{"line_number":816,"context_line":"        result \u003d self.driver.macs_for_instance(instance)"},{"line_number":817,"context_line":"        self.assertEqual(set([portgroup.address]), result)"},{"line_number":818,"context_line":"        mock_node.list_ports.assert_called_once_with(node.uuid)"},{"line_number":819,"context_line":""},{"line_number":820,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":821,"context_line":"    def test_macs_for_instance_with_portgroup_and_lone_port(self, mock_node):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_53690425","line":818,"updated":"2016-06-27 18:11:57.000000000","message":"\u0027detail\u003dTrue\u0027 is necessary for the assertion. Other tests have the same bugs.","commit_id":"cfb1fbf6619d2f3d8108e0f2d41e7f7c92a8ce05"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"78ef07ff44b4408e93f8d7cfcbb0a92290506f6e","unresolved":false,"context_lines":[{"line_number":1416,"context_line":"        node \u003d ironic_utils.get_test_node(uuid\u003dnode_uuid)"},{"line_number":1417,"context_line":"        portgroup \u003d ironic_utils.get_test_portgroup()"},{"line_number":1418,"context_line":"        port \u003d ironic_utils.get_test_port(portgroup_uuid\u003dportgroup.uuid)"},{"line_number":1419,"context_line":"        lone_port \u003d ironic_utils.get_test_port()"},{"line_number":1420,"context_line":""},{"line_number":1421,"context_line":"        mock_lp.return_value \u003d [port, lone_port]"},{"line_number":1422,"context_line":"        mock_lpg.return_value \u003d [portgroup]"}],"source_content_type":"text/x-python","patch_set":11,"id":"9ad45d7e_7f2f53f6","line":1419,"updated":"2016-08-09 20:27:29.000000000","message":"Both the portgroup and the lone port need to have an address field equal to the network_info VIF elements\u0027 address field, otherwise the assertions on mock_port_udt and mock_pg_udt won\u0027t succeed. You get this:\n\n    Traceback (most recent call last):\n      File \"/home/jaypipes/src/git.openstack.org/openstack/nova/.tox/py27/local/lib/python2.7/site-packages/mock/mock.py\", line 1305, in patched\n        return func(*args, **keywargs)\n      File \"nova/tests/unit/virt/ironic/test_driver.py\", line 1463, in test_plug_vifs_with_portgroup_lone_port\n        mock_pg_udt.assert_called_once_with(portgroup.uuid, expected_pg_patch)\n      File \"/home/jaypipes/src/git.openstack.org/openstack/nova/.tox/py27/local/lib/python2.7/site-packages/mock/mock.py\", line 947, in assert_called_once_with\n        raise AssertionError(msg)\n    AssertionError: Expected \u0027update\u0027 to be called once. Called 0 times.\n\nYou need to set the address of both the port and the portgroup to the resulting address of the VIFs from the get_test_network_info() return below on line 1426. Also note you will need to ensure the VIFs for the two networks have different MAC addresses.","commit_id":"ba4cf648d2512a3e42ad5d77b65a16005b395394"}],"nova/tests/unit/virt/ironic/utils.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"78ef07ff44b4408e93f8d7cfcbb0a92290506f6e","unresolved":false,"context_lines":[{"line_number":57,"context_line":"                \u0027node_uuid\u0027: kw.get(\u0027node_uuid\u0027, get_test_node().uuid),"},{"line_number":58,"context_line":"                \u0027address\u0027: kw.get(\u0027address\u0027, \u0027FF:FF:FF:FF:FF:FF\u0027),"},{"line_number":59,"context_line":"                \u0027extra\u0027: kw.get(\u0027extra\u0027, {}),"},{"line_number":60,"context_line":"                \u0027portgroup_uuid\u0027: kw.get(\u0027portgroup_uuid\u0027, None),"},{"line_number":61,"context_line":"                \u0027created_at\u0027: kw.get(\u0027created_at\u0027),"},{"line_number":62,"context_line":"                \u0027updated_at\u0027: kw.get(\u0027updated_at\u0027)})()"},{"line_number":63,"context_line":""}],"source_content_type":"text/x-python","patch_set":11,"id":"9ad45d7e_3fef9bb1","line":60,"updated":"2016-08-09 20:27:29.000000000","message":"fyi, the \", None\" isn\u0027t necessary.","commit_id":"ba4cf648d2512a3e42ad5d77b65a16005b395394"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"78ef07ff44b4408e93f8d7cfcbb0a92290506f6e","unresolved":false,"context_lines":[{"line_number":143,"context_line":"        pass"},{"line_number":144,"context_line":""},{"line_number":145,"context_line":"    def list_portgroups(self, node_uuid):"},{"line_number":146,"context_line":"        return []"},{"line_number":147,"context_line":""},{"line_number":148,"context_line":"    def set_power_state(self, node_uuid, target):"},{"line_number":149,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":11,"id":"9ad45d7e_9f2cc703","line":146,"updated":"2016-08-09 20:27:29.000000000","message":"Seems odd to have list_ports return None and list_portgroups return []?","commit_id":"ba4cf648d2512a3e42ad5d77b65a16005b395394"}],"nova/virt/ironic/client_wrapper.py":[{"author":{"_account_id":10343,"name":"Jim Rollenhagen","email":"jim@jimrollenhagen.com","username":"jimrollenhagen"},"change_message_id":"62686432322201531d86659e0e10cec6eaa0f566","unresolved":false,"context_lines":[{"line_number":31,"context_line":"ironic \u003d None"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"# The API version required by the Ironic driver"},{"line_number":34,"context_line":"IRONIC_API_VERSION \u003d (1, 15)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"class IronicClientWrapper(object):"}],"source_content_type":"text/x-python","patch_set":4,"id":"7a5de9d1_77c5618c","line":34,"updated":"2016-01-28 18:36:02.000000000","message":"apparently this should be 16","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":2889,"name":"Aeva Black","email":"aeva.online@gmail.com","username":"tenbrae"},"change_message_id":"18db4f420509e571911e3c06d6fe3ca9d3e90c53","unresolved":false,"context_lines":[{"line_number":31,"context_line":"ironic \u003d None"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"# The API version required by the Ironic driver"},{"line_number":34,"context_line":"IRONIC_API_VERSION \u003d (1, 15)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"class IronicClientWrapper(object):"}],"source_content_type":"text/x-python","patch_set":4,"id":"7a5de9d1_b7caf99f","line":34,"updated":"2016-01-28 18:37:17.000000000","message":"this should be 1.16 now\n\nhttps://review.openstack.org/#/c/139687/51/ironic/api/controllers/v1/node.py","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":11929,"name":"Michael Turek","email":"mjturek@linux.vnet.ibm.com","username":"mjturek"},"change_message_id":"97dbc23f2e05f8d536577fcb714ed04316affc8d","unresolved":false,"context_lines":[{"line_number":31,"context_line":"ironic \u003d None"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"# The API version required by the Ironic driver"},{"line_number":34,"context_line":"IRONIC_API_VERSION \u003d (1, 15)"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":""},{"line_number":37,"context_line":"class IronicClientWrapper(object):"}],"source_content_type":"text/x-python","patch_set":4,"id":"7aa08908_e75427ff","line":34,"in_reply_to":"7a5de9d1_b7caf99f","updated":"2016-06-13 17:01:58.000000000","message":"Done","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"563712b33337bd91c68ecfedc007fecbfbaf2c00","unresolved":false,"context_lines":[{"line_number":29,"context_line":"ironic \u003d None"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"# The API version required by the Ironic driver"},{"line_number":32,"context_line":"IRONIC_API_VERSION \u003d (1, 16)"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"class IronicClientWrapper(object):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3aaa91ec_7825ff08","line":32,"updated":"2016-06-27 18:11:57.000000000","message":"The version should be synced with the patch[1].\nIt should be 1.20.\n\n[1] https://review.openstack.org/#/c/332177/","commit_id":"cfb1fbf6619d2f3d8108e0f2d41e7f7c92a8ce05"}],"nova/virt/ironic/driver.py":[{"author":{"_account_id":6558,"name":"Sukhdev Kapur","email":"sukhdevkapur@gmail.com","username":"sukhdev-8"},"change_message_id":"dfe00d2fcd7ec2b212e48020817d4b17c8d6b1cf","unresolved":false,"context_lines":[{"line_number":1042,"context_line":""},{"line_number":1043,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":1044,"context_line":""},{"line_number":1045,"context_line":"        loneports \u003d []"},{"line_number":1046,"context_line":"        for port in ports:"},{"line_number":1047,"context_line":"            if ((not CONF.ironic.use_portgroups) or (not port.portgroup_uuid)):"},{"line_number":1048,"context_line":"                loneports.append(port)"}],"source_content_type":"text/x-python","patch_set":1,"id":"1a4dcd0f_2216b1a7","line":1045,"updated":"2015-08-04 23:00:27.000000000","message":"is this collection of physical_ports, right?","commit_id":"7273d90dfd5430667604d08a88d580c5e5cfa795"},{"author":{"_account_id":6558,"name":"Sukhdev Kapur","email":"sukhdevkapur@gmail.com","username":"sukhdev-8"},"change_message_id":"dfe00d2fcd7ec2b212e48020817d4b17c8d6b1cf","unresolved":false,"context_lines":[{"line_number":1056,"context_line":"        else:"},{"line_number":1057,"context_line":"            allports \u003d loneports"},{"line_number":1058,"context_line":""},{"line_number":1059,"context_line":"        if len(network_info) \u003e len(allports):"},{"line_number":1060,"context_line":"            raise exception.VirtualInterfacePlugException(_("},{"line_number":1061,"context_line":"                \"Ironic node: %(id)s virtual to physical interface count\""},{"line_number":1062,"context_line":"                \"  missmatch\""}],"source_content_type":"text/x-python","patch_set":1,"id":"1a4dcd0f_a208812e","line":1059,"updated":"2015-08-04 23:00:27.000000000","message":"With the new design, this restriction should be removed. Why would you not be allowed to have more networks than ports?","commit_id":"7273d90dfd5430667604d08a88d580c5e5cfa795"},{"author":{"_account_id":6558,"name":"Sukhdev Kapur","email":"sukhdevkapur@gmail.com","username":"sukhdev-8"},"change_message_id":"dfe00d2fcd7ec2b212e48020817d4b17c8d6b1cf","unresolved":false,"context_lines":[{"line_number":1068,"context_line":"        if len(network_info) \u003e 0:"},{"line_number":1069,"context_line":"            # not needed if no vif are defined"},{"line_number":1070,"context_line":"            counter \u003d 0"},{"line_number":1071,"context_line":"            for vif, pif in zip(network_info, allports):"},{"line_number":1072,"context_line":"                # attach what neutron needs directly to the port"},{"line_number":1073,"context_line":"                counter \u003d counter + 1"},{"line_number":1074,"context_line":"                port_id \u003d six.text_type(vif[\u0027id\u0027])"}],"source_content_type":"text/x-python","patch_set":1,"id":"1a4dcd0f_c23b4dea","line":1071,"updated":"2015-08-04 23:00:27.000000000","message":"This logic does not seem correct - why would you want to tie the ports and networks this way?\nLooking at the following document, this seems to implement scenario 3 and 10 - which is not supported in initial release\nhttps://docs.google.com/document/d/1a-DX4FQZoX1SdTOd9w_Ug6kCKdY1wfrDcR3SKVhWlcQ/view","commit_id":"7273d90dfd5430667604d08a88d580c5e5cfa795"},{"author":{"_account_id":13997,"name":"SHIGEMATSU Mitsuhiro","email":"shigematsu.mitsuhiro@lab.ntt.co.jp","username":"pshige"},"change_message_id":"94e14f24b2675743c9d62a018b7792f71dea8fb5","unresolved":false,"context_lines":[{"line_number":1080,"context_line":"                else:"},{"line_number":1081,"context_line":"                    self.ironicclient.call(\"port.update\", pif.uuid, patch)"},{"line_number":1082,"context_line":""},{"line_number":1083,"context_line":""},{"line_number":1084,"context_line":""},{"line_number":1085,"context_line":"    def _unplug_vifs(self, node, instance, network_info):"},{"line_number":1086,"context_line":"        # NOTE(PhilDay): Accessing network_info will block if the thread"}],"source_content_type":"text/x-python","patch_set":1,"id":"fa1b9901_37c084e0","line":1083,"updated":"2015-08-22 01:53:26.000000000","message":"too many blank lines","commit_id":"7273d90dfd5430667604d08a88d580c5e5cfa795"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"8e67791ac710d5d13361c4cd1313626ab9e62967","unresolved":false,"context_lines":[{"line_number":97,"context_line":"               default\u003d2,"},{"line_number":98,"context_line":"               help\u003d\u0027How often to retry in seconds when a request \u0027"},{"line_number":99,"context_line":"                    \u0027does conflict\u0027),"},{"line_number":100,"context_line":"    cfg.BoolOpt(\u0027use_portgroups\u0027,"},{"line_number":101,"context_line":"                default\u003dFalse,"},{"line_number":102,"context_line":"                help\u003d\u0027Used for logical port grouping\u0027),"},{"line_number":103,"context_line":"    ]"}],"source_content_type":"text/x-python","patch_set":3,"id":"1a7b0d38_17ef5c88","line":100,"updated":"2015-12-24 02:27:16.000000000","message":"Do we really need a config option for this? Is this for knowing if the ironic we\u0027re talking to supports port-groups? If so, couldn\u0027t we determine that with the API response?","commit_id":"159d3eac5fd8bb867a6b997cf7467dba79668c9f"},{"author":{"_account_id":6637,"name":"Sam Betts","email":"sam@code-smash.net","username":"sambetts"},"change_message_id":"9d3357ff4dcb9b059467948376dee012a658024c","unresolved":false,"context_lines":[{"line_number":698,"context_line":"                macs.append(portgroup.address)"},{"line_number":699,"context_line":""},{"line_number":700,"context_line":"        for port in ports:"},{"line_number":701,"context_line":"            if ((not CONF.ironic.use_portgroups) or (not port.portgroup_uuid)):"},{"line_number":702,"context_line":"                macs.append(port.address)"},{"line_number":703,"context_line":""},{"line_number":704,"context_line":"        if macs:"}],"source_content_type":"text/x-python","patch_set":3,"id":"7a740942_12eddeee","line":701,"updated":"2015-12-07 16:44:24.000000000","message":"Should be portgroup_id not uuid","commit_id":"159d3eac5fd8bb867a6b997cf7467dba79668c9f"},{"author":{"_account_id":6637,"name":"Sam Betts","email":"sam@code-smash.net","username":"sambetts"},"change_message_id":"9d3357ff4dcb9b059467948376dee012a658024c","unresolved":false,"context_lines":[{"line_number":1084,"context_line":""},{"line_number":1085,"context_line":"        loneports \u003d []"},{"line_number":1086,"context_line":"        for port in ports:"},{"line_number":1087,"context_line":"            if ((not CONF.ironic.use_portgroups) or (not port.portgroup_uuid)):"},{"line_number":1088,"context_line":"                loneports.append(port)"},{"line_number":1089,"context_line":""},{"line_number":1090,"context_line":"        number_portgroups \u003d 0"}],"source_content_type":"text/x-python","patch_set":3,"id":"7a740942_52ce0683","line":1087,"updated":"2015-12-07 16:44:24.000000000","message":"ditto","commit_id":"159d3eac5fd8bb867a6b997cf7467dba79668c9f"},{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"482d0efc896d4fd396c15ed9c568c2fc7fcbe0b3","unresolved":false,"context_lines":[{"line_number":646,"context_line":"            node \u003d self.ironicclient.call(\"node.get\", instance.node)"},{"line_number":647,"context_line":"        except ironic.exc.NotFound:"},{"line_number":648,"context_line":"            return None"},{"line_number":649,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":650,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"}],"source_content_type":"text/x-python","patch_set":4,"id":"dae33548_d0fbc5bf","line":649,"updated":"2016-02-17 07:59:22.000000000","message":"\"detail\u003dTrue\" seems necessary to get portgroup_uuid.","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":6637,"name":"Sam Betts","email":"sam@code-smash.net","username":"sambetts"},"change_message_id":"61b5456123b398f19a12033100caf43ac47e65a7","unresolved":false,"context_lines":[{"line_number":646,"context_line":"            node \u003d self.ironicclient.call(\"node.get\", instance.node)"},{"line_number":647,"context_line":"        except ironic.exc.NotFound:"},{"line_number":648,"context_line":"            return None"},{"line_number":649,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":650,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"}],"source_content_type":"text/x-python","patch_set":4,"id":"bae84128_f246b479","line":649,"in_reply_to":"dae33548_d0fbc5bf","updated":"2016-02-23 11:43:56.000000000","message":"+1","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":11929,"name":"Michael Turek","email":"mjturek@linux.vnet.ibm.com","username":"mjturek"},"change_message_id":"97dbc23f2e05f8d536577fcb714ed04316affc8d","unresolved":false,"context_lines":[{"line_number":646,"context_line":"            node \u003d self.ironicclient.call(\"node.get\", instance.node)"},{"line_number":647,"context_line":"        except ironic.exc.NotFound:"},{"line_number":648,"context_line":"            return None"},{"line_number":649,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":650,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"}],"source_content_type":"text/x-python","patch_set":4,"id":"7aa08908_02da01e8","line":649,"in_reply_to":"dae33548_d0fbc5bf","updated":"2016-06-13 17:01:58.000000000","message":"Done","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":13702,"name":"yushiro","username":"yushiro","inactive":true},"change_message_id":"a4f7f84334f69a8854aa07310a68cef77178295d","unresolved":false,"context_lines":[{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":653,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":654,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_uuid])"},{"line_number":655,"context_line":"        return set(macs)"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":"    def _generate_configdrive(self, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3a57f1b5_61955f3d","line":654,"range":{"start_line":654,"start_character":35,"end_line":654,"end_character":69},"updated":"2016-02-12 05:23:34.000000000","message":"self.ironicclient.call(\"node.list_ports\", node.uuid) doesn\u0027t include \u0027portgroup_uuid\u0027 and get an error \"AttributeError\". Only following values are included:\n\n* address\n* links\n* uuid\n\nTherefore, \"ports\" should be changed a list of \u0027port-detail\u0027 object as follows:\n\nports \u003d self._get_ironic_ports_detail(node.uuid)\n\ndef _get_ironic_ports_detail(self, node_uuid):\n    ir_ports \u003d self.ironicclient.call(\"node.list_ports\", node_uuid)\n    ports \u003d [self.ironicclient.call(\"port.get\", p.uuid) for p in ir_ports]\n    return ports\n\nMethod name(_get_ironic_ports_detail) is draft version...","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":6637,"name":"Sam Betts","email":"sam@code-smash.net","username":"sambetts"},"change_message_id":"61b5456123b398f19a12033100caf43ac47e65a7","unresolved":false,"context_lines":[{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":653,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":654,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_uuid])"},{"line_number":655,"context_line":"        return set(macs)"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":"    def _generate_configdrive(self, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":4,"id":"bae84128_b250ac33","line":654,"range":{"start_line":654,"start_character":35,"end_line":654,"end_character":69},"in_reply_to":"3a57f1b5_61955f3d","updated":"2016-02-23 11:43:56.000000000","message":"You can just use:\n\nself.ironicclient.call(\"node.list_ports\", node_uuid, detail\u003dTrue)","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":16066,"name":"xiexs","email":"xiexs@cn.fujitsu.com","username":"simen"},"change_message_id":"5a1a73c1951f6a62dfaaa880ffdccafcbbec0b6f","unresolved":false,"context_lines":[{"line_number":651,"context_line":""},{"line_number":652,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":653,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":654,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_uuid])"},{"line_number":655,"context_line":"        return set(macs)"},{"line_number":656,"context_line":""},{"line_number":657,"context_line":"    def _generate_configdrive(self, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":4,"id":"fa0719c6_a2c55b8f","line":654,"range":{"start_line":654,"start_character":35,"end_line":654,"end_character":69},"in_reply_to":"bae84128_b250ac33","updated":"2016-03-22 09:34:34.000000000","message":"Yes, I agree with Sam.\nAnd I think maybe we can introduce a new interface into ironic layer to get these info directly.","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":13702,"name":"yushiro","username":"yushiro","inactive":true},"change_message_id":"a4f7f84334f69a8854aa07310a68cef77178295d","unresolved":false,"context_lines":[{"line_number":1027,"context_line":"        self._unplug_vifs(node, instance, network_info)"},{"line_number":1028,"context_line":""},{"line_number":1029,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":1030,"context_line":"        ports \u003d [p for p in ports if not p.portgroup_uuid]"},{"line_number":1031,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":1032,"context_line":"        all_ports \u003d portgroups + ports"},{"line_number":1033,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"3a57f1b5_617c7f1f","line":1030,"range":{"start_line":1030,"start_character":28,"end_line":1030,"end_character":58},"updated":"2016-02-12 05:23:34.000000000","message":"Same comment L.654","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":11929,"name":"Michael Turek","email":"mjturek@linux.vnet.ibm.com","username":"mjturek"},"change_message_id":"97dbc23f2e05f8d536577fcb714ed04316affc8d","unresolved":false,"context_lines":[{"line_number":1027,"context_line":"        self._unplug_vifs(node, instance, network_info)"},{"line_number":1028,"context_line":""},{"line_number":1029,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":1030,"context_line":"        ports \u003d [p for p in ports if not p.portgroup_uuid]"},{"line_number":1031,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":1032,"context_line":"        all_ports \u003d portgroups + ports"},{"line_number":1033,"context_line":""}],"source_content_type":"text/x-python","patch_set":4,"id":"7aa08908_978aaa62","line":1030,"range":{"start_line":1030,"start_character":28,"end_line":1030,"end_character":58},"in_reply_to":"3a57f1b5_617c7f1f","updated":"2016-06-13 17:01:58.000000000","message":"Done","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":6610,"name":"Zhenguo Niu","email":"Niu.ZGlinux@gmail.com","username":"niu-zglinux"},"change_message_id":"ff7e2a508c4b17bef88567855cdf6018de1b92f2","unresolved":false,"context_lines":[{"line_number":1026,"context_line":"        # start by ensuring the ports are clear"},{"line_number":1027,"context_line":"        self._unplug_vifs(node, instance, network_info)"},{"line_number":1028,"context_line":""},{"line_number":1029,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid)"},{"line_number":1030,"context_line":"        ports \u003d [p for p in ports if not p.portgroup_uuid]"},{"line_number":1031,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":1032,"context_line":"        all_ports \u003d portgroups + ports"},{"line_number":1033,"context_line":""},{"line_number":1034,"context_line":"        if len(network_info) \u003e len(all_ports):"},{"line_number":1035,"context_line":"            raise exception.VirtualInterfacePlugException(_("}],"source_content_type":"text/x-python","patch_set":4,"id":"7a5de9d1_be0b51d5","line":1032,"range":{"start_line":1029,"start_character":8,"end_line":1032,"end_character":38},"updated":"2016-02-01 08:19:09.000000000","message":"I think this is a very common use case, can we add an api in ironic to expose all ports(portgroups + ports_without_portgroup_uuid) instead of doing this ourselves everytime, or at least a utils function is needed.","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"e16642d09a8e59fd78eb062e2e17aea3768b5ce8","unresolved":false,"context_lines":[{"line_number":1198,"context_line":"        :returns: a string representing the host ID"},{"line_number":1199,"context_line":"        \"\"\""},{"line_number":1200,"context_line":""},{"line_number":1201,"context_line":"        node \u003d self.ironicclient.call(\"node.get\", instance.node)"},{"line_number":1202,"context_line":"        if getattr(node, \u0027network_provider\u0027, \u0027none\u0027) \u003d\u003d \u0027none\u0027:"},{"line_number":1203,"context_line":"            # flat network, go ahead and allow the port to be bound"},{"line_number":1204,"context_line":"            return super(IronicDriver, self).network_binding_host_id("}],"source_content_type":"text/x-python","patch_set":4,"id":"1af94dfe_300f6089","line":1201,"updated":"2016-03-18 08:39:58.000000000","message":"In the latest code, this was replaced with _get_node().\nThis method doesn\u0027t get network_provider(network_interface).\nIt is necessary to fix it when rebasing this code.","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":13689,"name":"Hironori Shiina","email":"Hironori.Shiina@fujitsu.com","username":"shiina"},"change_message_id":"e16642d09a8e59fd78eb062e2e17aea3768b5ce8","unresolved":false,"context_lines":[{"line_number":1199,"context_line":"        \"\"\""},{"line_number":1200,"context_line":""},{"line_number":1201,"context_line":"        node \u003d self.ironicclient.call(\"node.get\", instance.node)"},{"line_number":1202,"context_line":"        if getattr(node, \u0027network_provider\u0027, \u0027none\u0027) \u003d\u003d \u0027none\u0027:"},{"line_number":1203,"context_line":"            # flat network, go ahead and allow the port to be bound"},{"line_number":1204,"context_line":"            return super(IronicDriver, self).network_binding_host_id("},{"line_number":1205,"context_line":"                context, instance)"}],"source_content_type":"text/x-python","patch_set":4,"id":"1af94dfe_7088c8c5","line":1202,"updated":"2016-03-18 08:39:58.000000000","message":"\u0027network_interface\u0027 and \u0027flat\u0027 according to ironic refactoring.","commit_id":"4013d9159942c5f95c32463478621a73cf382c53"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"78ef07ff44b4408e93f8d7cfcbb0a92290506f6e","unresolved":false,"context_lines":[{"line_number":638,"context_line":""},{"line_number":639,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":640,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":641,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_uuid])"},{"line_number":642,"context_line":"        return set(macs)"},{"line_number":643,"context_line":""},{"line_number":644,"context_line":"    def _generate_configdrive(self, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":11,"id":"9ad45d7e_df363f51","line":641,"updated":"2016-08-09 20:27:29.000000000","message":"Note that the field on the Port object is portgroup_id, not portgroup_uuid:\n\nhttps://github.com/openstack/ironic/blob/master/ironic/objects/port.py#L50\n\nSo I\u0027m pretty sure this won\u0027t work on a real non-mocked-out Ironic :)\n\nIt\u0027s also an integer, not a UUID.","commit_id":"ba4cf648d2512a3e42ad5d77b65a16005b395394"},{"author":{"_account_id":10343,"name":"Jim Rollenhagen","email":"jim@jimrollenhagen.com","username":"jimrollenhagen"},"change_message_id":"5c9b70175355b3d06f39ceb25933eb173b7a3d87","unresolved":false,"context_lines":[{"line_number":674,"context_line":""},{"line_number":675,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":676,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":677,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_id])"},{"line_number":678,"context_line":"        return set(macs)"},{"line_number":679,"context_line":""},{"line_number":680,"context_line":"    def _generate_configdrive(self, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":12,"id":"9ad45d7e_056a4a1a","line":677,"updated":"2016-08-09 21:25:06.000000000","message":"@jaypipes: you referred to the objects layer in your comment on the last patchset, but the plan is indeed to have it as portgroup_uuid in the API layer...\n\nSee also https://review.openstack.org/#/c/332177/11/ironic/api/controllers/v1/port.py","commit_id":"4d142b9e489bd4bcb8f1b093d233c69765508ccc"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":687,"context_line":""},{"line_number":688,"context_line":"        macs \u003d [pg.address for pg in portgroups]"},{"line_number":689,"context_line":"        # don\u0027t return mac addresses for ports that are members of a group"},{"line_number":690,"context_line":"        macs.extend([p.address for p in ports if not p.portgroup_id])"},{"line_number":691,"context_line":"        return set(macs)"},{"line_number":692,"context_line":""},{"line_number":693,"context_line":"    def _generate_configdrive(self, context, instance, node, network_info,"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_6ed656f2","line":690,"range":{"start_line":690,"start_character":55,"end_line":690,"end_character":67},"updated":"2016-10-07 15:21:45.000000000","message":"as mentioned by jroll, has to be portgroup_uuid","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":1060,"context_line":""},{"line_number":1061,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1062,"context_line":"                                       detail\u003dTrue)"},{"line_number":1063,"context_line":"        ports \u003d [p for p in ports if not p.portgroup_id]"},{"line_number":1064,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":1065,"context_line":"        all_ports \u003d portgroups + ports"},{"line_number":1066,"context_line":""}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_ee00a668","line":1063,"range":{"start_line":1063,"start_character":43,"end_line":1063,"end_character":55},"updated":"2016-10-07 15:21:45.000000000","message":"ditto","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":1083,"context_line":"                        patch \u003d [{\u0027op\u0027: \u0027add\u0027,"},{"line_number":1084,"context_line":"                                  \u0027path\u0027: \u0027/extra/vif_port_id\u0027,"},{"line_number":1085,"context_line":"                                  \u0027value\u0027: port_id}]"},{"line_number":1086,"context_line":"                        if hasattr(pif, \u0027portgroup_id\u0027):"},{"line_number":1087,"context_line":"                            # this is a port object"},{"line_number":1088,"context_line":"                            self.ironicclient.call(\"port.update\","},{"line_number":1089,"context_line":"                                                   pif.uuid, patch)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_8e2c8203","line":1086,"range":{"start_line":1086,"start_character":41,"end_line":1086,"end_character":53},"updated":"2016-10-07 15:21:45.000000000","message":"ditto","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":1058,"context_line":"        # start by ensuring the ports are clear"},{"line_number":1059,"context_line":"        self._unplug_vifs(node, instance, network_info)"},{"line_number":1060,"context_line":""},{"line_number":1061,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1062,"context_line":"                                       detail\u003dTrue)"},{"line_number":1063,"context_line":"        ports \u003d [p for p in ports if not p.portgroup_id]"},{"line_number":1064,"context_line":"        portgroups \u003d self.ironicclient.call(\u0027node.list_portgroups\u0027, node.uuid)"},{"line_number":1065,"context_line":"        all_ports \u003d portgroups + ports"},{"line_number":1066,"context_line":""},{"line_number":1067,"context_line":"        if len(network_info) \u003e len(all_ports):"},{"line_number":1068,"context_line":"            raise exception.VirtualInterfacePlugException(_("},{"line_number":1069,"context_line":"                \"Ironic node: %(id)s virtual to physical interface count\""},{"line_number":1070,"context_line":"                \"  mismatch\""},{"line_number":1071,"context_line":"                \" (Vif count: %(vif_count)d, Pif count: %(pif_count)d)\")"},{"line_number":1072,"context_line":"                % {\u0027id\u0027: node.uuid,"},{"line_number":1073,"context_line":"                   \u0027vif_count\u0027: len(network_info),"},{"line_number":1074,"context_line":"                   \u0027pif_count\u0027: len(all_ports)})"},{"line_number":1075,"context_line":""},{"line_number":1076,"context_line":"        if len(network_info) \u003e 0:"},{"line_number":1077,"context_line":"            # not needed if no vif are defined"},{"line_number":1078,"context_line":"            for vif in network_info:"},{"line_number":1079,"context_line":"                for pif in all_ports:"},{"line_number":1080,"context_line":"                    if vif[\u0027address\u0027] \u003d\u003d pif.address:"},{"line_number":1081,"context_line":"                        # attach what neutron needs directly to the port"},{"line_number":1082,"context_line":"                        port_id \u003d six.text_type(vif[\u0027id\u0027])"},{"line_number":1083,"context_line":"                        patch \u003d [{\u0027op\u0027: \u0027add\u0027,"},{"line_number":1084,"context_line":"                                  \u0027path\u0027: \u0027/extra/vif_port_id\u0027,"},{"line_number":1085,"context_line":"                                  \u0027value\u0027: port_id}]"},{"line_number":1086,"context_line":"                        if hasattr(pif, \u0027portgroup_id\u0027):"},{"line_number":1087,"context_line":"                            # this is a port object"},{"line_number":1088,"context_line":"                            self.ironicclient.call(\"port.update\","},{"line_number":1089,"context_line":"                                                   pif.uuid, patch)"},{"line_number":1090,"context_line":"                        else:"},{"line_number":1091,"context_line":"                            # it\u0027s a portgroup object"},{"line_number":1092,"context_line":"                            self.ironicclient.call(\"portgroup.update\","},{"line_number":1093,"context_line":"                                                   pif.uuid, patch)"},{"line_number":1094,"context_line":"                        break"},{"line_number":1095,"context_line":""},{"line_number":1096,"context_line":"    def _unplug_vifs(self, node, instance, network_info):"},{"line_number":1097,"context_line":"        # NOTE(PhilDay): Accessing network_info will block if the thread"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_ce804ac2","line":1094,"range":{"start_line":1061,"start_character":8,"end_line":1094,"end_character":29},"updated":"2016-10-07 15:21:45.000000000","message":"This is very similar to _unplug_vifs and can be refactored I think. (the only difference is a patch value and network_info length check?)","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":1106,"context_line":"                                                node.uuid, detail\u003dTrue)"},{"line_number":1107,"context_line":"            ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1108,"context_line":"                                           detail\u003dTrue)"},{"line_number":1109,"context_line":"            ports \u003d [p for p in ports if not p.portgroup_id]"},{"line_number":1110,"context_line":"            all_ports \u003d portgroups + ports"},{"line_number":1111,"context_line":""},{"line_number":1112,"context_line":"            # not needed if no vif are defined"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_0e4152a9","line":1109,"range":{"start_line":1109,"start_character":47,"end_line":1109,"end_character":59},"updated":"2016-10-07 15:21:45.000000000","message":"ditto","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"},{"author":{"_account_id":12356,"name":"Vladyslav Drok","email":"vdrok@mirantis.com","username":"vdrok"},"change_message_id":"6faad4d8e5412f7592b50394f15625a790e76915","unresolved":false,"context_lines":[{"line_number":1115,"context_line":"                    # we can not attach a dict directly"},{"line_number":1116,"context_line":"                    patch \u003d [{\u0027op\u0027: \u0027remove\u0027, \u0027path\u0027: \u0027/extra/vif_port_id\u0027}]"},{"line_number":1117,"context_line":"                    try:"},{"line_number":1118,"context_line":"                        if hasattr(pif, \u0027portgroup_id\u0027):"},{"line_number":1119,"context_line":"                            # this is a port object"},{"line_number":1120,"context_line":"                            self.ironicclient.call(\"port.update\", pif.uuid,"},{"line_number":1121,"context_line":"                                                   patch)"}],"source_content_type":"text/x-python","patch_set":13,"id":"1a95cdbc_4e47dabb","line":1118,"range":{"start_line":1118,"start_character":41,"end_line":1118,"end_character":53},"updated":"2016-10-07 15:21:45.000000000","message":"ditto","commit_id":"d5932a8be3c2980f887053ca273c117652c062cb"}],"releasenotes/notes/ironic-uses-portgroups-f5332c207d88c7df.yaml":[{"author":{"_account_id":10343,"name":"Jim Rollenhagen","email":"jim@jimrollenhagen.com","username":"jimrollenhagen"},"change_message_id":"dba8431ab850333a85d295326048c6e19b11fd90","unresolved":false,"context_lines":[{"line_number":1,"context_line":"---"},{"line_number":2,"context_line":"features:"},{"line_number":3,"context_line":"  - The ironic driver can now utilize ironic\u0027s \"port groups\""},{"line_number":4,"context_line":"    to support LAG and MLAG configurations."}],"source_content_type":"text/x-yaml","patch_set":15,"id":"fa6399be_3e35f845","line":3,"updated":"2016-10-11 11:25:27.000000000","message":"s/port groups/portgroups/\n\nWe should also have a note about the required ironicclient version and ironic API version, after we land that code and know what they are.","commit_id":"60db13ba802d518ddca6ed93663f2ab72585323f"}]}
