Retrieve servers networking information from Neutron if enabled.

       Should be used when up to date networking information is required,
       and Nova's networking info caching mechanism is not fast enough.

def servers_update_addresses(request, servers, all_tenants=False):
    """Retrieve servers networking information from Neutron if enabled.

       Should be used when up to date networking information is required,
       and Nova's networking info caching mechanism is not fast enough.
    """

    # NOTE(e0ne): we don't need to call neutron if we have no instances
    if not servers:
        return

    # Get all (filtered for relevant servers) information from Neutron
    try:
        # NOTE(e0ne): we need tuple here to work with @memoized decorator.
        # @memoized works with hashable arguments only.
        ports = list_resources_with_long_filters(
            port_list, 'device_id',
            tuple([instance.id for instance in servers]),
            request=request)
        fips = FloatingIpManager(request)
        if fips.is_supported():
            floating_ips = list_resources_with_long_filters(
                fips.list, 'port_id', tuple([port.id for port in ports]),
                all_tenants=all_tenants)
        else:
            floating_ips = []
        # NOTE(e0ne): we need frozenset here to work with @memoized decorator.
        # @memoized works with hashable arguments only
        networks = list_resources_with_long_filters(
            network_list, 'id', frozenset([port.network_id for port in ports]),
            request=request)
    except neutron_exc.NotFound as e:
        LOG.error('Neutron resource does not exist. %s', e)
        return
    except Exception as e:
        LOG.error('Unable to connect to Neutron: %s', e)
        error_message = _('Unable to connect to Neutron.')
        messages.error(request, error_message)
        return

    # Map instance to its ports
    instances_ports = collections.defaultdict(list)
    for port in ports:
        instances_ports[port.device_id].append(port)

    # Map port to its floating ips
    ports_floating_ips = collections.defaultdict(list)
    for fip in floating_ips:
        ports_floating_ips[fip.port_id].append(fip)

    # Map network id to its name
    network_names = dict((network.id, network.name_or_id)
                         for network in networks)

    for server in servers:
        try:
            addresses = _server_get_addresses(
                request,
                server,
                instances_ports,
                ports_floating_ips,
                network_names)
        except Exception as e:
            LOG.error(six.text_type(e))
        else:
            server.addresses = addresses