From b16f404d8c95b7da83b4371a4fcee3f2c6a9754d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Stocki?= Date: Wed, 2 Oct 2019 15:39:35 +0200 Subject: [PATCH] added client interface --- Snapshot.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ zfssm_client.py | 33 +++++++++++++++++++++++------ zfssmd.py | 1 + zfssmd_worker.py | 2 ++ 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 Snapshot.py diff --git a/Snapshot.py b/Snapshot.py new file mode 100644 index 0000000..c2dd35b --- /dev/null +++ b/Snapshot.py @@ -0,0 +1,55 @@ +import re +import datetime + +class Snapshot(object): + def __init__(self, snapshot_string): + self.snapshot_string = snapshot_string + self.snapshot_tuple = self.parse_string_to_table() + ## TODO Dunno if it's useful yet. Probably not + #self.snapshot_name = self.get_snapshot_name() + #self.snapshot_zvol = self.get_snapshot_zvol() + #self.snapshot_creation_time = self.get_snapshot_creation_time() + #self.snaphot_used_size = self.get_snapshot_used_size() + #self.snapshot_referenced_size = self.get_snapshot_referenced_size() + + def __repr__(self): + return self.get_snapshot_name() + + def get_snapshot_string(self): + return self.snapshot_string + + def parse_string_to_table(self): + array = re.split(r'\t+', self.snapshot_string) + return tuple(array) + + ## FIXME Have to precompile regexes for speed. Or maybe use another re method; findall might be slow + def get_snapshot_name(self): + name_str = self.snapshot_tuple[0] + name = re.findall(r"[^/]+$", name_str)[0] + return name + + def get_snapshot_zvol(self): + name_str = self.snapshot_tuple[0] + zvol = re.findall(r"^.*[\\/]", name_str)[0] + return zvol + + def get_snapshot_creation_time(self): + time_epoch = int(self.snapshot_tuple[1]) + return str(datetime.datetime.utcfromtimestamp(time_epoch)) + + def get_snapshot_used_size(self): + used_str = self.snapshot_tuple[2] + return self.sizeof_fmt(int(used_str)) + + def get_snapshot_referenced_size(self): + referenced_str = self.snapshot_tuple[3] + return self.sizeof_fmt(int(referenced_str)) + + @staticmethod + def sizeof_fmt(num, suffix='B'): + ## FIXME WOW taken from stack but it's too fucking slow. Probably because of division. Have to profile + for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']: + if abs(num) < 1024.0: + return "%3.1f%s%s" % (num, unit, suffix) + num /= 1024.0 + return "%.1f%s%s" % (num, 'Yi', suffix) \ No newline at end of file diff --git a/zfssm_client.py b/zfssm_client.py index d083968..812a740 100644 --- a/zfssm_client.py +++ b/zfssm_client.py @@ -1,8 +1,29 @@ import Pyro4 -import datetime +# from argparse import ArgumentParser +## TODO Arguments +from Snapshot import Snapshot -uri = "PYRO:058b7dde9ec53de9235cfc57a07ce17a9eabfce3@./u:/run/zfssmd.sock" -zfssmd_connection = Pyro4.Proxy(uri) -snapshots = zfssmd_connection.get_current_list() -timestamp = (next(iter(snapshots))) -print(datetime.datetime.fromtimestamp(timestamp).isoformat()) \ No newline at end of file +PYRO_URI = "PYRO:058b7dde9ec53de9235cfc57a07ce17a9eabfce3@./u:/run/zfssmd.sock" + +class ZFSSMDClient(object): + def __init__(self, uri=PYRO_URI): + self.uri = uri + self.pyro_conn = Pyro4.Proxy(self.uri) + + ## FIXME Check for old timestamp + + def get_snapshot_list(self): + response = self.pyro_conn.get_current_list() + slist = next(iter(response.values())) + return slist + + def make_snapshot_objects(self): + snapshot_object_list = list() + for snapshot in self.get_snapshot_list(): + snapshot_obj = Snapshot(snapshot) + snapshot_object_list.append(snapshot_obj) + return snapshot_object_list + +objects = (ZFSSMDClient().make_snapshot_objects()) +for o in objects: + print(o.get_snapshot_zvol()+o.get_snapshot_name()+" "+o.get_snapshot_creation_time() + " " + o.get_snapshot_used_size() + " " + o.get_snapshot_referenced_size()) \ No newline at end of file diff --git a/zfssmd.py b/zfssmd.py index a071fea..49ad846 100644 --- a/zfssmd.py +++ b/zfssmd.py @@ -26,6 +26,7 @@ class ZfsSnapshotManagerDaemon(object): ## 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] + # noinspection PyUnusedLocal retval = p.wait() ## TODO Implement retval actions last_refreshed = time.time() self.snapshots = snapshot_list diff --git a/zfssmd_worker.py b/zfssmd_worker.py index ee9608a..a14c490 100644 --- a/zfssmd_worker.py +++ b/zfssmd_worker.py @@ -17,8 +17,10 @@ class ZFSSMDaemonRefresh(object): def run(self): while True: + ## FIXME Rework it as root process cursor if it's even possible to avoid RPC 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)) + ## TODO Check if this doesn't cause CPU locks time.sleep(self.interval) \ No newline at end of file