backup.py

changeset 74
4f56142e7497
parent 71
a8a5ebb64e02
child 76
4b08fca3ce34
--- a/backup.py	Fri Jan 26 10:35:00 2018 +0000
+++ b/backup.py	Fri Jan 26 19:04:04 2018 +0000
@@ -5,7 +5,6 @@
 import config
 import logging
 import time
-import keyring
 import borgend
 import repository
 from enum import IntEnum
@@ -107,82 +106,47 @@
 class Backup(TerminableThread):
 
     def __decode_config(self, cfg):
-        loc0='backup target %d' % self.identifier
+        loc0='Backup %d' % self.identifier
 
-        self._name=config.check_string(cfg, 'name', 'Name', loc0)
+        self.backup_name=config.check_string(cfg, 'name', 'Name', loc0)
 
-        self.logger=logger.getChild(self._name)
+        logger.debug("Configuring backup '%s'" % self.backup_name)
 
-        self.loc='backup target "%s"' % self._name
+        self.logger=logger.getChild(self.backup_name)
+
+        loc="Backup '%s'" % self.backup_name
 
         reponame=config.check_string(cfg, 'repository',
-                                     'Target repository', self.loc)
+                                     'Target repository', loc)
 
-        self.repository=repository.get_controller(reponame)
+        self.repository=repository.find_repository(reponame)
+        if not self.repository:
+            raise Exception("Repository '%s' not configured" % reponame)
 
         self.archive_prefix=config.check_string(cfg, 'archive_prefix',
-                                                'Archive prefix', self.loc)
+                                                'Archive prefix', loc)
 
         self.archive_template=config.check_string(cfg, 'archive_template',
-                                                  'Archive template', self.loc)
+                                                  'Archive template', loc)
 
         self.backup_interval=config.check_nonneg_int(cfg, 'backup_interval',
-                                                     'Backup interval', self.loc,
+                                                     'Backup interval', loc,
                                                      config.defaults['backup_interval'])
 
         self.retry_interval=config.check_nonneg_int(cfg, 'retry_interval',
-                                                    'Retry interval', self.loc,
+                                                    'Retry interval', loc,
                                                     config.defaults['retry_interval'])
 
-        self.paths=config.check_nonempty_list_of_strings(cfg, 'paths', 'Paths', self.loc)
-
-        self.common_parameters=config.check_list_of_dicts(cfg, 'common_parameters',
-                                                         'Borg parameters', self.loc,
-                                                         default=[])
-
-        self.create_parameters=config.check_list_of_dicts(cfg, 'create_parameters',
-                                                         'Create parameters', self.loc,
-                                                         default=[])
-
-        self.prune_parameters=config.check_list_of_dicts(cfg, 'prune_parameters',
-                                                         'Prune parameters', self.loc,
-                                                         default=[])
-
-        self.__keychain_account=config.check_string(cfg, 'keychain_account',
-                                                    'Keychain account', self.loc,
-                                                    default='')
-
-        self.__passphrase=None
+        self.paths=config.check_nonempty_list_of_strings(cfg, 'paths', 'Paths', loc)
 
-        if config.settings['extract_passphrases_at_startup']:
-            try:
-                self.extract_passphrase()
-            except Exception:
-                pass
+        self.borg_parameters=config.BorgParameters.from_config(cfg, loc)
 
-    def extract_passphrase(self):
-        acc=self.__keychain_account
-        if not self.__passphrase:
-            if acc and acc!='':
-                self.logger.debug('Requesting passphrase')
-                try:
-                    pw=keyring.get_password("borg-backup", acc)
-                except Exception as err:
-                    self.logger.error('Failed to retrieve passphrase')
-                    raise err
-                else:
-                    self.logger.debug('Received passphrase')
-                self.__passphrase=pw
-            else:
-                self.__passphrase=None
-        return self.__passphrase
 
     def __init__(self, identifier, cfg, scheduler):
         self.identifier=identifier
-        self.config=config
         self.__status_update_callback=None
         self.scheduler=scheduler
-        self.logger=None # setup up __decode_config once backup name is known
+        self.logger=None # setup up in __decode_config once backup name is known
 
         self.borg_instance=None
         self.thread_log=None
@@ -197,7 +161,7 @@
 
         self.__decode_config(cfg)
 
-        super().__init__(target = self.__main_thread, name = self._name)
+        super().__init__(target = self.__main_thread, name = self.backup_name)
         self.daemon=True
 
     def is_running(self):
@@ -293,17 +257,19 @@
         self.logger.debug('Borg result: %s' % str(res))
 
         with self._cond:
-            if res is None:
+            if res is None and self.errors.ok():
                 self.logger.error('No result from borg despite no error in log')
-                if errors.ok():
-                    self.errors=self.errors.combine(Errors.ERRORS)
+                self.errors=Errors.ERRORS
 
 
-    def __do_launch(self, op, archive_or_repository, *args):
-        passphrase=self.extract_passphrase()
+    def __do_launch(self, op, archive_or_repository,
+                    common_params, op_params, paths=[]):
 
-        inst=BorgInstance(op.operation, archive_or_repository, *args)
-        inst.launch(passphrase=passphrase)
+        inst=BorgInstance(op.operation, archive_or_repository,
+                          common_params, op_params, paths)
+
+        # Only the Repository object has access to the passphrase
+        self.repository.launch_borg_instance(inst)
 
         self.logger.debug('Creating listener threads')
 
@@ -328,22 +294,25 @@
         t_log.start()
         t_res.start()
 
+
     def __launch(self, op):
         self.logger.debug("Launching '%s'" % str(op.operation))
 
+        params=(config.borg_parameters
+                +self.repository.borg_parameters
+                +self.borg_parameters)
+
         if op.operation==Operation.CREATE:
-            archive="%s::%s%s" % (self.repository.repository_name,
+            archive="%s::%s%s" % (self.repository.location,
                                   self.archive_prefix,
                                   self.archive_template)
 
-            self.__do_launch(op, archive,
-                             self.common_parameters+self.create_parameters,
-                             self.paths)
+            self.__do_launch(op, archive, params.common,
+                             params.create, self.paths)
         elif op.operation==Operation.PRUNE:
-            self.__do_launch(op, self.repository.repository_name,
-                             ([{'prefix': self.archive_prefix}] + 
-                              self.common_parameters +
-                              self.prune_parameters))
+            self.__do_launch(op, self.repository.location, params.common,
+                             [{'prefix': self.archive_prefix}] + params.create)
+
         else:
             raise NotImplementedError("Invalid operation '%s'" % str(op.operation))
 
@@ -403,7 +372,7 @@
                     if not self._terminate:
                         self.__main_thread_queue_and_launch()
             except Exception as err:
-                self.logger.exception("Error with backup '%s'" % self._name)
+                self.logger.exception("Error with backup '%s'" % self.backup_name)
                 self.errors=Errors.ERRORS
 
             self.state=State.INACTIVE
@@ -445,7 +414,7 @@
             self.__update_status()
 
             # Wait under scheduled wait
-            self.scheduler.wait_until(now+delay, self._cond, self._name)
+            self.scheduler.wait_until(now+delay, self._cond, self.backup_name)
         else:
             # Nothing scheduled - just wait
             self.logger.info("Waiting for manual scheduling")
@@ -466,7 +435,7 @@
             self.__update_status()
             res=self.repository.queue_action(self._cond,
                                              action=self.__launch_and_wait,
-                                             name=self._name)
+                                             name=self.backup_name)
             if not res and not self._terminate:
                 self.logger.debug("Queueing aborted")
                 self.scheduled_operation=None

mercurial