Пример #1
0
def _get_ip_lookup_cache() -> IPLookupCache:
    """A file based fall-back DNS cache in case resolution fails"""
    if "ip_lookup" in _config_cache:
        # Return already created and initialized cache
        return IPLookupCache(_config_cache.get("ip_lookup"))

    cache = IPLookupCache(_config_cache.get("ip_lookup"))
    cache.load_persisted()
    return cache
Пример #2
0
def _ip_to_hostname(config_cache: config.ConfigCache,
                    ip: Optional[HostAddress]) -> Optional[HostName]:
    if "ip_to_hostname" not in _config_cache:
        cache = _config_cache.get("ip_to_hostname")

        for host in config_cache.all_active_realhosts():
            host_config = config_cache.get_host_config(host)
            try:
                cache[config.lookup_ip_address(host_config, family=socket.AF_INET)] = host
            except Exception:
                pass
    else:
        cache = _config_cache.get("ip_to_hostname")

    return cache.get(ip)
Пример #3
0
def cached_dns_lookup(
    hostname: HostName,
    *,
    family: socket.AddressFamily,
    is_no_ip_host: bool,
) -> Optional[str]:
    cache = _config_cache.get("cached_dns_lookup")

    cache_id = hostname, family

    # Address has already been resolved in prior call to this function?
    try:
        return cache[cache_id]
    except KeyError:
        pass

    ip_lookup_cache = _get_ip_lookup_cache()

    cached_ip = ip_lookup_cache.get(cache_id)
    if cached_ip and config.use_dns_cache:
        cache[cache_id] = cached_ip
        return cached_ip

    if is_no_ip_host:
        cache[cache_id] = None
        return None

    # Now do the actual DNS lookup
    try:
        ipa = socket.getaddrinfo(hostname, None, family)[0][4][0]

        # Update our cached address if that has changed or was missing
        if ipa != cached_ip:
            console.verbose("Updating %s DNS cache for %s: %s\n" % (family, hostname, ipa))
            ip_lookup_cache.update_cache(cache_id, ipa)

        cache[cache_id] = ipa  # Update in-memory-cache
        return ipa

    except (MKTerminate, MKTimeout):
        # We should be more specific with the exception handler below, then we
        # could drop this special handling here
        raise

    except Exception as e:
        # DNS failed. Use cached IP address if present, even if caching
        # is disabled.
        if cached_ip:
            cache[cache_id] = cached_ip
            return cached_ip
        cache[cache_id] = None
        raise MKIPAddressLookupError("Failed to lookup %s address of %s via DNS: %s" % (
            {
                socket.AF_INET: "IPv4",
                socket.AF_INET6: "IPv6"
            }[family],
            hostname,
            e,
        ))
Пример #4
0
def update_timeperiods_cache() -> None:
    # { "last_update": 1498820128, "timeperiods": [{"24x7": True}] }
    # The value is store within the config cache since we need a fresh start on reload
    tp_cache = _config_cache.get("timeperiods_cache")

    if not tp_cache:
        response = livestatus.LocalConnection().query("GET timeperiods\nColumns: name in")
        for tp_name, tp_active in response:
            tp_cache[tp_name] = bool(tp_active)
Пример #5
0
def timeperiod_active(timeperiod: TimeperiodName) -> Optional[bool]:
    """Returns
    True : active
    False: inactive
    None : unknown timeperiod

    Raises an exception if e.g. a timeout or connection error appears.
    This way errors can be handled upstream."""
    update_timeperiods_cache()
    return _config_cache.get("timeperiods_cache").get(timeperiod)
Пример #6
0
def check_timeperiod(timeperiod: TimeperiodName) -> bool:
    """Check if a timeperiod is currently active. We have no other way than
    doing a Livestatus query. This is not really nice, but if you have a better
    idea, please tell me..."""
    # Let exceptions happen, they will be handled upstream.
    try:
        update_timeperiods_cache()
    except MKTimeout:
        raise

    except Exception:
        if cmk.utils.debug.enabled():
            raise

        # If the query is not successful better skip this check then fail
        return True

    # Note: This also returns True when the timeperiod is unknown
    #       The following function timeperiod_active handles this differently
    return _config_cache.get("timeperiods_cache").get(timeperiod, True)
