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 |