mirror of
https://github.com/psy0rz/zfs_autobackup.git
synced 2025-04-11 22:40:01 +03:00
central timehandling and better mocking during test
This commit is contained in:
parent
477e980ba2
commit
5cca819916
@ -4,6 +4,8 @@
|
||||
|
||||
import sys
|
||||
|
||||
import zfs_autobackup.util
|
||||
|
||||
#dirty hack for this error:
|
||||
#AttributeError: module 'collections' has no attribute 'MutableMapping'
|
||||
|
||||
@ -28,6 +30,9 @@ import contextlib
|
||||
import sys
|
||||
import io
|
||||
|
||||
import datetime
|
||||
|
||||
|
||||
TEST_POOLS="test_source1 test_source2 test_target1"
|
||||
ZFS_USERSPACE= subprocess.check_output("dpkg-query -W zfsutils-linux |cut -f2", shell=True).decode('utf-8').rstrip()
|
||||
ZFS_KERNEL= subprocess.check_output("modinfo zfs|grep ^version |sed 's/.* //'", shell=True).decode('utf-8').rstrip()
|
||||
@ -105,3 +110,18 @@ def prepare_zpools():
|
||||
subprocess.check_call("zfs set autobackup:test=child test_source2/fs2", shell=True)
|
||||
|
||||
print("Prepare done")
|
||||
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def mocktime(time_str, format="%Y%m%d%H%M%S"):
|
||||
|
||||
def fake_datetime_now():
|
||||
return datetime.datetime.strptime(time_str, format)
|
||||
|
||||
with patch.object(zfs_autobackup.util,'datetime_now_mock', fake_datetime_now()):
|
||||
yield
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
from basetest import *
|
||||
import time
|
||||
|
||||
class TestZfsAutobackup32(unittest2.TestCase):
|
||||
"""various new 3.2 features"""
|
||||
@ -137,18 +136,39 @@ test_target1/test_source2/fs2/sub@test-20101111000001
|
||||
""")
|
||||
|
||||
|
||||
# def test_stuff(self):
|
||||
#
|
||||
#
|
||||
# shelltest("zfs set autobackup:test=true test_source2")
|
||||
# # shelltest("zfs set readonly=on test_target1")
|
||||
#
|
||||
# with patch('time.strftime', return_value="test-20101111000000"):
|
||||
# self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty --clear-mountpoint".split(" ")).run())
|
||||
#
|
||||
# # shelltest("zfs mount test_target1/test_source2/fs2/sub" )
|
||||
#
|
||||
# with patch('time.strftime', return_value="test-20101111000001"):
|
||||
# self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --verbose --allow-empty --rollback".split(" ")).run())
|
||||
|
||||
|
||||
#XXX: VERBERTERING VAN ADD VIRTUALSNAPSHOTS IN GIT STASH!
|
||||
def test_thinning(self):
|
||||
|
||||
# time_str = "20111112000000" # month in the "future"
|
||||
# future_timestamp = time_secs = time.mktime(time.strptime(time_str, "%Y%m%d%H%M%S"))
|
||||
# with patch('time.time', return_value=future_timestamp):
|
||||
|
||||
with mocktime("20001001000000"):
|
||||
print(datetime_now(False))
|
||||
self.assertFalse(ZfsAutobackup("test --allow-empty --clear-mountpoint --verbose".split(" ")).run())
|
||||
|
||||
# with patch('time.strftime', return_value="test-20001101000000"):
|
||||
# self.assertFalse(ZfsAutobackup("test --allow-empty --clear-mountpoint test_target1 --no-progress --allow-empty --clear-mountpoint".split(" ")).run())
|
||||
#
|
||||
# with patch('time.strftime', return_value="test-20001201000000"):
|
||||
# self.assertFalse(ZfsAutobackup("test --allow-empty --clear-mountpoint".split(" ")).run())
|
||||
#
|
||||
# with patch('time.strftime', return_value="test-20001202000000"):
|
||||
# self.assertFalse(ZfsAutobackup("test --allow-empty --clear-mountpoint".split(" ")).run())
|
||||
#
|
||||
# time_str="test-20001203000000"
|
||||
# with patch('time.time', return_value=time.mktime(time.strptime(time_str, "test-%Y%m%d%H%M%S"))):
|
||||
# with patch('time.strftime', return_value=time_str):
|
||||
# self.assertFalse(ZfsAutobackup("test test_target1 --no-progress --allow-empty --clear-mountpoint --keep-source=1d2d".split(" ")).run())
|
||||
#
|
||||
#
|
||||
#
|
||||
# r=shelltest("zfs list -H -o name -r -t snapshot test_source1 test_target1")
|
||||
# self.assertMultiLineEqual(r,"""
|
||||
# /test_target1
|
||||
# /test_target1/test_source1/fs1
|
||||
# /test_target1/test_source1/fs1/sub
|
||||
# /test_target1/test_source2/fs2/sub
|
||||
# """)
|
||||
|
@ -1,4 +1,3 @@
|
||||
import time
|
||||
|
||||
from .ThinnerRule import ThinnerRule
|
||||
|
||||
@ -37,7 +36,7 @@ class Thinner:
|
||||
|
||||
return ret
|
||||
|
||||
def thin(self, objects, keep_objects=None, now=None):
|
||||
def thin(self, objects, keep_objects, now):
|
||||
"""thin list of objects with current schedule rules. objects: list of
|
||||
objects to thin. every object should have timestamp attribute.
|
||||
|
||||
@ -49,8 +48,6 @@ class Thinner:
|
||||
now: if specified, use this time as current time
|
||||
"""
|
||||
|
||||
if not keep_objects:
|
||||
keep_objects = []
|
||||
|
||||
# always keep a number of the last objets?
|
||||
if self.always_keep:
|
||||
@ -68,9 +65,6 @@ class Thinner:
|
||||
for rule in self.rules:
|
||||
time_blocks[rule.period] = {}
|
||||
|
||||
if not now:
|
||||
now = int(time.time())
|
||||
|
||||
keeps = []
|
||||
removes = []
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import argparse
|
||||
import sys
|
||||
from datetime import time, datetime
|
||||
|
||||
from .CliBase import CliBase
|
||||
from .util import datetime_now
|
||||
|
||||
|
||||
class ZfsAuto(CliBase):
|
||||
@ -59,7 +59,7 @@ class ZfsAuto(CliBase):
|
||||
self.snapshot_time_format = args.snapshot_format.format(args.backup_name)
|
||||
self.hold_name = args.hold_format.format(args.backup_name)
|
||||
|
||||
dt = datetime.utcnow() if args.utc else datetime.now()
|
||||
dt = datetime_now(args.utc)
|
||||
|
||||
self.verbose("")
|
||||
self.verbose("Current time {} : {}".format(args.utc and "UTC" or " ", dt.strftime("%Y-%m-%d %H:%M:%S")))
|
||||
|
@ -1,9 +1,7 @@
|
||||
import time
|
||||
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
from signal import signal, SIGPIPE
|
||||
from .util import output_redir, sigpipe_handler
|
||||
from .util import output_redir, sigpipe_handler, datetime_now
|
||||
|
||||
from .ZfsAuto import ZfsAuto
|
||||
|
||||
@ -203,7 +201,7 @@ class ZfsAutobackup(ZfsAuto):
|
||||
else:
|
||||
# past the deadline?
|
||||
deadline_ttl = ThinnerRule("0s" + self.args.destroy_missing).ttl
|
||||
now = int(time.time())
|
||||
now = datetime_now(self.args.utc).timestamp()
|
||||
if dataset.our_snapshots[-1].timestamp + deadline_ttl > now:
|
||||
dataset.verbose("Destroy missing: Waiting for deadline.")
|
||||
else:
|
||||
@ -461,8 +459,7 @@ class ZfsAutobackup(ZfsAuto):
|
||||
################# snapshotting
|
||||
if not self.args.no_snapshot:
|
||||
self.set_title("Snapshotting")
|
||||
dt = datetime.utcnow() if self.args.utc else datetime.now()
|
||||
snapshot_name = dt.strftime(self.snapshot_time_format)
|
||||
snapshot_name = datetime_now(self.args.utc).strftime(self.snapshot_time_format)
|
||||
source_node.consistent_snapshot(source_datasets, snapshot_name,
|
||||
min_changed_bytes=self.args.min_change,
|
||||
pre_snapshot_cmds=self.args.pre_snapshot_cmd,
|
||||
|
@ -12,6 +12,7 @@ from .CachedProperty import CachedProperty
|
||||
from .ZfsPool import ZfsPool
|
||||
from .ZfsDataset import ZfsDataset
|
||||
from .ExecuteNode import ExecuteError
|
||||
from .util import datetime_now
|
||||
|
||||
|
||||
class ZfsNode(ExecuteNode):
|
||||
@ -59,7 +60,8 @@ class ZfsNode(ExecuteNode):
|
||||
def thin(self, objects, keep_objects):
|
||||
# NOTE: if thinning is disabled with --no-thinning, self.__thinner will be none.
|
||||
if self.__thinner is not None:
|
||||
return self.__thinner.thin(objects, keep_objects)
|
||||
|
||||
return self.__thinner.thin(objects, keep_objects, datetime_now(self.utc))
|
||||
else:
|
||||
return (keep_objects, [])
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
import os.path
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from signal import signal, SIGPIPE
|
||||
|
||||
import util
|
||||
|
||||
signal(SIGPIPE, util.sigpipe_handler)
|
||||
|
||||
|
||||
try:
|
||||
print ("voor eerste")
|
||||
raise Exception("eerstre")
|
||||
except Exception as e:
|
||||
print ("voor tweede")
|
||||
raise Exception("tweede")
|
||||
finally:
|
||||
print ("JO")
|
||||
|
||||
def generator():
|
||||
|
||||
try:
|
||||
util.deb('in generator')
|
||||
print ("TRIGGER SIGPIPE")
|
||||
sys.stdout.flush()
|
||||
util.deb('after trigger')
|
||||
|
||||
# if False:
|
||||
yield ("bla")
|
||||
# yield ("bla")
|
||||
|
||||
except GeneratorExit as e:
|
||||
util.deb('GENEXIT '+str(e))
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
util.deb('EXCEPT '+str(e))
|
||||
finally:
|
||||
util.deb('FINALLY')
|
||||
print("nog iets")
|
||||
sys.stdout.flush()
|
||||
util.deb('after print in finally WOOP!')
|
||||
|
||||
|
||||
util.deb('START')
|
||||
g=generator()
|
||||
util.deb('after generator')
|
||||
for bla in g:
|
||||
# print ("heb wat ontvangen")
|
||||
util.deb('ontvangen van gen')
|
||||
break
|
||||
# raise Exception("moi")
|
||||
|
||||
pass
|
||||
raise Exception("moi")
|
||||
|
||||
util.deb('after for')
|
||||
|
||||
while True:
|
||||
pass
|
||||
|
||||
#
|
||||
# with open('test.py', 'rb') as fh:
|
||||
#
|
||||
# # fsize = fh.seek(10000, os.SEEK_END)
|
||||
# # print(fsize)
|
||||
#
|
||||
# start=time.time()
|
||||
# for i in range(0,1000000):
|
||||
# # fh.seek(0, 0)
|
||||
# fsize=fh.seek(0, os.SEEK_END)
|
||||
# # fsize=fh.tell()
|
||||
# # os.path.getsize('test.py')
|
||||
# print(time.time()-start)
|
||||
#
|
||||
#
|
||||
# print(fh.tell())
|
||||
#
|
||||
# sys.exit(0)
|
||||
#
|
||||
#
|
||||
#
|
||||
# checked=1
|
||||
# skipped=1
|
||||
# coverage=0.1
|
||||
#
|
||||
# max_skip=0
|
||||
#
|
||||
#
|
||||
# skipinarow=0
|
||||
# while True:
|
||||
# total=checked+skipped
|
||||
#
|
||||
# skip=coverage<random()
|
||||
# if skip:
|
||||
# skipped = skipped + 1
|
||||
# print("S {:.2f}%".format(checked * 100 / total))
|
||||
#
|
||||
# skipinarow = skipinarow+1
|
||||
# if skipinarow>max_skip:
|
||||
# max_skip=skipinarow
|
||||
# else:
|
||||
# skipinarow=0
|
||||
# checked=checked+1
|
||||
# print("C {:.2f}%".format(checked * 100 / total))
|
||||
#
|
||||
# print(max_skip)
|
||||
#
|
||||
# skip=0
|
||||
# while True:
|
||||
#
|
||||
# total=checked+skipped
|
||||
# if skip>0:
|
||||
# skip=skip-1
|
||||
# skipped = skipped + 1
|
||||
# print("S {:.2f}%".format(checked * 100 / total))
|
||||
# else:
|
||||
# checked=checked+1
|
||||
# print("C {:.2f}%".format(checked * 100 / total))
|
||||
#
|
||||
# #calc new skip
|
||||
# skip=skip+((1/coverage)-1)*(random()*2)
|
||||
# # print(skip)
|
||||
# if skip> max_skip:
|
||||
# max_skip=skip
|
||||
#
|
||||
# print(max_skip)
|
@ -1,21 +1,9 @@
|
||||
# root@psyt14s:/home/psy/zfs_autobackup# ls -lh /home/psy/Downloads/carimage.zip
|
||||
# -rw-rw-r-- 1 psy psy 990M Nov 26 2020 /home/psy/Downloads/carimage.zip
|
||||
# root@psyt14s:/home/psy/zfs_autobackup# time sha1sum /home/psy/Downloads/carimage.zip
|
||||
# a682e1a36e16fe0d0c2f011104f4a99004f19105 /home/psy/Downloads/carimage.zip
|
||||
#
|
||||
# real 0m2.558s
|
||||
# user 0m2.105s
|
||||
# sys 0m0.448s
|
||||
# root@psyt14s:/home/psy/zfs_autobackup# time python3 -m zfs_autobackup.ZfsCheck
|
||||
#
|
||||
# real 0m1.459s
|
||||
# user 0m0.993s
|
||||
# sys 0m0.462s
|
||||
|
||||
# NOTE: surprisingly sha1 in via python3 is faster than the native sha1sum utility, even in the way we use below!
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def tmp_name(suffix=""):
|
||||
@ -48,7 +36,7 @@ def output_redir():
|
||||
def sigpipe_handler(sig, stack):
|
||||
#redir output so we dont get more SIGPIPES during cleanup. (which my try to write to stdout)
|
||||
output_redir()
|
||||
deb('redir')
|
||||
#deb('redir')
|
||||
|
||||
# def check_output():
|
||||
# """make sure stdout still functions. if its broken, this will trigger a SIGPIPE which will be handled by the sigpipe_handler."""
|
||||
@ -63,3 +51,13 @@ def sigpipe_handler(sig, stack):
|
||||
# fh.write("DEB: "+txt+"\n")
|
||||
|
||||
|
||||
# This should be the only source of trueth for the current datetime.
|
||||
# This function will be mocked during unit testing.
|
||||
|
||||
|
||||
datetime_now_mock=None
|
||||
def datetime_now(utc):
|
||||
if datetime_now_mock is None:
|
||||
return( datetime.utcnow() if utc else datetime.now())
|
||||
else:
|
||||
return datetime_now_mock
|
||||
|
Loading…
x
Reference in New Issue
Block a user