From b921a833dcabe404acc4a86f14b702e5a9e22e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Stocki?= Date: Wed, 2 Oct 2019 11:46:30 +0200 Subject: [PATCH] Working Daemon Prototype --- zfssm_client.py | 9 ++++---- zfssmd.py | 55 ++++++++++++++++++++++++++++++++++++++++++------ zfssmd_worker.py | 24 +++++++++++++++++++++ 3 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 zfssmd_worker.py diff --git a/zfssm_client.py b/zfssm_client.py index 0817392..d083968 100644 --- a/zfssm_client.py +++ b/zfssm_client.py @@ -1,9 +1,8 @@ import Pyro4 -import time ## FIXME only debug +import datetime -start = time.time() uri = "PYRO:058b7dde9ec53de9235cfc57a07ce17a9eabfce3@./u:/run/zfssmd.sock" zfssmd_connection = Pyro4.Proxy(uri) -print(zfssmd_connection.get_current_list()) -end=time.time() -print(end-start) +snapshots = zfssmd_connection.get_current_list() +timestamp = (next(iter(snapshots))) +print(datetime.datetime.fromtimestamp(timestamp).isoformat()) \ No newline at end of file diff --git a/zfssmd.py b/zfssmd.py index 288aa9a..a16c2e1 100644 --- a/zfssmd.py +++ b/zfssmd.py @@ -1,28 +1,69 @@ #!/usr/bin/python3 import subprocess import Pyro4 +from pathlib import Path +import logging as log +import signal +import time +from zfssmd_worker import ZFSSM_Daemon_Refresh ENCODING = 'utf-8' +UNIX_SOCK=Path('/run/zfssmd.sock') +UNIX_PID=Path('/run/zfssmd.pid') +CONN_ID='058b7dde9ec53de9235cfc57a07ce17a9eabfce3' class ZfsSnapshotManagerDaemon(object): # TODO docstrings class and methods snapshots = list() + last_refreshed=0 def __init__(self): - self.snapshots = self.call_zfs_list_snapshots() + self.last_refreshed = self.call_zfs_list_snapshots() + @Pyro4.expose def call_zfs_list_snapshots(self): command = ('zfs list -Hp -t snapshot -o name,creation,used,referenced -s name') + ## TODO try except this shit + ## TODO log exec time of this command p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) snapshot_list = [snapshot.decode(ENCODING) for snapshot in p.stdout] retval = p.wait() ## TODO Implement retval actions - return snapshot_list + last_refreshed = time.time() + self.snapshots = snapshot_list + self.last_refreshed = last_refreshed + return last_refreshed @Pyro4.expose def get_current_list(self): - return self.snapshots + return {self.last_refreshed:self.snapshots} # TODO socket start and delete handling + SIGINT handling -daemon = Pyro4.Daemon(port=None,unixsocket='/run/zfssmd.sock') -uri = daemon.register(ZfsSnapshotManagerDaemon(), "058b7dde9ec53de9235cfc57a07ce17a9eabfce3") -print (uri) ## FIXME debug only -daemon.requestLoop() \ No newline at end of file + +def check_start_conditions(): + ## TODO test if already running PID + ## FIXME For now we're just forcing start with deleting sock file first + if (UNIX_SOCK.is_socket() or UNIX_SOCK.is_file()): + try: + UNIX_SOCK.unlink() + except Exception as e: + log.error("Couldn't delete sock file" + str(UNIX_SOCK)) + log.error(e) + raise SystemExit(1) + else: + log.debug("Socket not set. Continuing.") + +def sigterm_handler(_signo, _stack_frame): + log.warning("Received Termination signal. Cleaning up.") + UNIX_SOCK.unlink() + raise SystemExit(0) + +def start_daemon(): + signal.signal(signal.SIGTERM, sigterm_handler) + signal.signal(signal.SIGINT, sigterm_handler) + check_start_conditions() + daemon = Pyro4.Daemon(port=None,unixsocket=str(UNIX_SOCK)) + uri = daemon.register(ZfsSnapshotManagerDaemon(), CONN_ID) + log.info(uri) + ZFSSM_Daemon_Refresh() + daemon.requestLoop() + +start_daemon() \ No newline at end of file diff --git a/zfssmd_worker.py b/zfssmd_worker.py new file mode 100644 index 0000000..dfa9df9 --- /dev/null +++ b/zfssmd_worker.py @@ -0,0 +1,24 @@ +import time +import threading +import Pyro4 +import logging as log + +DEFAULT_REFRESH_INTERVAL=(5 * 60) + +class ZFSSM_Daemon_Refresh(object): + ## TODO Docstrings + def __init__(self, interval=DEFAULT_REFRESH_INTERVAL): + self.interval = interval + + thread = threading.Thread(target=self.run, args=()) + thread.daemon = True + thread.start() + ## TODO make it exit gracefully with daemon + + def run(self): + while True: + uri = "PYRO:058b7dde9ec53de9235cfc57a07ce17a9eabfce3@./u:/run/zfssmd.sock" + zfssmd_connection = Pyro4.Proxy(uri) + last_ref = zfssmd_connection.call_zfs_list_snapshots() + log.debug("Refreshed list " + str(last_ref)) + time.sleep(self.interval) \ No newline at end of file