""" Commonly used general functions. This module provides the following methods: - `hostname`: get the current machine's hostname - `getlocaldomain`: get the current machine's domain name - `resolve`: attempt to convert a local/public IP to hostname - `readlog`: read contents of a log file from disk """ from datetime import datetime, timedelta import inspect import logging import os from pkg_resources import Requirement, resource_filename import re import socket from systemd import journal from logparse import config logger = logging.getLogger(__name__) def hostname(path): # get the hostname of current server """ Get the hostname of the current machine using the file supplied in the `hostname-path` config option. """ hnfile = open(path, 'r') hn = re.search('^(\w*)\n*', hnfile.read()).group(1) return hn def getlocaldomain(): # get the parent fqdn of current server """ Get parent domain name (possibly FQDN) of the current machine. Note: if `socket.fetfqdn()` returns localhost, make sure the first entry in the hostname file includes the FQDN. """ domain = socket.getfqdn().split('.', 1) if len(domain) != 2: logger.warning("Could not get domain of this server, only hostname. Please consider updating the hostname file at {0}".format(config.prefs.get("logparse", "hostname-path"))) return 'localdomain' else: return domain[-1] def resolve(ip, fqdn=None): # try to resolve an ip to hostname """ Attempt to resolve an IP into a hostname or FQDN. Possible values for fqdn: - fqdn show full hostname and domain - fqdn-implicit show hostname and domain unless local - host-only only show hostname - ip never resolve anything Note resolve-domains settings defined in individual sections of the config take priority over the global config (this is enforced in parser modules) """ if not fqdn: fqdn = config.prefs.get("logparse", "resolve-domains") if fqdn == 'ip': return(ip) try: socket.inet_aton(ip) # succeeds if text contains ip hn = socket.gethostbyaddr(ip)[0] # resolve ip to hostname if fqdn == 'fqdn-implicit' and hn.split('.', 1)[1] == getlocaldomain(): return(hn.split('.')[0]) elif fqdn == 'fqdn' or fqdn == 'fqdn-implicit': return(hn) elif fqdn == 'host-only': return(hn.split('.')[0]) else: logger.warning("Invalid value for FQDN config") return(hn) except socket.herror: # cannot resolve ip logger.debug(ip + " cannot be found, might not exist anymore") return(ip) except (OSError, socket.error): # socket.error for Python 2 compatibility # already a hostname logger.debug(ip + " is already a hostname") return(ip) except Exception as err: logger.warning("failed to resolve hostname for " + ip + ": " + str(err)) return(ip) # return ip if no hostname exists def readlog(path = None, mode = 'r'): """ Read a logfile from disk and return string """ if (path == None): logger.error("No path provided") return 1 else: if (os.path.isfile(path) is False): logger.error("Log at {0} was requested but does not exist".format(path)) return '' else: try: return open(path, mode).read() except IOError or OSError as e: logger.warning("Error reading log at {0}: {1}".format(path, e.strerror)) return 1