def restore_files_and_dirs(self): ''' Restore files and directories to a previous state of the blockchain. >>> from blockchain_backup.bitcoin.tests import utils as test_utils >>> test_utils.init_database() >>> restore_dir = os.path.join(gettempdir(), 'bitcoin/data/testnet3/backups/level1') >>> restore_task = RestoreTask(restore_dir) >>> restore_task.manager = BitcoinManager(restore_task.log_name) >>> restore_task.restore_files_and_dirs() True >>> test_utils.stop_restore() >>> test_utils.start_fake_restore() >>> restore_task = RestoreTask(restore_dir) >>> restore_task.manager = BitcoinManager(restore_task.log_name) >>> restore_task.restore_files_and_dirs() True >>> test_utils.stop_restore() ''' ok = True try: if bitcoin_utils.is_restore_running(): restore_pid = get_pid(constants.RESTORE_PROGRAM) restore_process = None self.log('{} is already running using pid: {}'.format( constants.RESTORE_PROGRAM, restore_pid)) else: self.log('starting restore') restore_process = self.start_restore() restore_pid = None if restore_process is not None or restore_pid is not None: self.wait_for_restore(restore_process) self.stop_restore(restore_process, restore_pid) else: self.manager.update_progress(self.RESTORE_UNABLE_TO_START) ok = False except: # 'bare except' because it catches more than "except Exception" ok = False self.log(format_exc()) if not ok: self.manager.update_progress(self.RESTORE_ERROR) return ok
def start_backup(self): ''' Start backup. >>> from blockchain_backup.bitcoin.tests import utils as test_utils >>> test_utils.init_database() >>> backup_task = BackupTask() >>> backup_task.manager = BitcoinManager(backup_task.log_name) >>> backup_task.prep_backup() >>> backup_process, backup_pid = backup_task.start_backup() >>> backup_process is not None True >>> backup_pid is None True >>> test_utils.stop_backup() ''' bin_dir = os.path.join(virtualenv_dir(), 'bin') data_dir = self.manager.data_dir if not data_dir.endswith(os.sep): data_dir += os.sep if is_backup_running(): backup_process = None backup_pid = get_pid(constants.BACKUP_PROGRAM) self.log('{} is already running using pid: {}'.format( constants.BACKUP_PROGRAM, backup_pid)) else: backup_pid = None args = [] # "bcb-backup" is a link to safecopy so we can distinguish it when we kill it args.append(os.path.join(bin_dir, constants.BACKUP_PROGRAM)) args.append('--exclude') args.append(get_excluded_files()) args.append('--verbose') args.append('--quick') args.append('--delete') args.append(f'{data_dir}*') args.append(self.to_backup_dir) # Popen appears to report "'list' object has no attribute 'split'" # the docs state Popen should pass a sequence as the first arg backup_process = Popen(args, stdout=PIPE, universal_newlines=True) return backup_process, backup_pid
def start_bitcoind(self): ''' Start bitcoind as a daemon. >>> from blockchain_backup.bitcoin.tests import utils as test_utils >>> need_backup = False >>> test_utils.init_database() >>> update_task = UpdateTask() >>> update_task.manager = BitcoinManager(update_task.log_name) >>> bitcoind_process, bitcoind_pid = update_task.start_bitcoind() >>> update_task.stop_bitcoind(bitcoind_process, bitcoind_pid, need_backup) (False, ' Error opening block database.\\n') ''' if is_bitcoind_running(): bitcoind_process = None bitcoind_pid = get_pid(bitcoind()) if bitcoind_pid is None: sleep(5) bitcoind_pid = get_pid(bitcoind()) self.log(f'bitcoind is already running using pid: {bitcoind_pid}') else: bitcoind_pid = None command_args = [] if self.manager.bin_dir is None: command_args.append(bitcoind()) ok = True else: cmd = os.path.join(self.manager.bin_dir, bitcoind()) command_args.append(cmd) ok = os.path.exists(cmd) if ok: extra_args = preferences.get_extra_args() use_test_net = '-testnet' in extra_args if self.manager.data_dir is not None: data_dir = self.manager.data_dir if use_test_net and data_dir.endswith( constants.TEST_NET_SUBDIR): data_dir = data_dir[:data_dir.rfind(constants. TEST_NET_SUBDIR)] command_args.append(f'-datadir={data_dir}') # don't allow any interaction with the user's wallet command_args.append('-disablewallet') if extra_args: for extra_arg in extra_args: command_args.append(extra_arg) command_args.append('-daemon') try: bitcoind_process = Popen(command_args) self.log( f'bitcoind started: {bitcoind_process is not None}') except FileNotFoundError as fnfe: raise BitcoinException(str(fnfe)) else: bitcoind_process = None self.log( f'{bitcoind()} does not exist in {self.manager.bin_dir}') state.set_start_access_time(now()) return bitcoind_process, bitcoind_pid
def run_qt(self): ''' Run bitcon-qt. ''' ok = False error_message = None self.manager.update_menu(constants.DISABLE_ITEM) try: command_args = self.get_launch_args() if command_args is None: ok = False else: self.manager.rename_logs() state.set_start_access_time(now()) self.log(f'starting bitcoin-qt: {command_args}') os.putenv('DISPLAY', ':0.0') if bitcoin_utils.is_bitcoin_qt_running(): bitcoin_pid = get_pid(bitcoin_utils.bitcoin_qt()) bitcoin_process = None else: bitcoin_pid = None bitcoin_process = Popen(command_args) if bitcoin_process is not None or bitcoin_pid is not None: self.wait_for_close(bitcoin_process) state.set_last_access_time(now()) ok = True else: self.manager.update_progress(self.BITCOIN_QT_OTHER_APP_RUNNING) ok = False except CalledProcessError as cpe: ok = False stdout = cpe.stdout if stdout and not isinstance(stdout, str): stdout = stdout.decode() stderr = cpe.stderr if stderr and not isinstance(stderr, str): stderr = stderr.decode() __, error_message, log_message = self.manager.process_bitcoin_cli_error( 'getblockchaininfo', cpe.returncode, stdout, stderr) if error_message is None: error_message = log_message self.log(error_message) except BitcoinException as be: ok = False error_message = str(be) self.log(error_message) except FileNotFoundError as fnfe: ok = False error_message = str(fnfe) self.log(error_message) except Exception: self.log(format_exc()) if ok: # check the logs to make sure everything was ok ok, error_message = self.manager.bitcoin_finished_ok( bitcoin_utils.is_bitcoin_qt_running) if ok: if self.current_block > 0: state.set_last_block_updated(self.current_block) else: if error_message is None: error_message = '' self.manager.update_subnotice('{} {}'.format( self.BITCOIN_QT_ERROR_LABEL, error_message)) self.manager.update_progress(' ') return ok, error_message