Пример #7
0
def cached_dns_lookup(
    hostname: HostName,
    *,
    family: socket.AddressFamily,
    force_file_cache_renewal: bool,
) -> Optional[HostAddress]:
    """Cached DNS lookup in *two* caching layers

    1) outer layer (this function):
       A *config cache* that caches all calls until the configuration is changed or runtime ends.
       Other than activating a changed configuration there is no way to remove cached results during
       runtime. Changes made by a differend process will not be noticed.
       This layer caches `None` for lookups that failed, after raising the corresponding exception
       *once*. Subsequent lookups for this hostname / family combination  will not raise an
       exception, until the configuration is changed.

    2) inner layer: see _file_cached_dns_lookup
    """
    cache = _config_cache.get("cached_dns_lookup")
    cache_id = hostname, family

    # Address has already been resolved in prior call to this function?
    try:
        return cache[cache_id]
    except KeyError:
        pass

    try:
        ip_address = _file_cached_dns_lookup(
            hostname,
            family,
            force_file_cache_renewal=force_file_cache_renewal,
        )
    except MKIPAddressLookupError:
        cache[cache_id] = None
        raise

    return cache.setdefault(cache_id, ip_address)
Пример #8
0
def cleanup_timeperiod_caches() -> None:
    _config_cache.get("timeperiods_cache").clear()
Пример #9
0
def cached_dns_lookup(
    hostname: HostName,
    *,
    family: socket.AddressFamily,
    force_file_cache_renewal: bool,
) -> Optional[str]:
    """Cached DNS lookup in *two* caching layers

    1) outer layer:
       A *config cache* that caches all calls until the configuration is changed or runtime ends.
       Other than activating a changed configuration there is no way to remove cached results during
       runtime. Changes made by a differend process will not be noticed.
       This layer caches `None` for lookups that failed, after raising the corresponding exception
       *once*. Subsequent lookups for this hostname / family combination  will not raise an
       exception, until the configuration is changed.

    2) inner layer:
       This layer caches *successful* lookups of host name / IP address
       family combinations, and writes them to a file.
       Note that after the file is loaded initially, the data in the IPLookupCache is keept in sync
       with the file, and itself stored in a dict in the config cache.
       Before a new value is writte to file, the file is re-read, as another process might have
       changed it.
    """
    cache = _config_cache.get("cached_dns_lookup")
    cache_id = hostname, family

    # Address has already been resolved in prior call to this function?
    try:
        return cache[cache_id]
    except KeyError:
        pass

    ip_lookup_cache = _get_ip_lookup_cache()

    cached_ip = ip_lookup_cache.get(cache_id)
    if cached_ip and not force_file_cache_renewal:
        cache[cache_id] = cached_ip
        return cached_ip

    # Now do the actual DNS lookup
    try:
        ipa = socket.getaddrinfo(hostname, None, family)[0][4][0]

        # Update our cached address if that has changed or was missing
        if ipa != cached_ip:
            console.verbose("Updating %s DNS cache for %s: %s\n" %
                            (family, hostname, ipa))
            ip_lookup_cache.update_cache(cache_id, ipa)

        cache[cache_id] = ipa  # Update in-memory-cache
        return ipa

    except (MKTerminate, MKTimeout):
        # We should be more specific with the exception handler below, then we
        # could drop this special handling here
        raise

    except Exception as e:
        # DNS failed. Use cached IP address if present, even if caching
        # is disabled.
        if cached_ip:
            cache[cache_id] = cached_ip
            return cached_ip
        cache[cache_id] = None
        raise MKIPAddressLookupError(
            "Failed to lookup %s address of %s via DNS: %s" % (
                {
                    socket.AF_INET: "IPv4",
                    socket.AF_INET6: "IPv6"
                }[family],
                hostname,
                e,
            ))