-#
-# utilities.py
-#
-# Commonly used general functions
-#
+"""
+Commonly used general functions.
-import re
+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 ipaddress
+import logging
import os
+from pkg_resources import Requirement, resource_filename
+import re
import socket
-import inspect
+from systemd import journal
-import logging
-logger = logging.getLogger(__name__)
+from logparse import config, formatting
+from logparse.timeparse import timeparse
-from pkg_resources import Requirement, resource_filename
-from . 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
- domain = socket.getfqdn().split('.', 1) # Note: if socket.fetfqdn() returns localhost, make sure the first entry in /etc/hosts contains the fqdn
+ """
+ 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 /etc/hosts')
+ 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 = 'host-only'): # try to resolve an ip to hostname
- # 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
- # resolve-domains defined in individual sections of the config take priority over global config
+
+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['resolve-domains']
+ fqdn = config.prefs.get("logparse", "resolve-domains")
if fqdn == 'ip':
return(ip)
try:
- socket.inet_aton(ip) # succeeds if text contains ip
+ ip_obj = ipaddress.ip_address(ip)
+ except ValueError as err:
+ logger.debug("Invalid format: " + str(err))
+ return ip
+
+ try:
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))
+ 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 file
+ if (fqdn == "host-only") or (fqdn == "fqdn-implicit" and ip_obj.is_private):
+ return hn.split('.')[0]
+ if fqdn == 'fqdn' or fqdn == 'fqdn-implicit':
+ return hn
+ return hn
+
+
+
+def readlog(path = None, mode = 'r'):
+ """
+ Read a logfile from disk and return string
+ """
+
if (path == None):
- logger.error("no path provided")
- return
+ 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))
except IOError or OSError as e:
logger.warning("Error reading log at {0}: {1}".format(path, e.strerror))
return 1
+
+class LogPeriod:
+
+ def __init__(self, section):
+ if config.prefs.get(section.split("_")[0], "period"):
+ self.startdate = datetime.now() - timeparse(config.prefs.get(section.split("_")[0], "period"))
+ logger.debug("Parsing logs for {0} since {1}".format(section, self.startdate.strftime(formatting.DATEFMT + " " + formatting.TIMEFMT)))
+ self.unique = True
+ else:
+ self.startdate = datetime.now() - timeparse(config.prefs.get("logparse", "period"))
+ self.unique = False