def start_restore(self): ''' Start restoring the files and directories. >>> from blockchain_backup.bitcoin.tests import utils as test_utils >>> test_utils.init_database() >>> restore_task = RestoreTask(os.path.join(gettempdir(), 'bitcoin/data/testnet3/backups/level1')) >>> restore_task.manager = BitcoinManager(restore_task.log_name) >>> restore_process = restore_task.start_restore() >>> restore_process is not None True >>> test_utils.stop_restore() ''' # do NOT use the --delete flag -- the backups dir itself would be deleted args = [] # restore program is a link to safecopy bin_dir = os.path.join(virtualenv_dir(), 'bin') args.append(os.path.join(bin_dir, constants.RESTORE_PROGRAM)) args.append('--exclude') args.append(bitcoin_utils.get_excluded_files()) args.append('--verbose') args.append('--quick') args.append(f'{self.restore_dir}/*') args.append(self.manager.data_dir) restore_process = Popen(args, stdout=PIPE, universal_newlines=True) return restore_process
def stop_bitcoin_qt(): ''' Stop bitcoin_qt and determine if it ended properly. >>> init_database() >>> stop_bitcoin_qt() ''' seconds = 0 while (bitcoin_utils.is_bitcoin_qt_running() and seconds < 60): try: send_bitcoin_cli_cmd('stop') sleep(5) seconds += 5 except: pass # use brute force if necessary if bitcoin_utils.is_bitcoin_qt_running(): bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [os.path.join(bin_dir, 'killmatch'), bitcoin_utils.bitcoin_qt()] command.run(*args).stdout # give it a little more time to settle down sleep(5) log(f'bitcoin-qt running: {bitcoin_utils.is_bitcoin_qt_running()}')
def interrupt_backup(self): ''' End user interrupts the 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.to_backup_dir, backup_task.backup_formatted_time, __ = backup_utils.prep_backup(backup_task.manager.data_dir) >>> backup_process, backup_pid = backup_utils.start_backup(backup_task.manager.data_dir, ... backup_task.to_backup_dir) >>> test_utils.start_fake_backup() >>> backup_task.interrupt_backup() True ''' MAX_SECS = 3 seconds = 0 self.log('interrupting backup') if self.to_backup_dir is not None: # remove all files that suggest this backup is complete backup_utils.delete_last_updated_files(self.to_backup_dir) # add a flag that we started to use this dir to backup backup_utils.add_backup_flag(self.to_backup_dir, self.backup_formatted_time) try: bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [ os.path.join(bin_dir, 'killmatch'), constants.BACKUP_PROGRAM ] attempts = 0 while backup_utils.is_backup_running() and attempts < 3: result = command.run(*args).stdout self.log(f'result of stopping backup: {result}') if backup_utils.is_backup_running(): sleep(3) attempts += 1 except CalledProcessError as cpe: self.log(cpe) self.log(format_exc()) while seconds < MAX_SECS: self.manager.update_header(backup_utils.STOPPED_BACKUP_HEADER) self.manager.update_progress(backup_utils.STOPPED_BACKUP_PROGRESS) self.manager.notify_close_window() sleep(1) seconds += 1 # return value is for testing purposes only return not backup_utils.is_backup_running()
def interrupt_restore(self): ''' User wants the restoration interrupted. This is not recommended because it almost always leaves the blockchain in unusable shape. >>> 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) >>> test_utils.start_fake_restore() >>> restore_task.interrupt_restore() True ''' max_secs = 3 seconds = 0 try: bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [ os.path.join(bin_dir, 'killmatch'), constants.RESTORE_PROGRAM ] args = [ os.path.join('/usr/local/bin', 'killmatch'), constants.RESTORE_PROGRAM ] self.log(f'args: {args}') attempts = 0 while bitcoin_utils.is_restore_running() and attempts < 5: command.run(*args) if bitcoin_utils.is_restore_running(): sleep(3) attempts += 1 except CalledProcessError as cpe: self.log(cpe) self.log(format_exc()) # a new page was displayed so give socketio time to connect while seconds < max_secs: self.manager.update_header(self.STOPPED_RESTORE) self.manager.update_subnotice(self.STOP_RESTORE_NOT_COMPLETE) self.manager.notify_done() sleep(1) seconds += 1 # return value is for testing purposes only return not bitcoin_utils.is_restore_running()
def stop_backup(self, backup_process, backup_pid): ''' Stop 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 >>> backup_task.stop_backup(backup_process, backup_pid) >>> test_utils.start_fake_backup() >>> backup_pid = get_pid(constants.BACKUP_PROGRAM) >>> backup_task.stop_backup(None, backup_pid) ''' try: if backup_process is None and backup_pid is not None: if is_backup_running(): bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [ os.path.join(bin_dir, 'killmatch'), '"{} --exclude {}"'.format(constants.BACKUP_PROGRAM, get_excluded_files()) ] result = command.run(*args).stdout self.log(f'killing backup result: {result}') try: pid, returncode = os.waitpid(backup_pid, os.P_WAIT) self.log(f'waitpid {pid} return code: {returncode}') except ChildProcessError: self.log('backup_pid already dead') else: # if bcb-backup hasn't stopped yet, then kill it if backup_process is None: self.log('not back process active') else: if backup_process.poll() is None: self.log('killing backup') backup_process.terminate() # wait until backup terminates backup_process.wait() self.log( f'backup return code: {backup_process.returncode}') except: # 'bare except' because it catches more than "except Exception" self.log(f'error while stopping backup\n{format_exc()}')
def stop_bitcoin_core_apps(): ''' Stop all bitcoin core apps. >>> stop_bitcoin_core_apps() ''' if bitcoin_utils.is_bitcoin_qt_running(): stop_bitcoin_qt() # if it's still running, then kill it if bitcoin_utils.is_bitcoin_qt_running(): bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [os.path.join(bin_dir, 'killmatch'), bitcoin_utils.bitcoin_qt()] command.run(*args).stdout if bitcoin_utils.is_bitcoind_running(): stop_bitcoind() # if it's still running, then kill it if bitcoin_utils.is_bitcoind_running(): bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [os.path.join(bin_dir, 'killmatch'), bitcoin_utils.bitcoind()] command.run(*args).stdout
def stop_restore(): ''' Stop the restore. >>> init_database() >>> stop_restore() ''' while bitcoin_utils.is_restore_running(): sleep(5) bin_dir = os.path.join(virtualenv_dir(), 'bin') excluded_files = bitcoin_utils.get_excluded_files() args = [os.path.join(bin_dir, 'killmatch'), f'"{constants.RESTORE_PROGRAM} --exclude {excluded_files}"'] result = command.run(*args).stdout log(f'killing restore result: {result}')
def stop_restore(self, restore_process, restore_pid): ''' Stop restore. >>> from blockchain_backup.bitcoin.tests import utils as test_utils >>> test_utils.init_database() >>> restore_task = RestoreTask(os.path.join(gettempdir(), 'bitcoin/data/testnet3/backups/level1')) >>> restore_task.manager = BitcoinManager(restore_task.log_name) >>> restore_process = restore_task.start_restore() >>> restore_process is not None True >>> restore_task.stop_restore(restore_process, None) >>> test_utils.start_fake_restore() >>> restore_pid = get_pid(constants.RESTORE_PROGRAM) >>> restore_task.stop_restore(None, restore_pid) ''' try: if restore_process is None: if bitcoin_utils.is_restore_running(): bin_dir = os.path.join(virtualenv_dir(), 'bin') args = [ os.path.join(bin_dir, 'killmatch'), '"{} --exclude {}"'.format( constants.RESTORE_PROGRAM, bitcoin_utils.get_excluded_files()) ] result = command.run(*args).stdout self.log(f'killing restore result: {result}') try: pid, returncode = os.waitpid(restore_pid, os.P_WAIT) self.log(f'waitpid {pid} return code: {returncode}') except ChildProcessError: self.log('restore_pid already dead') else: # if bcb-restore hasn't stopped yet, then kill it if restore_process.poll() is None: self.log('killing restore') restore_process.terminate() # wait until restore terminates restore_process.wait() self.log(f'restore return code: {restore_process.returncode}') except: # 'bare except' because it catches more than "except Exception" self.log(f'error while stopping restore\n{format_exc()}') self.log(f'error while stopping restore\n{format_exc()}')
def start_fake_restore(): ''' Start a program which has the restore program's name, but just keeps itself running for a few minutes so we can test for the app to be running. >>> start_fake_restore() >>> bin_dir = os.path.join(virtualenv_dir(), 'bin') >>> sleep(15) >>> args = [os.path.join(bin_dir, 'killmatch'), constants.RESTORE_PROGRAM] >>> result = command.run(*args) ''' bin_dir = os.path.join(virtualenv_dir(), 'bin') config_dir = os.path.join(PROJECT_PATH, 'config') args = [os.path.join(bin_dir, constants.RESTORE_PROGRAM), config_dir, '/tmp'] command.background(*args)
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