backup.py

changeset 32
06fc14211ba9
parent 31
b4b4bb7a2ec5
child 34
9fce700d42de
equal deleted inserted replaced
31:b4b4bb7a2ec5 32:06fc14211ba9
76 76
77 self.__keychain_account=config.check_string(cfg, 'keychain_account', 77 self.__keychain_account=config.check_string(cfg, 'keychain_account',
78 'Keychain account', self.loc, 78 'Keychain account', self.loc,
79 default='') 79 default='')
80 80
81 self.__passphrase=None
82
81 if config.settings['extract_passphrases_at_startup']: 83 if config.settings['extract_passphrases_at_startup']:
82 self.extract_passphrase() 84 try:
85 self.extract_passphrase()
86 except Exception:
87 pass
83 88
84 def extract_passphrase(self): 89 def extract_passphrase(self):
85 acc=self.__keychain_account 90 acc=self.__keychain_account
86 if acc and acc!='': 91 if not self.__passphrase:
87 pw=keyring.get_password("borg-backup", acc) 92 if acc and acc!='':
88 self.__passphrase=pw 93 logger.debug('Requesting passphrase')
89 else: 94 try:
90 self.__passphrase=None 95 pw=keyring.get_password("borg-backup", acc)
96 except Exception as err:
97 logger.error('Failed to retrieve password: %s' % str(err))
98 raise err
99 else:
100 logger.debug('Received passphrase')
101 self.__passphrase=pw
102 else:
103 self.__passphrase=None
104 return self.__passphrase
91 105
92 def __init__(self, identifier, cfg): 106 def __init__(self, identifier, cfg):
93 self.identifier=identifier 107 self.identifier=identifier
94 108
95 self.__decode_config(cfg) 109 self.__decode_config(cfg)
96 110
97 self.config=config 111 self.config=config
98 self.lastrun=None 112 self.lastrun_when=None
99 self.lastrun_success=None 113 self.lastrun_success=None
100 self.borg_instance=None 114 self.borg_instance=None
101 self.current_operation=None 115 self.current_operation=None
102 self.thread_log=None 116 self.thread_log=None
103 self.thread_res=None 117 self.thread_res=None
210 224
211 self.thread_log.join() 225 self.thread_log.join()
212 226
213 with self.lock: 227 with self.lock:
214 if self.current_operation['operation']=='create': 228 if self.current_operation['operation']=='create':
215 self.lastrun=self.current_operation['when_monotonic'] 229 self.lastrun_when=self.current_operation['when_monotonic']
216 self.lastrun_success=success 230 self.lastrun_success=success
217 self.thread_res=None 231 self.thread_res=None
218 self.thread_log=None 232 self.thread_log=None
219 self.borg_instance=None 233 self.borg_instance=None
220 self.current_operation=None 234 self.current_operation=None
222 status, callback=self.__status_unlocked() 236 status, callback=self.__status_unlocked()
223 if callback: 237 if callback:
224 callback(self, status) 238 callback(self, status)
225 239
226 def __do_launch(self, queue, op, archive_or_repository, *args): 240 def __do_launch(self, queue, op, archive_or_repository, *args):
227 self.extract_passphrase() 241 passphrase=self.extract_passphrase()
228 242
229 inst=BorgInstance(op['operation'], archive_or_repository, *args) 243 inst=BorgInstance(op['operation'], archive_or_repository, *args)
230 inst.launch(passphrase=self.__passphrase) 244 inst.launch(passphrase=passphrase)
231 245
232 logger.debug('Creating listener threads') 246 logger.debug('Creating listener threads')
233 247
234 t_log=Thread(target=self.__log_listener) 248 t_log=Thread(target=self.__log_listener)
235 t_log.daemon=True 249 t_log.daemon=True
256 if self.timer: 270 if self.timer:
257 logger.debug('Unscheduling timed operation due to launch of operation') 271 logger.debug('Unscheduling timed operation due to launch of operation')
258 self.timer=None 272 self.timer=None
259 self.scheduled_operation=None 273 self.scheduled_operation=None
260 274
261 logger.debug("Launching '%s' on '%s'" % (op['operation'], self.name)) 275 try:
262 276 logger.debug("Launching '%s' on '%s'" % (op['operation'], self.name))
263 if op['operation']=='create': 277
264 archive="%s::%s%s" % (self.repository, 278 if op['operation']=='create':
265 self.archive_prefix, 279 archive="%s::%s%s" % (self.repository,
266 self.archive_template) 280 self.archive_prefix,
267 281 self.archive_template)
268 self.__do_launch(queue, op, archive, 282
269 self.common_parameters+self.create_parameters, 283 self.__do_launch(queue, op, archive,
270 self.paths) 284 self.common_parameters+self.create_parameters,
271 elif op['operation']=='prune': 285 self.paths)
272 self.__do_launch(queue, op, self.repository, 286 elif op['operation']=='prune':
273 ([{'prefix': self.archive_prefix}] + 287 self.__do_launch(queue, op, self.repository,
274 self.common_parameters + 288 ([{'prefix': self.archive_prefix}] +
275 self.prune_parameters)) 289 self.common_parameters +
276 else: 290 self.prune_parameters))
277 logger.error("Invalid operaton '%s'" % op['operation']) 291 else:
292 raise NotImplementedError("Invalid operation '%s'" % op['operation'])
293 except Exception as err:
294 logging.debug('Rescheduling after failure')
295 self.lastrun_when=time.monotonic()
296 self.lastrun_success=False
278 self.__schedule_unlocked() 297 self.__schedule_unlocked()
298 raise err
279 299
280 return True 300 return True
281 301
282 def create(self, queue): 302 def create(self, queue):
283 op={'operation': 'create', 'detail': 'manual'} 303 op={'operation': 'create', 'detail': 'manual'}
336 self.__launch(op, None) 356 self.__launch(op, None)
337 357
338 def __next_operation_unlocked(self): 358 def __next_operation_unlocked(self):
339 # TODO: pruning as well 359 # TODO: pruning as well
340 now=time.monotonic() 360 now=time.monotonic()
341 if not self.lastrun: 361 if not self.lastrun_when:
342 initial_interval=self.retry_interval 362 initial_interval=self.retry_interval
343 if initial_interval==0: 363 if initial_interval==0:
344 initial_interval=self.backup_interval 364 initial_interval=self.backup_interval
345 if initial_interval==0: 365 if initial_interval==0:
346 return None 366 return None
352 if self.retry_interval==0: 372 if self.retry_interval==0:
353 return None 373 return None
354 else: 374 else:
355 return {'operation': 'create', 375 return {'operation': 'create',
356 'detail': 'retry', 376 'detail': 'retry',
357 'when_monotonic': self.lastrun+self.retry_interval} 377 'when_monotonic': self.lastrun_when+self.retry_interval}
358 else: 378 else:
359 if self.backup_interval==0: 379 if self.backup_interval==0:
360 return None 380 return None
361 else: 381 else:
362 return {'operation': 'create', 382 return {'operation': 'create',
363 'detail': None, 383 'detail': None,
364 'when_monotonic': self.lastrun+self.backup_interval} 384 'when_monotonic': self.lastrun_when+self.backup_interval}
365 385
366 def __schedule_unlocked(self): 386 def __schedule_unlocked(self):
367 if self.current_operation: 387 if self.current_operation:
368 return self.current_operation 388 return self.current_operation
369 else: 389 else:

mercurial