示例#1
0
    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
示例#2
0
    def delete_extra_files(self, from_dir, to_dir):
        '''
            Delete files that are not part
            of the current blockchain.

            >>> from blockchain_backup.bitcoin.tests import utils as test_utils
            >>> test_utils.init_database()
            >>> from_dir = os.path.join(gettempdir(), 'bitcoin/data/testnet3/backups/level1')
            >>> restore_task = RestoreTask(from_dir)
            >>> restore_task.manager = BitcoinManager(restore_task.log_name)
            >>> restore_task.delete_extra_files(from_dir, restore_task.manager.data_dir)
            True
        '''

        BACKUP_SUBDIR = bitcoin_utils.get_backup_subdir()
        EXCLUDED_FILES = bitcoin_utils.get_excluded_files()

        ok = True

        try:
            to_entries = os.scandir(to_dir)
            for entry in to_entries:
                if entry.name in [EXCLUDED_FILES]:
                    self.log(f'skipping {entry.name}')
                elif entry.name.startswith(constants.LAST_UPDATED_PREFIX):
                    os.remove(entry.path)
                    self.log(f'deleted {entry.path}')
                elif entry.is_file():
                    from_file = os.path.join(from_dir, entry.name)
                    if not os.path.exists(from_file):
                        os.remove(entry.path)
                        self.log(f'deleted {entry.path}')
                elif entry.is_dir() and entry.name != BACKUP_SUBDIR:
                    from_file = os.path.join(from_dir, entry.name)
                    if os.path.exists(from_file):
                        ok = self.delete_extra_files(
                            os.path.join(from_dir, entry.name), entry.path)
                    else:
                        rmtree(entry.path)
                        self.log(f'deleted dir tree: {entry.path}')

                if not ok or self.is_interrupted():
                    break

        except:  # 'bare except' because it catches more than "except Exception"
            ok = False
            self.log(format_exc())

        if not ok and not self.is_interrupted():
            self.manager.update_progress(self.RESTORE_ERROR)

        return ok
示例#3
0
    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()}')
示例#4
0
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}')
示例#5
0
    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()}')
示例#6
0
    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