From 83c730565efe2823eaae449e777add250b32b828 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Thu, 1 Sep 2016 01:32:59 +0200 Subject: [PATCH] Add support for dynamic DNS resolution in host addresses --- config-sample.py | 17 ++++++++++++ picomon/checks.py | 2 +- picomon/dyndns.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 picomon/dyndns.py diff --git a/config-sample.py b/config-sample.py index 8e75797..0bb9cc1 100644 --- a/config-sample.py +++ b/config-sample.py @@ -60,6 +60,23 @@ unnamed = Host(ipv4='127.0.0.1', ipv6='::1') v6only = Host(ipv6='2001:0DB8::beef') +# Dynamic DNS resolution for the hosts (discouraged but for truly dynamic DNS) +from picomon.dyndns import DynDNS4, DynDNS6 + +dynamic = Host(ipv4=DynDNS4('example.com'), ipv6=DynDNS6('example.com'), + name='example.com') + +# Shorthands for dynamic hosts +from picomon.dyndns import DynHost, DynHost4, DynHost6 + +dynamic2 = DynHost(dns='example.com') +dynamic3 = DynHost('example.com') +dynv4only = DynHost4(dns='example.com') +dynv6only = DynHost6(dns='example.com') + +partdyn = DynHost(dns='example.com', ipv6='::1') + + # Checks ######## diff --git a/picomon/checks.py b/picomon/checks.py index d071419..64c93ba 100644 --- a/picomon/checks.py +++ b/picomon/checks.py @@ -110,7 +110,7 @@ class Check(object): lambda s: "'" + s.replace("'", "'\"'\"'") + "'", command)) try: - p = Popen(command, stdout=PIPE, stderr=PIPE) + p = Popen(map(str, command), stdout=PIPE, stderr=PIPE) except OSError as e: self.errmsg = 'Check not available: ' + e.strerror return False diff --git a/picomon/dyndns.py b/picomon/dyndns.py new file mode 100644 index 0000000..3dfff9c --- /dev/null +++ b/picomon/dyndns.py @@ -0,0 +1,66 @@ +import socket +from .checks import Host + + +class DynDNS(object): + """ + mimicks a str() but resolves a host to an IP + + >>> x=DynDNS('localhost') + >>> print(x) + 127.0.0.1 + >>> print(x.replace('.', ' ')) + 127 0 0 1 + >>> x == 'localhost' + True + >>> x == '127.0.0.1' + True + """ + + def __init__(self, host, family=0): + self._host = host + self._family = family + + def __str__(self): + """ pick up the first matching address """ + return socket.getaddrinfo(self._host, None, self._family)[0][4][0] + + def __repr__(self): + return str(self) + + def __eq__(self, other): + """ consider equality if host or string representation match """ + if isinstance(other, type(self)) and self._host == other._host: + return True + + other_str = str(other) + return self._host == other_str or str(self) == other_str + + def __getattr__(self, attr): + return getattr(str(self), attr) + + +class DynDNS4(DynDNS): + def __init__(self, host): + DynDNS.__init__(self, host, socket.AF_INET) + + +class DynDNS6(DynDNS): + def __init__(self, host): + DynDNS.__init__(self, host, socket.AF_INET6) + + +class DynHost(Host): + def __init__(self, dns, ipv4=None, ipv6=None, name=None): + Host.__init__(self, ipv4=ipv4 or DynDNS4(dns), + ipv6=ipv6 or DynDNS6(dns), name=name or dns) + + +class DynHost4(Host): + def __init__(self, dns, name=None): + Host.__init__(self, ipv4=DynDNS4(dns), name=name or dns) + + +class DynHost6(Host): + def __init__(self, dns): + Host.__init__(self, ipv6=DynDNS6(dns), name=name or dns) -- GitLab