# HG changeset patch # User Tuomo Valkonen # Date 1516372947 0 # Node ID 4cad934aa9ce38269982308c812d955b89853cd9 # Parent e343594c00148f894485bb4460b4e0097babe8f1 Can launch borg now; output not yet processed diff -r e343594c0014 -r 4cad934aa9ce backup.py --- a/backup.py Fri Jan 19 10:41:01 2018 +0000 +++ b/backup.py Fri Jan 19 14:42:27 2018 +0000 @@ -4,6 +4,8 @@ import config from instance import BorgInstance +from queue import Queue +from threading import Thread class Backup: @@ -17,6 +19,9 @@ self.repository=config.check_string(cfg, 'repository', 'Target repository', self.loc) + self.archive_prefix=config.check_string(cfg, 'archive_prefix', + 'Archive prefix', self.loc) + self.archive_template=config.check_string(cfg, 'archive_template', 'Archive template', self.loc) @@ -30,9 +35,13 @@ self.paths=config.check_nonempty_list_of_strings(cfg, 'paths', 'Paths', self.loc) - self.borg_parameters=config.check_list_of_dicts(cfg, 'borg_parameters', - 'Borg parameters', self.loc, - default=[]) + self.create_parameters=config.check_list_of_dicts(cfg, 'create_parameters', + 'Borg parameters', self.loc, + default=[]) + + self.prune_parameters=config.check_list_of_dicts(cfg, 'prune_parameters', + 'Borg parameters', self.loc, + default=[]) def __init__(self, identifier, cfg): @@ -40,20 +49,55 @@ self.__decode_config(cfg) - self.config=config self.lastrun=None - self.current_instance=None + self.borg_instance=None + self.thread=None + + def __block_when_running(self): + assert(self.borg_instance is None and self.thread is None) - def create(self): - if self.current_instance is not None: - raise AssertionError('%s running: cannot launch' % self.loc) + def __listener(self): + for status in iter(self.borg_instance.read, None): + # What to do? + print(status) + # What to do on error + # queue.put({'identifier': instance.identifier, + # 'operation': instance.operation, + # 'status': status}) + + def __launch(self, queue, operation, archive_or_repository, *args): + + inst=BorgInstance(operation, archive_or_repository, *args) + inst.launch() + + t=Thread(target=self.__listener) + t.daemon=True - archive="%s::%s" % (self.repository, self.archive_template) + self.thread=t + self.borg_instance=inst + self.queue=queue + + t.start() + + def create(self, queue): + self.__block_when_running() - inst=BorgInstance(self.identifier, 'create', self.borg_parameters, - archive, self.paths) - print(inst.construct_cmdline()) + archive="%s::%s%s" % (self.repository, + self.archive_prefix, + self.archive_template) + + self.__launch(queue, 'create', archive, + self.create_parameters, self.paths) + + def prune(self, queue): + self.__block_when_running() + self.__launch(queue, 'prune', self.repository, + [{'prefix': self.archive_prefix}] + self.prune_parameters) + + def join(self): + if self.thread: + self.thread.join() diff -r e343594c0014 -r 4cad934aa9ce borgend.py --- a/borgend.py Fri Jan 19 10:41:01 2018 +0000 +++ b/borgend.py Fri Jan 19 14:42:27 2018 +0000 @@ -2,8 +2,8 @@ from backup import Backup from config import settings +from queue import Queue import ui -import queue #import scheduler if __name__ == "__main__": @@ -17,4 +17,7 @@ for i in range(len(backupconfigs)): backups[i]=Backup(i, backupconfigs[i]) -backups[0].create() +queue=Queue() +backups[0].create(queue) + +backups[0].join() diff -r e343594c0014 -r 4cad934aa9ce config.py --- a/config.py Fri Jan 19 10:41:01 2018 +0000 +++ b/config.py Fri Jan 19 14:42:27 2018 +0000 @@ -23,6 +23,7 @@ 'executable': 'borg', 'common_parameters': [], 'create_parameters': [], + 'prune_parameters': [], } } @@ -128,12 +129,16 @@ cfg[field]=fn(cfg, field, field, loc, defa[field]) return cfg + def check_parameters(cmd): + settings['borg']=check_and_set(settings['borg'], cmd+'_parameters', + 'borg', defaults['borg'], + check_list_of_dicts) + settings['borg']=check_and_set(settings['borg'], 'executable', 'borg', defaults['borg'], check_string) - settings['borg']=check_and_set(settings['borg'], 'common_parameters', 'borg', - defaults['borg'], check_list_of_dicts) + check_parameters('common') + check_parameters('create') + check_parameters('prune') - settings['borg']=check_and_set(settings['borg'], 'create_parameters', 'borg', - defaults['borg'], check_list_of_dicts) diff -r e343594c0014 -r 4cad934aa9ce instance.py --- a/instance.py Fri Jan 19 10:41:01 2018 +0000 +++ b/instance.py Fri Jan 19 14:42:27 2018 +0000 @@ -5,25 +5,13 @@ import json from subprocess import Popen, PIPE from config import settings, arglistify -from queue import Queue -from threading import Thread - -def linereader(stream, instance, queue): - # What to do on error? - for line in iter(stream.readline, b''): - status=json.loads(line) - queue.put({'identifier': instance.identifier, - 'operation': instance.operation, - 'status': status}) - out.close() class BorgInstance: - def __init__(self, identifier, operation, args, archive, argsl): - self.identifier=identifier; + def __init__(self, operation, archive_or_repository, args, argsl): self.operation=operation; self.args=args; - self.archive=archive; + self.archive_or_repository=archive_or_repository; self.argsl=argsl; def construct_cmdline(self): @@ -33,22 +21,41 @@ tmp1=self.operation+'_parameters' if tmp1 in settings['borg']: cmd=cmd+arglistify(settings['borg'][tmp1]) - return cmd+arglistify(self.args)+[self.archive]+self.argsl + cmd=cmd+arglistify(self.args)+[self.archive_or_repository]+self.argsl + print(cmd) + return cmd - def launch(self, queue): + def launch(self): # What to do with stderr? Is it needed? self.proc=Popen(self.construct_cmdline(), stdout=PIPE, stderr=PIPE) - linereaderargs=(self.proc.stdout, self, queue) - self.t=Thread(target=linereader, args=linereaderargs) - t.daemon=True - t.start() - def read_output(): - try: - obj=self.queue.get_nowait() - except Empty: - obj=Empty - return obj + def read(self): + line=self.proc.stdout.readline() + if line==b'': + line=self.proc.stderr.readline() + if line==b'': + return None + print('EEE'+str(line)) + return 'error' + else: + print('###' + str(line)) + # # What to do on error? stderr? + status=json.loads(line) + return status + + # for line in iter(stream.readline, b''): + # status=json.loads(line) + # queue.put({'identifier': instance.identifier, + # 'operation': instance.operation, + # 'status': status}) + # out.close() + + # def read_output(): + # try: + # obj=self.queue.get_nowait() + # except Empty: + # obj=Empty + # return obj