'Disassociates a floating IP from its fixed IP.
Makes sure everything makes sense then calls _disassociate_floating_ip,
rpc\'ing to correct host if i\'m not it.'

@messaging.expected_exceptions(exception.FloatingIpNotFoundForAddress)
def disassociate_floating_ip(self, context, address, affect_auto_assigned=False):

    floating_ip = objects.FloatingIP.get_by_address(context, address)
    if ((not affect_auto_assigned) and floating_ip.auto_assigned):
        raise exception.CannotDisassociateAutoAssignedFloatingIP()
    self._floating_ip_owned_by_project(context, floating_ip)
    if (not floating_ip.fixed_ip_id):
        floating_address = floating_ip.address
        raise exception.FloatingIpNotAssociated(address=floating_address)
    fixed_ip = objects.FixedIP.get_by_id(context, floating_ip.fixed_ip_id)
    network = objects.Network.get_by_id(context.elevated(), fixed_ip.network_id)
    interface = floating_ip.interface
    if network.multi_host:
        instance = objects.Instance.get_by_uuid(context, fixed_ip.instance_uuid)
        service = objects.Service.get_by_host_and_binary(context.elevated(), instance.host, 'nova-network')
        if (service and self.servicegroup_api.service_is_up(service)):
            host = instance.host
        else:
            host = self.host
            interface = None
    else:
        host = network.host
    if (host == self.host):
        self._disassociate_floating_ip(context, address, interface, fixed_ip.instance_uuid)
    else:
        self.network_rpcapi._disassociate_floating_ip(context, address, interface, host, fixed_ip.instance_uuid)
