ZFS_Snapshot_Manager/Disk.py

79 lines
3.4 KiB
Python

from Snapshot import Snapshot
import datetime
class Disk(object):
"""
Keeps snapshots assigned to corresponding disks,
so we can filter by disks and check for disk replica anomalies.
"""
def __init__(self, disk):
"""At init we create empty list we can append Snapshot() objects to"""
self.disk_name = disk
self.snapshots = list()
def add_snapshot(self, snapshot):
"""
After we created Disk() we want to add to it some Snapshot()
This function performs necessary sanity checks to make sure that snapshot is assigned to correct disk
:param snapshot: Snapshot() object we will try to assign to disk
"""
if isinstance(snapshot,Snapshot):
disk = snapshot.get_disk_name()
if snapshot.get_disk_name() == self.disk_name:
self.snapshots.append(snapshot)
else:
raise AssertionError
def get_latest_snapshot_ctime(self):
"""
We look for the latest taken snapshot, so we can check for failures
:return: Epoch time of creation of the most recent snapshot
"""
latest = max(self.snapshots, key=lambda snapshot: snapshot.get_snapshot_creation_time_epoch())
assert isinstance(latest,Snapshot)
return latest.get_snapshot_creation_time_epoch()
def get_snapshot_cumulative_size(self, human_readable = True):
"""
Gets cumulative size of snapshots for the Disk() so we can look if it isn't 0 bytes or too small
:param human_readable: For console app we want to use human-readable size values
:return: cumulative size of snapshots human-readable or if not in bytes
"""
## TODO Probably should add initial disk size to this or make seperate method
if human_readable:
return Snapshot.sizeof_fmt\
(sum(snapshot.get_snapshot_used_size(human_readable=False) for snapshot in self.snapshots))
else:
return sum(snapshot.get_snapshot_used_size(human_readable=False) for snapshot in self.snapshots)
def check_if_old(self):
"""
We check if we received snapshot from the last day
:return: True if we didn't receive snapshot, False if everything is working fine here.
"""
latest_date = self.get_latest_snapshot_ctime()
now = datetime.datetime.now().timestamp()
acceptable_time = 24*60*60 # 1 day
return True if (now - latest_date > acceptable_time) else False
def check_if_zero_bytes(self):
## TODO Check if empty snapshot is for sure bad snapshot. If the last but one isn't empty, it might be ok.
"""
We check if the snapshot is empty. It's probably useless if it is
:return: True if snapshot is zero bytes in size. False, if it's fine.
"""
size = self.get_snapshot_cumulative_size(human_readable=False)
return True if (size == 0) else False
def check_for_problems(self):
## TODO Some verbose information what is probably wrong about latest snapshot.
"""
We combine the factors that make snapshot bad. E.g if snapshot isn't empty but it's old it's still bad.
:return: False if everyhing about latest snapshot is fine. True if something went wrong
"""
return True if any([self.check_if_zero_bytes(), self.check_if_old()]) else False
def __repr__(self):
return self.disk_name + " " + str(self.check_for_problems())