'Makes sure we rollback ports and VIFs if we fail updating ports'

@mock.patch('nova.network.neutronv2.api.API._has_port_binding_extension', return_value=True)
@mock.patch('nova.network.neutronv2.api.API._populate_neutron_extension_values')
@mock.patch('nova.network.neutronv2.api.API._update_port', side_effect=(mock.MagicMock(), exception.PortInUse(port_id=uuids.created_port_id)))
@mock.patch.object(objects.VirtualInterface, 'create')
@mock.patch.object(objects.VirtualInterface, 'destroy')
@mock.patch('nova.network.neutronv2.api.API._unbind_ports')
@mock.patch('nova.network.neutronv2.api.API._delete_ports')
def test_update_ports_for_instance_fails_rollback_ports_and_vifs(self, mock_delete_ports, mock_unbind_ports, mock_vif_destroy, mock_vif_create, mock_update_port, mock_populate_ext_values, mock_has_port_binding_extension):

    instance = fake_instance.fake_instance_obj(self.context)
    ntrn = mock.Mock(spec='neutronclient.v2_0.client.Client')
    requests_and_created_ports = [(objects.NetworkRequest(network_id=uuids.network_id, port_id=uuids.preexisting_port_id), None), (objects.NetworkRequest(network_id=uuids.network_id, port_id=uuids.created_port_id), uuids.created_port_id)]
    network = {'id': uuids.network_id}
    nets = {uuids.network_id: network}
    self.assertRaises(exception.PortInUse, self.api._update_ports_for_instance, self.context, instance, ntrn, ntrn, requests_and_created_ports, nets, bind_host_id=None, dhcp_opts=None, available_macs=None)
    mock_update_port.assert_has_calls([mock.call(ntrn, instance, uuids.preexisting_port_id, mock.ANY), mock.call(ntrn, instance, uuids.created_port_id, mock.ANY)])
    mock_vif_create.assert_called_once_with()
    mock_vif_destroy.assert_called_once_with()
    mock_unbind_ports.assert_called_once_with(self.context, [uuids.preexisting_port_id], ntrn, ntrn)
    mock_delete_ports.assert_called_once_with(ntrn, instance, [uuids.created_port_id])
