diff --git a/.gitignore b/.gitignore index 44e3cb6..27fdf0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.sqlite3 *.egg-info +__pycache__ diff --git a/netmon/entry.py b/netmon/entry.py new file mode 100644 index 0000000..8cb64e7 --- /dev/null +++ b/netmon/entry.py @@ -0,0 +1,66 @@ +from .ping import Ping +import time +import typing as t +import sqlite3 +import argparse +import logging + + +logger = logging.getLogger(__name__) + + +def record(target: str, interval: int, outage_interval: int): + """Record errors while pinging `target` each `interval` seconds""" + + ping = Ping(target) + db = sqlite3.connect("netmon.sqlite3") + + outage: t.Optional[int] = None + + try: + while True: + res = ping.ping() + if outage is None and not res: # beginning of outage + outage = int(time.time()) + logger.info("Could not reach target.") + + elif outage is not None and res: # end of outage + delta = int(time.time() - outage) + logger.info( + "Could reach target again (out for %d min %d s)", + delta // 60, + delta % 60, + ) + with db: + db.execute( + "INSERT INTO errors (from_time, to_time, host) VALUES (?, ?, ?);", + (int(outage), int(time.time()), target), + ) + time.sleep(interval if outage is None else outage_interval) + except KeyboardInterrupt as exn: + if outage is not None: + with db: + db.execute( + "INSERT INTO errors (from_time, to_time, host) VALUES (?, ?, ?);", + (int(outage), int(time.time()), target), + ) + raise exn + + +def entry(): + parser = argparse.ArgumentParser() + parser.add_argument("host", help="Remote host to ping (IP address preferred)") + parser.add_argument("-i", "--interval", default=30, help="Time between two pings") + parser.add_argument( + "-I", + "--outage-interval", + default=2, + help="Time between two pings while the network is down", + ) + args = parser.parse_args() + + record(args.host, args.interval, args.outage_interval) + + +if __name__ == "__main__": + entry() diff --git a/netmon/ping.py b/netmon/ping.py new file mode 100644 index 0000000..d4475c6 --- /dev/null +++ b/netmon/ping.py @@ -0,0 +1,23 @@ +import subprocess + + +class Ping: + host: str + _cmd: list[str] + + def __init__(self, host: str): + self.host = host + self._cmd = ["/usr/bin/ping", "-c", "1", "-W", "1", "-qn", self.host] + + def ping(self) -> bool: + try: + subprocess.run( + self._cmd, + shell=False, + check=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + return True + except subprocess.CalledProcessError: + return False diff --git a/netmon/py.typed b/netmon/py.typed new file mode 100644 index 0000000..e69de29