| 70 |
70 |
| 71 self.prune_parameters=config.check_list_of_dicts(cfg, 'prune_parameters', |
71 self.prune_parameters=config.check_list_of_dicts(cfg, 'prune_parameters', |
| 72 'Prune parameters', self.loc, |
72 'Prune parameters', self.loc, |
| 73 default=[]) |
73 default=[]) |
| 74 |
74 |
| 75 keychain_account=config.check_string(cfg, 'keychain_account', |
75 self.__keychain_account=config.check_string(cfg, 'keychain_account', |
| 76 'Keychain account', self.loc, |
76 'Keychain account', self.loc, |
| 77 default='') |
77 default='') |
| 78 |
78 |
| 79 if keychain_account and keychain_account!='': |
79 if config.settings['__extract_passphrases_at_startup']: |
| 80 pw=keyring.get_password("borg-backup", keychain_account) |
80 self.extract_passphrase() |
| 81 self.__password=pw |
81 |
| |
82 def extract_passphrase(self): |
| |
83 acc=self.__keychain_account |
| |
84 if acc and acc!='': |
| |
85 pw=keyring.get_password("borg-backup", acc) |
| |
86 self.__passphrase=pw |
| 82 else: |
87 else: |
| 83 self.__password=None |
88 self.__passphrase=None |
| 84 |
89 |
| 85 def __init__(self, identifier, cfg): |
90 def __init__(self, identifier, cfg): |
| 86 self.identifier=identifier |
91 self.identifier=identifier |
| 87 |
92 |
| 88 self.__decode_config(cfg) |
93 self.__decode_config(cfg) |
| 121 success=True |
126 success=True |
| 122 for status in iter(self.borg_instance.read_log, None): |
127 for status in iter(self.borg_instance.read_log, None): |
| 123 logging.debug(str(status)) |
128 logging.debug(str(status)) |
| 124 t=status['type'] |
129 t=status['type'] |
| 125 |
130 |
| 126 errors_this_message=False |
131 errors_this_message=None |
| 127 callback=None |
132 callback=None |
| 128 |
133 |
| 129 if t=='progress_percent': |
134 if t=='progress_percent': |
| 130 current=safe_get_int(status, 'current') |
135 current=safe_get_int(status, 'current') |
| 131 total=safe_get_int(status, 'total') |
136 total=safe_get_int(status, 'total') |
| 160 if 'name' not in status: |
165 if 'name' not in status: |
| 161 status['name']='borg' |
166 status['name']='borg' |
| 162 lvl=translate_loglevel(status['levelname']) |
167 lvl=translate_loglevel(status['levelname']) |
| 163 logging.log(lvl, status['name'] + ': ' + status['message']) |
168 logging.log(lvl, status['name'] + ': ' + status['message']) |
| 164 if lvl>=logging.WARNING: |
169 if lvl>=logging.WARNING: |
| 165 errors_this_message=True |
170 errors_this_message=status |
| 166 elif t=='exception': |
171 with self.lock: |
| 167 errors_this_message=True |
172 self.current_operation['errors']=True |
| 168 elif t=='unparsed_error': |
173 status, callback=self.__status_unlocked() |
| 169 errors_this_message=True |
174 else: |
| 170 |
175 logging.debug('Unrecognised log entry %s' % str(status)) |
| 171 if errors_this_message: |
|
| 172 with self.lock: |
|
| 173 self.current_operation['errors']=True |
|
| 174 status, callback=self.__status_unlocked() |
|
| 175 |
176 |
| 176 if callback: |
177 if callback: |
| 177 callback(self, status) |
178 callback(self, status, errors=errors_this_message) |
| 178 |
179 |
| 179 logging.debug('Waiting for borg subprocess to terminate in log thread') |
180 logging.debug('Waiting for borg subprocess to terminate in log thread') |
| 180 |
181 |
| 181 self.borg_instance.wait() |
182 self.borg_instance.wait() |
| 182 |
183 |
| 219 status, callback=self.__status_unlocked() |
220 status, callback=self.__status_unlocked() |
| 220 if callback: |
221 if callback: |
| 221 callback(self, status) |
222 callback(self, status) |
| 222 |
223 |
| 223 def __do_launch(self, queue, op, archive_or_repository, *args): |
224 def __do_launch(self, queue, op, archive_or_repository, *args): |
| |
225 self.extract_passphrase() |
| |
226 |
| 224 inst=BorgInstance(op['operation'], archive_or_repository, *args) |
227 inst=BorgInstance(op['operation'], archive_or_repository, *args) |
| 225 inst.launch(password=self.__password) |
228 inst.launch(passphrase=self.__passphrase) |
| 226 |
229 |
| 227 t_log=Thread(target=self.__log_listener) |
230 t_log=Thread(target=self.__log_listener) |
| 228 t_log.daemon=True |
231 t_log.daemon=True |
| 229 |
232 |
| 230 t_res=Thread(target=self.__result_listener) |
233 t_res=Thread(target=self.__result_listener) |
| 376 |
379 |
| 377 def schedule(self): |
380 def schedule(self): |
| 378 with self.lock: |
381 with self.lock: |
| 379 return self.__schedule_unlocked() |
382 return self.__schedule_unlocked() |
| 380 |
383 |
| 381 def set_status_update_callback(self, callback): |
|
| 382 with self.lock: |
|
| 383 self.status_update_callback=callback |
|
| 384 |
|
| 385 def status(self): |
384 def status(self): |
| 386 with self.lock: |
385 with self.lock: |
| 387 res=self.__status_unlocked() |
386 res=self.__status_unlocked() |
| 388 return res[0] |
387 return res[0] |
| 389 |
388 |
| 390 def __status_unlocked(self): |
389 def __status_unlocked(self): |
| 391 callback=self.status_update_callback |
390 callback=self.__status_update_callback |
| 392 if self.current_operation: |
391 if self.current_operation: |
| 393 status=self.current_operation |
392 status=self.current_operation |
| 394 status['type']='current' |
393 status['type']='current' |
| 395 elif self.scheduled_operation: |
394 elif self.scheduled_operation: |
| 396 status=self.scheduled_operation |
395 status=self.scheduled_operation |