)]}'
{"nova/tests/unit/virt/ironic/test_driver.py":[{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1504,"context_line":"        self.assertFalse(mock_update.called)"},{"line_number":1505,"context_line":""},{"line_number":1506,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1507,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1508,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1509,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1510,"context_line":"    def test_attach_interface(self, mock_node, mock_lp, mock_neutron_gc,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_9bbd09da","line":1507,"updated":"2016-08-09 15:39:29.000000000","message":"You can remove the return_value\u003dmock.Mock() since that is the default return value of any mocked method.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1504,"context_line":"        self.assertFalse(mock_update.called)"},{"line_number":1505,"context_line":""},{"line_number":1506,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1507,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1508,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1509,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1510,"context_line":"    def test_attach_interface(self, mock_node, mock_lp, mock_neutron_gc,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_52f89a49","line":1507,"in_reply_to":"9ad45d7e_9bbd09da","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1509,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1510,"context_line":"    def test_attach_interface(self, mock_node, mock_lp, mock_neutron_gc,"},{"line_number":1511,"context_line":"                              mock_pvifs):"},{"line_number":1512,"context_line":"        node_uuid \u003d \u0027aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\u0027"},{"line_number":1513,"context_line":"        node \u003d ironic_utils.get_test_node(uuid\u003dnode_uuid)"},{"line_number":1514,"context_line":"        port_address \u003d \u002700:00:00:00:00:00\u0027"},{"line_number":1515,"context_line":"        port \u003d ironic_utils.get_test_port(extra\u003d{}, address\u003dport_address)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_fbb405f3","line":1512,"updated":"2016-08-09 15:39:29.000000000","message":"Instead of specifying a uuid like above, you can do:\n\n from nova.test import uuidsentinel as uuids\n ...\n\n node \u003d ironic_utils.get_test_node(uuid\u003duuids.node)\n\n and just replace all your references to the node_uuid variable with uuids.node.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1509,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1510,"context_line":"    def test_attach_interface(self, mock_node, mock_lp, mock_neutron_gc,"},{"line_number":1511,"context_line":"                              mock_pvifs):"},{"line_number":1512,"context_line":"        node_uuid \u003d \u0027aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\u0027"},{"line_number":1513,"context_line":"        node \u003d ironic_utils.get_test_node(uuid\u003dnode_uuid)"},{"line_number":1514,"context_line":"        port_address \u003d \u002700:00:00:00:00:00\u0027"},{"line_number":1515,"context_line":"        port \u003d ironic_utils.get_test_port(extra\u003d{}, address\u003dport_address)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_92bfb25f","line":1512,"in_reply_to":"9ad45d7e_fbb405f3","updated":"2016-08-16 12:38:18.000000000","message":"This can be done for all tests in separate change.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1517,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1518,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1519,"context_line":""},{"line_number":1520,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1521,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1522,"context_line":""},{"line_number":1523,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_dbb781f3","line":1520,"updated":"2016-08-09 15:39:29.000000000","message":"Just put:\n\n mock_client \u003d mock_neutron_gc.return_value","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1517,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1518,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1519,"context_line":""},{"line_number":1520,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1521,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1522,"context_line":""},{"line_number":1523,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_32787ec4","line":1520,"in_reply_to":"9ad45d7e_dbb781f3","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1535,"context_line":"        mock_pvifs.assert_called_once_with(instance, ni)"},{"line_number":1536,"context_line":""},{"line_number":1537,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1538,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1539,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1540,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1541,"context_line":"    def test_attach_interface_to_specified_port(self, mock_node, mock_lp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_3bcfbd80","line":1538,"updated":"2016-08-09 15:39:29.000000000","message":"ditto","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1535,"context_line":"        mock_pvifs.assert_called_once_with(instance, ni)"},{"line_number":1536,"context_line":""},{"line_number":1537,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1538,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1539,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1540,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1541,"context_line":"    def test_attach_interface_to_specified_port(self, mock_node, mock_lp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_d2700adf","line":1538,"in_reply_to":"9ad45d7e_3bcfbd80","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1550,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1551,"context_line":"        mock_node.list_ports.return_value \u003d [port1, port2]"},{"line_number":1552,"context_line":""},{"line_number":1553,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1554,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1555,"context_line":""},{"line_number":1556,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_1bcab96e","line":1553,"updated":"2016-08-09 15:39:29.000000000","message":"ditto from above.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1550,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1551,"context_line":"        mock_node.list_ports.return_value \u003d [port1, port2]"},{"line_number":1552,"context_line":""},{"line_number":1553,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1554,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1555,"context_line":""},{"line_number":1556,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_9234d2fb","line":1553,"in_reply_to":"9ad45d7e_1bcab96e","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1568,"context_line":"        mock_pvifs.assert_called_once_with(instance, ni)"},{"line_number":1569,"context_line":""},{"line_number":1570,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1571,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1572,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1573,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1574,"context_line":"    def test_attach_interface_no_available_ports(self, mock_node, mock_lp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_7bc93578","line":1571,"updated":"2016-08-09 15:39:29.000000000","message":"ditto","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1568,"context_line":"        mock_pvifs.assert_called_once_with(instance, ni)"},{"line_number":1569,"context_line":""},{"line_number":1570,"context_line":"    @mock.patch.object(ironic_driver.IronicDriver, \u0027plug_vifs\u0027)"},{"line_number":1571,"context_line":"    @mock.patch.object(neutronapi, \u0027get_client\u0027, return_value\u003dmock.Mock())"},{"line_number":1572,"context_line":"    @mock.patch.object(FAKE_CLIENT.node, \u0027list_ports\u0027)"},{"line_number":1573,"context_line":"    @mock.patch.object(FAKE_CLIENT, \u0027node\u0027)"},{"line_number":1574,"context_line":"    def test_attach_interface_no_available_ports(self, mock_node, mock_lp,"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_d23e4ad9","line":1571,"in_reply_to":"9ad45d7e_7bc93578","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1580,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1581,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1582,"context_line":""},{"line_number":1583,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1584,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1585,"context_line":""},{"line_number":1586,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_5bc4315e","line":1583,"updated":"2016-08-09 15:39:29.000000000","message":"ditto","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1580,"context_line":"        mock_node.get.return_value \u003d node"},{"line_number":1581,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1582,"context_line":""},{"line_number":1583,"context_line":"        mock_client \u003d mock_neutron_gc()"},{"line_number":1584,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1585,"context_line":""},{"line_number":1586,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_3226bece","line":1583,"in_reply_to":"9ad45d7e_5bc4315e","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1585,"context_line":""},{"line_number":1586,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1587,"context_line":"        ni \u003d utils.get_test_network_info()"},{"line_number":1588,"context_line":"        self.assertRaises(exception.NovaException,"},{"line_number":1589,"context_line":"                          self.driver.attach_interface, instance, None, ni[0])"},{"line_number":1590,"context_line":"        self.assertFalse(mock_client.update_port.called)"},{"line_number":1591,"context_line":"        self.assertFalse(mock_pvifs.called)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_bba1edab","line":1588,"updated":"2016-08-09 15:39:29.000000000","message":"Can we be more specific than NovaException here please?","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1585,"context_line":""},{"line_number":1586,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1587,"context_line":"        ni \u003d utils.get_test_network_info()"},{"line_number":1588,"context_line":"        self.assertRaises(exception.NovaException,"},{"line_number":1589,"context_line":"                          self.driver.attach_interface, instance, None, ni[0])"},{"line_number":1590,"context_line":"        self.assertFalse(mock_client.update_port.called)"},{"line_number":1591,"context_line":"        self.assertFalse(mock_pvifs.called)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_ca4dea73","line":1588,"in_reply_to":"9ad45d7e_bba1edab","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1612,"context_line":""},{"line_number":1613,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1614,"context_line":"        ni \u003d utils.get_test_network_info()"},{"line_number":1615,"context_line":"        self.assertRaises(exception.NovaException,"},{"line_number":1616,"context_line":"                          self.driver.attach_interface, instance, None, ni[0])"},{"line_number":1617,"context_line":"        self.assertFalse(mock_client.update_port.called)"},{"line_number":1618,"context_line":"        self.assertFalse(mock_pvifs.called)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_9ba4e9b9","line":1615,"updated":"2016-08-09 15:39:29.000000000","message":"Please provide a more specific exception to catch than NovaException","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1612,"context_line":""},{"line_number":1613,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1614,"context_line":"        ni \u003d utils.get_test_network_info()"},{"line_number":1615,"context_line":"        self.assertRaises(exception.NovaException,"},{"line_number":1616,"context_line":"                          self.driver.attach_interface, instance, None, ni[0])"},{"line_number":1617,"context_line":"        self.assertFalse(mock_client.update_port.called)"},{"line_number":1618,"context_line":"        self.assertFalse(mock_pvifs.called)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_6a3036e9","line":1615,"in_reply_to":"9ad45d7e_9ba4e9b9","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14ec79c1ab3976a28713e6d7b64c540f89116f4a","unresolved":false,"context_lines":[{"line_number":1543,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1544,"context_line":""},{"line_number":1545,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1546,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1547,"context_line":""},{"line_number":1548,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1549,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_971ab97b","line":1546,"updated":"2016-08-17 12:33:46.000000000","message":"above line isn\u0027t needed.","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"a80a5447aa983fa4c1b5165b236481c9d8a1f534","unresolved":false,"context_lines":[{"line_number":1543,"context_line":"        mock_node.list_ports.return_value \u003d [port]"},{"line_number":1544,"context_line":""},{"line_number":1545,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1546,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1547,"context_line":""},{"line_number":1548,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1549,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_b2cd43b9","line":1546,"in_reply_to":"3ac371cc_971ab97b","updated":"2016-08-17 12:38:27.000000000","message":"Done","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14ec79c1ab3976a28713e6d7b64c540f89116f4a","unresolved":false,"context_lines":[{"line_number":1576,"context_line":"        mock_node.list_ports.return_value \u003d [port1, port2]"},{"line_number":1577,"context_line":""},{"line_number":1578,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1579,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1580,"context_line":""},{"line_number":1581,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1582,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_771f3d6c","line":1579,"updated":"2016-08-17 12:33:46.000000000","message":"the above line isn\u0027t needed.","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"a80a5447aa983fa4c1b5165b236481c9d8a1f534","unresolved":false,"context_lines":[{"line_number":1576,"context_line":"        mock_node.list_ports.return_value \u003d [port1, port2]"},{"line_number":1577,"context_line":""},{"line_number":1578,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1579,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1580,"context_line":""},{"line_number":1581,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1582,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_52bdef00","line":1579,"in_reply_to":"3ac371cc_771f3d6c","updated":"2016-08-17 12:38:27.000000000","message":"Done","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14ec79c1ab3976a28713e6d7b64c540f89116f4a","unresolved":false,"context_lines":[{"line_number":1633,"context_line":"        mock_node.list_ports.return_value \u003d [port_available, port_specified]"},{"line_number":1634,"context_line":""},{"line_number":1635,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1636,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1637,"context_line":""},{"line_number":1638,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1639,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_d710b15b","line":1636,"updated":"2016-08-17 12:33:46.000000000","message":"above line isn\u0027t needed.","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"a80a5447aa983fa4c1b5165b236481c9d8a1f534","unresolved":false,"context_lines":[{"line_number":1633,"context_line":"        mock_node.list_ports.return_value \u003d [port_available, port_specified]"},{"line_number":1634,"context_line":""},{"line_number":1635,"context_line":"        mock_client \u003d mock_neutron_gc.return_value"},{"line_number":1636,"context_line":"        mock_client.update_port \u003d mock.Mock()"},{"line_number":1637,"context_line":""},{"line_number":1638,"context_line":"        instance \u003d fake_instance.fake_instance_obj(self.ctx, node\u003dnode_uuid)"},{"line_number":1639,"context_line":"        ni \u003d utils.get_test_network_info()"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_923927a7","line":1636,"in_reply_to":"3ac371cc_d710b15b","updated":"2016-08-17 12:38:27.000000000","message":"Done","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"}],"nova/virt/ironic/driver.py":[{"author":{"_account_id":14819,"name":"Timofey Durakov","email":"timofei.nd@gmail.com","username":"tdurakov"},"change_message_id":"9cf77d1ea37b27185dbb3a9cacb3eac6f2882b68","unresolved":false,"context_lines":[{"line_number":1175,"context_line":"        return super(IronicDriver, self).network_binding_host_id("},{"line_number":1176,"context_line":"            context, instance)"},{"line_number":1177,"context_line":""},{"line_number":1178,"context_line":"    def attach_interface(self, instance, image_meta, vif):"},{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9ad45d7e_ed34a14b","line":1178,"range":{"start_line":1178,"start_character":8,"end_line":1178,"end_character":24},"updated":"2016-08-08 09:31:26.000000000","message":"could you please add unit-test for that","commit_id":"7baa249913fdb8b5c7dcf952f460807d384c8053"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"73a582325f357740aaf88235dfd803a1cadbd4a2","unresolved":false,"context_lines":[{"line_number":1175,"context_line":"        return super(IronicDriver, self).network_binding_host_id("},{"line_number":1176,"context_line":"            context, instance)"},{"line_number":1177,"context_line":""},{"line_number":1178,"context_line":"    def attach_interface(self, instance, image_meta, vif):"},{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9ad45d7e_246d2b05","line":1178,"range":{"start_line":1178,"start_character":8,"end_line":1178,"end_character":24},"in_reply_to":"9ad45d7e_ed34a14b","updated":"2016-08-08 12:42:48.000000000","message":"Done","commit_id":"7baa249913fdb8b5c7dcf952f460807d384c8053"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1175,"context_line":"        return super(IronicDriver, self).network_binding_host_id("},{"line_number":1176,"context_line":"            context, instance)"},{"line_number":1177,"context_line":""},{"line_number":1178,"context_line":"    def attach_interface(self, instance, image_meta, vif):"},{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_fbab6587","line":1178,"updated":"2016-08-09 15:39:29.000000000","message":"@rpodolyaka: Good point. Not sure it\u0027s worth worrying too much about in this first patch series, though. When the multi-compute patch series lands we can consider the concurrency issues.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"c0bac0d015d6efbd10d7e1c2209a13e142e08d71","unresolved":false,"context_lines":[{"line_number":1175,"context_line":"        return super(IronicDriver, self).network_binding_host_id("},{"line_number":1176,"context_line":"            context, instance)"},{"line_number":1177,"context_line":""},{"line_number":1178,"context_line":"    def attach_interface(self, instance, image_meta, vif):"},{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_f2b6feda","line":1178,"updated":"2016-08-09 10:09:05.000000000","message":"I wonder how this should work in the case of a \u0027clustered\u0027 driver like ironic when there can be possibly more than 1 nova-compute process managing the same instance (I believe, we can do that in Newton, or maybe that\u0027s still on review...). Normally, we would put a @synchronized decorator here, but if my assumption about multiple nova-compute\u0027s managing ironic nodes is true, then it would not help: we can check list_ports() output and do not find a port with the given address and it can possibly be concurrently added one line below.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"},{"line_number":1182,"context_line":"                                               \u0027local_link_connection\u0027,"},{"line_number":1183,"context_line":"                                               \u0027extra\u0027])"},{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_dbae6197","line":1182,"updated":"2016-08-09 15:39:29.000000000","message":"Is there a particular Ironic API microversion that introduces local_link_connection into the response for list ports? If so, we will need to double-check that the minimum ironic API microversion sent from the Ironic virt driver matches this... chat with Vasyl, Vlad or Anton about this.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"f5b8b7b47fa162c4613827ee3d83434f6c5b282b","unresolved":false,"context_lines":[{"line_number":1179,"context_line":"        node \u003d self._get_node(instance.node)"},{"line_number":1180,"context_line":"        ports \u003d self.ironicclient.call(\"node.list_ports\", node.uuid,"},{"line_number":1181,"context_line":"                                       fields\u003d[\u0027address\u0027,"},{"line_number":1182,"context_line":"                                               \u0027local_link_connection\u0027,"},{"line_number":1183,"context_line":"                                               \u0027extra\u0027])"},{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_3a2dcdfe","line":1182,"in_reply_to":"9ad45d7e_dbae6197","updated":"2016-08-10 10:10:15.000000000","message":"local_link_connection was introduced in 1.19\nhttps://github.com/openstack/ironic/blob/master/ironic/api/controllers/v1/versions.py#L51\nironic virt driver already requires 1.20\nhttps://github.com/openstack/nova/blob/master/nova/virt/ironic/client_wrapper.py#L32","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"0339d1ad5a5f3e073c4c17583158f9874d0b32ad","unresolved":false,"context_lines":[{"line_number":1182,"context_line":"                                               \u0027local_link_connection\u0027,"},{"line_number":1183,"context_line":"                                               \u0027extra\u0027])"},{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"},{"line_number":1186,"context_line":"            if \u0027vif_port_id\u0027 in port[0].extra:"},{"line_number":1187,"context_line":"                raise exception.NovaException(\"Port with address %s on node \""},{"line_number":1188,"context_line":"                                              \"%s is already in use.\" %"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_630527c1","line":1185,"updated":"2016-08-09 09:41:06.000000000","message":"This won\u0027t work in py3 as filter returns iterator.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"c0bac0d015d6efbd10d7e1c2209a13e142e08d71","unresolved":false,"context_lines":[{"line_number":1182,"context_line":"                                               \u0027local_link_connection\u0027,"},{"line_number":1183,"context_line":"                                               \u0027extra\u0027])"},{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"},{"line_number":1186,"context_line":"            if \u0027vif_port_id\u0027 in port[0].extra:"},{"line_number":1187,"context_line":"                raise exception.NovaException(\"Port with address %s on node \""},{"line_number":1188,"context_line":"                                              \"%s is already in use.\" %"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_72b04e44","line":1185,"in_reply_to":"9ad45d7e_630527c1","updated":"2016-08-09 10:09:05.000000000","message":"I suggest you use list comprehensions here to make the code py3 compatible and probably a bit more readable:\n\n  ports \u003d [p if p.address \u003d\u003d vif[\u0027address\u0027] for p in self.ironicclient.call(...)]\n  if ports:\n      ...\n\nThe only drawback is that you can\u0027t stop processing a list of ports early once you\u0027ve found the one you need. You could achieve that with something like:\n\n  port \u003d next((p if p.address \u003d\u003d vif[\u0027address\u0027] for p in self.ironicclient.call(...)), None)\n  if port is not None:\n      ...\n\nBut, I think, the latter is less readable.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1182,"context_line":"                                               \u0027local_link_connection\u0027,"},{"line_number":1183,"context_line":"                                               \u0027extra\u0027])"},{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"},{"line_number":1186,"context_line":"            if \u0027vif_port_id\u0027 in port[0].extra:"},{"line_number":1187,"context_line":"                raise exception.NovaException(\"Port with address %s on node \""},{"line_number":1188,"context_line":"                                              \"%s is already in use.\" %"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_79f8164a","line":1185,"in_reply_to":"9ad45d7e_72b04e44","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"},{"line_number":1186,"context_line":"            if \u0027vif_port_id\u0027 in port[0].extra:"},{"line_number":1187,"context_line":"                raise exception.NovaException(\"Port with address %s on node \""},{"line_number":1188,"context_line":"                                              \"%s is already in use.\" %"},{"line_number":1189,"context_line":"                                              (vif[\u0027address\u0027], node.uuid))"},{"line_number":1190,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_3b969d4c","line":1187,"updated":"2016-08-09 15:39:29.000000000","message":"Please raise a more specific exception here. There is already PortInUse that is appropriate to use here:\n\nhttps://github.com/openstack/nova/blob/master/nova/exception.py#L798","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1184,"context_line":"        port \u003d filter(lambda p: p.address \u003d\u003d vif[\u0027address\u0027], ports)"},{"line_number":1185,"context_line":"        if len(port):"},{"line_number":1186,"context_line":"            if \u0027vif_port_id\u0027 in port[0].extra:"},{"line_number":1187,"context_line":"                raise exception.NovaException(\"Port with address %s on node \""},{"line_number":1188,"context_line":"                                              \"%s is already in use.\" %"},{"line_number":1189,"context_line":"                                              (vif[\u0027address\u0027], node.uuid))"},{"line_number":1190,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_ef86f8d9","line":1187,"in_reply_to":"9ad45d7e_3b969d4c","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1189,"context_line":"                                              (vif[\u0027address\u0027], node.uuid))"},{"line_number":1190,"context_line":"        else:"},{"line_number":1191,"context_line":"            port \u003d filter(lambda p: \u0027vif_port_id\u0027 not in p.extra, ports)"},{"line_number":1192,"context_line":"            if not len(port):"},{"line_number":1193,"context_line":"                raise exception.NovaException(\"Node %s has no available \""},{"line_number":1194,"context_line":"                                              \"ports for attach to.\" %"},{"line_number":1195,"context_line":"                                              node.uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_1b911953","line":1192,"updated":"2016-08-09 15:39:29.000000000","message":"Same comment as above about using a list comprehension instead of a filter() expression.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1189,"context_line":"                                              (vif[\u0027address\u0027], node.uuid))"},{"line_number":1190,"context_line":"        else:"},{"line_number":1191,"context_line":"            port \u003d filter(lambda p: \u0027vif_port_id\u0027 not in p.extra, ports)"},{"line_number":1192,"context_line":"            if not len(port):"},{"line_number":1193,"context_line":"                raise exception.NovaException(\"Node %s has no available \""},{"line_number":1194,"context_line":"                                              \"ports for attach to.\" %"},{"line_number":1195,"context_line":"                                              node.uuid)"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_99ab521d","line":1192,"in_reply_to":"9ad45d7e_1b911953","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1190,"context_line":"        else:"},{"line_number":1191,"context_line":"            port \u003d filter(lambda p: \u0027vif_port_id\u0027 not in p.extra, ports)"},{"line_number":1192,"context_line":"            if not len(port):"},{"line_number":1193,"context_line":"                raise exception.NovaException(\"Node %s has no available \""},{"line_number":1194,"context_line":"                                              \"ports for attach to.\" %"},{"line_number":1195,"context_line":"                                              node.uuid)"},{"line_number":1196,"context_line":"        body \u003d {"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_7ba015a0","line":1193,"updated":"2016-08-09 15:39:29.000000000","message":"Please use the existing PortNotFree exception:\n\nhttps://github.com/openstack/nova/blob/master/nova/exception.py#L816","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1190,"context_line":"        else:"},{"line_number":1191,"context_line":"            port \u003d filter(lambda p: \u0027vif_port_id\u0027 not in p.extra, ports)"},{"line_number":1192,"context_line":"            if not len(port):"},{"line_number":1193,"context_line":"                raise exception.NovaException(\"Node %s has no available \""},{"line_number":1194,"context_line":"                                              \"ports for attach to.\" %"},{"line_number":1195,"context_line":"                                              node.uuid)"},{"line_number":1196,"context_line":"        body \u003d {"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_0f8434d2","line":1193,"in_reply_to":"9ad45d7e_7ba015a0","updated":"2016-08-16 12:38:18.000000000","message":"Done","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"55d10097969aa640c9726ad049fc687d182cbd19","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_5b9b9172","line":1213,"updated":"2016-08-09 15:39:29.000000000","message":"Agreed with @rpodolyaka and @avolkov here.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":21813,"name":"Andrey Volkov","email":"m@amadev.ru","username":"avolkov"},"change_message_id":"0339d1ad5a5f3e073c4c17583158f9874d0b32ad","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_efdd7915","line":1213,"updated":"2016-08-09 09:41:06.000000000","message":"We have a possible race here.\n1. ironicclient.list_ports.\n2. neutron.update_port,\n3. plug_vifs (including ironicclient.port_update).\n\nI have several worries:\n- What if between step 1 and 2 (or 1 and 3) another request for port comes?\n- What if step 3 fails? Maybe, we should rollback neutron.update_port?\n\nIMO It would be great if Ironic has a port reservation.  Maybe, it has had it already?","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"f5b8b7b47fa162c4613827ee3d83434f6c5b282b","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_da7c71b7","line":1213,"in_reply_to":"9ad45d7e_5b9b9172","updated":"2016-08-10 10:10:15.000000000","message":"Also _plug_vifs calls list_ports again, perhaps will better to add method plug_vif (single), and call it here instead of plug_vifs.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"3ebb04c323cdd341b4241aa635a5abfbb8ffdbb2","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"3ac371cc_4a3bbad1","line":1213,"in_reply_to":"9ad45d7e_d14eca39","updated":"2016-08-16 12:38:18.000000000","message":"implemented same as in libvirt driver","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"2f802f0c30e509a58814724834f4a800c0d9bad8","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_d14eca39","line":1213,"in_reply_to":"9ad45d7e_da7c71b7","updated":"2016-08-11 14:21:45.000000000","message":"if multiple requests for same interface comes, neutron should update first port and fails on other because after first update port will BOUND.\nif these requests for different interfaces, then we cannot decide that ports will in conflict. For minimize change of conflict we can do _plug_vif first and hope next requests will choose another ironic port or fail because no more ports available.\nAnyway this case has low probability.","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"c0bac0d015d6efbd10d7e1c2209a13e142e08d71","unresolved":false,"context_lines":[{"line_number":1210,"context_line":"        neutron \u003d neutronapi.get_client(context)"},{"line_number":1211,"context_line":"        neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1212,"context_line":"        vif[\u0027address\u0027] \u003d port[0].address"},{"line_number":1213,"context_line":"        self.plug_vifs(instance, [vif])"}],"source_content_type":"text/x-python","patch_set":4,"id":"9ad45d7e_f2c71e10","line":1213,"in_reply_to":"9ad45d7e_efdd7915","updated":"2016-08-09 10:09:05.000000000","message":"neutron.update_port() should probably be the very first action taken (especially if we can get it fail, if this port is already attached to this or another instance, so that we \"serialize\" attachment of interfaces on the neutron side).","commit_id":"0c27a38c5b72698131dc7fb9f19d7ddf8d794fa3"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"14ec79c1ab3976a28713e6d7b64c540f89116f4a","unresolved":false,"context_lines":[{"line_number":1232,"context_line":"            body \u003d {"},{"line_number":1233,"context_line":"                \u0027port\u0027: {"},{"line_number":1234,"context_line":"                    \u0027device_owner\u0027: \u0027baremetal:none\u0027,"},{"line_number":1235,"context_line":"                    \u0027device_id\u0027: node.instance_uuid or node.uuid,"},{"line_number":1236,"context_line":"                    \u0027admin_state_up\u0027: True,"},{"line_number":1237,"context_line":"                    \u0027mac_address\u0027: ports[0].address,"},{"line_number":1238,"context_line":"                    \u0027binding:vnic_type\u0027: \u0027baremetal\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_b715354a","line":1235,"updated":"2016-08-17 12:33:46.000000000","message":"Shouldn\u0027t this always be instance.uuid? if it\u0027s *either* the instance UUID or the node UUID, how would Neutron or Ironic know which is which? Also, node.instance_uuid should *always* be not-None by the time an attach_interface() is called here. So for clarity, I would remove the \"or node.uuid\" part.","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":8259,"name":"Andrey Shestakov","email":"ashestakov@mirantis.com","username":"ashestakov"},"change_message_id":"a80a5447aa983fa4c1b5165b236481c9d8a1f534","unresolved":false,"context_lines":[{"line_number":1232,"context_line":"            body \u003d {"},{"line_number":1233,"context_line":"                \u0027port\u0027: {"},{"line_number":1234,"context_line":"                    \u0027device_owner\u0027: \u0027baremetal:none\u0027,"},{"line_number":1235,"context_line":"                    \u0027device_id\u0027: node.instance_uuid or node.uuid,"},{"line_number":1236,"context_line":"                    \u0027admin_state_up\u0027: True,"},{"line_number":1237,"context_line":"                    \u0027mac_address\u0027: ports[0].address,"},{"line_number":1238,"context_line":"                    \u0027binding:vnic_type\u0027: \u0027baremetal\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"3ac371cc_92ebe712","line":1235,"in_reply_to":"3ac371cc_b715354a","updated":"2016-08-17 12:38:27.000000000","message":"Done","commit_id":"48a89154e4193a0e0d30249dd28de3351c8e095c"},{"author":{"_account_id":6849,"name":"Roman Podoliaka","email":"roman.podoliaka@gmail.com","username":"rpodolyaka"},"change_message_id":"761ad9ce04d5c4d7f685a40ab17da5a6aefa063a","unresolved":false,"context_lines":[{"line_number":1245,"context_line":"            }"},{"line_number":1246,"context_line":"            context \u003d nova_context.get_admin_context()"},{"line_number":1247,"context_line":"            neutron \u003d neutronapi.get_client(context)"},{"line_number":1248,"context_line":"            neutron.update_port(vif[\u0027id\u0027], body)"},{"line_number":1249,"context_line":"        except Exception as e:"},{"line_number":1250,"context_line":"            self.unplug_vifs(instance, [vif])"},{"line_number":1251,"context_line":"            raise exception.PortUpdateFailed(port_id\u003dvif[\u0027id\u0027], reason\u003de)"}],"source_content_type":"text/x-python","patch_set":6,"id":"3ac371cc_d890e145","line":1248,"updated":"2016-08-17 13:43:44.000000000","message":"If I understand this correctly, we currently have a fundamental problem with Neutron API that suffers from the \u0027lost update\u0027 problem: two concurrent requests can try to update the same port and the last one will win, thus the first update will be lost. I don\u0027t see how we can fix this, unless we introduce some sort of optimistic concurrency control into Neutron API and require an e-tag value to be passed (or something like that) to effectively serialize port updates on the Neutron side.\n\nThe bottom line is, it\u0027s a more general problem and we do not have to fix it here.","commit_id":"6f13473072fb5bbfb930973ab43406d8107941b6"}]}
