def restore_mysql(cfg, dst, backup_copy, cache): """Restore from mysql backup""" LOG.debug('mysql: %r', cfg) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(cfg) exit(1) try: ensure_empty(dst) dst_storage = get_destination( cfg, get_hostname_from_backup_copy(backup_copy) ) key = dst_storage.basename(backup_copy) copy = dst_storage.status()[key] if cache: restore_from_mysql(cfg, copy, dst, cache=Cache(cache)) else: restore_from_mysql(cfg, copy, dst) except (TwinDBBackupError, CacheException) as err: LOG.error(err) exit(1) except (OSError, IOError) as err: LOG.error(err) exit(1)
def verify_mysql(cfg, hostname, dst, backup_copy): """Verify backup""" LOG.debug('mysql: %r', cfg) if not backup_copy: list_available_backups(cfg) exit(1) print(verify_mysql_backup(cfg, dst, backup_copy, hostname))
def restore_mysql(ctx, dst, backup_copy, cache): """Restore from mysql backup""" LOG.debug('mysql: %r', ctx.obj['twindb_config']) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: ensure_empty(dst) incomplete_copy = MySQLCopy( path=backup_copy ) dst_storage = ctx.obj['twindb_config'].destination( backup_source=incomplete_copy.host ) mysql_status = MySQLStatus(dst=dst_storage) copies = [ cp for cp in mysql_status if backup_copy.endswith(cp.name) ] try: copy = copies.pop(0) except IndexError: raise TwinDBBackupError( 'Can not find copy %s in MySQL status. ' 'Inspect output of `twindb-backup status` and verify ' 'that correct copy is specified.' % backup_copy ) if copies: raise TwinDBBackupError( 'Multiple copies match pattern %s. Make sure you give unique ' 'copy name for restore.' ) if cache: restore_from_mysql( ctx.obj['twindb_config'], copy, dst, cache=Cache(cache) ) else: restore_from_mysql(ctx.obj['twindb_config'], copy, dst) except (TwinDBBackupError, CacheException) as err: LOG.error(err) LOG.debug(traceback.format_exc()) exit(1) except (OSError, IOError) as err: LOG.error(err) LOG.debug(traceback.format_exc()) exit(1)
def share_backup(ctx, s3_url): """Share backup copy for download""" if not s3_url: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: share(ctx.obj['twindb_config'], s3_url) except TwinDBBackupError as err: LOG.error(err) exit(1)
def share_backup(ctx, s3_url): """Share backup copy for download""" if not s3_url: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: share(ctx.obj['twindb_config'], s3_url) except TwinDBBackupError as err: LOG.error(err) exit(1)
def test_list_available_backups_ssh(mock_get_destination, tmpdir): backup_dir = tmpdir.mkdir('backups') mock_config = mock.Mock() mock_config.get.return_value = str(backup_dir) # Ssh destination mock_dst = mock.Mock() mock_dst.remote_path = '/foo/bar' mock_get_destination.return_value = mock_dst mock_dst.list_files.return_value = [] list_available_backups(mock_config) calls = [ mock.call( '/foo/bar', pattern='/hourly/files/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/daily/files/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/weekly/files/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/monthly/files/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/yearly/files/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/hourly/mysql/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/daily/mysql/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/weekly/mysql/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/monthly/mysql/', recursive=True, files_only=True ), mock.call( '/foo/bar', pattern='/yearly/mysql/', recursive=True, files_only=True ), mock.call( '/foo/bar', files_only=True, pattern='/binlog/', recursive=True ) ] mock_dst.list_files.assert_has_calls(calls)
def verify_mysql(cfg, hostname, dst, backup_copy): """Verify backup""" LOG.debug('mysql: %r', cfg) try: if not backup_copy: list_available_backups(cfg) exit(1) print(verify_mysql_backup(cfg, dst, backup_copy, hostname)) finally: shutil.rmtree(dst, ignore_errors=True)
def restore_file(cfg, dst, backup_copy): """Restore from file backup""" LOG.debug('file: %r', cfg) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(cfg) exit(1) try: ensure_empty(dst) restore_from_file(cfg, backup_copy, dst) except TwinDBBackupError as err: LOG.error(err) exit(1)
def verify_mysql(ctx, hostname, dst, backup_copy): """Verify backup""" LOG.debug("mysql: %r", ctx.obj["twindb_config"]) try: if not backup_copy: list_available_backups(ctx.obj["twindb_config"]) exit(1) print( verify_mysql_backup(ctx.obj["twindb_config"], dst, backup_copy, hostname)) finally: shutil.rmtree(dst, ignore_errors=True)
def restore_mysql(ctx, dst, backup_copy, cache): """Restore from mysql backup""" LOG.debug('mysql: %r', ctx.obj['twindb_config']) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: ensure_empty(dst) incomplete_copy = MySQLCopy(path=backup_copy) dst_storage = ctx.obj['twindb_config'].destination( backup_source=incomplete_copy.host) mysql_status = MySQLStatus(dst=dst_storage, status_directory=incomplete_copy.host) copies = [cp for cp in mysql_status if backup_copy.endswith(cp.name)] try: copy = copies.pop(0) except IndexError: raise TwinDBBackupError( 'Can not find copy %s in MySQL status. ' 'Inspect output of `twindb-backup status` and verify ' 'that correct copy is specified.' % backup_copy) if copies: raise TwinDBBackupError( 'Multiple copies match pattern %s. Make sure you give unique ' 'copy name for restore.') if cache: restore_from_mysql(ctx.obj['twindb_config'], copy, dst, cache=Cache(cache)) else: restore_from_mysql(ctx.obj['twindb_config'], copy, dst) except (TwinDBBackupError, CacheException) as err: LOG.error(err) LOG.debug(traceback.format_exc()) exit(1) except (OSError, IOError) as err: LOG.error(err) LOG.debug(traceback.format_exc()) exit(1)
def restore_file(ctx, dst, backup_copy): """Restore from file backup""" LOG.debug('file: %r', ctx.obj['twindb_config']) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: ensure_empty(dst) copy = FileCopy(path=backup_copy) restore_from_file(ctx.obj['twindb_config'], copy, dst) except TwinDBBackupError as err: LOG.error(err) exit(1) except KeyboardInterrupt: LOG.info('Exiting...') kill_children() exit(1)
def restore_file(ctx, dst, backup_copy): """Restore from file backup""" LOG.debug('file: %r', ctx.obj['twindb_config']) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(ctx.obj['twindb_config']) exit(1) try: ensure_empty(dst) copy = FileCopy(path=backup_copy) restore_from_file(ctx.obj['twindb_config'], copy, dst) except TwinDBBackupError as err: LOG.error(err) exit(1) except KeyboardInterrupt: LOG.info('Exiting...') kill_children() exit(1)
def verify_mysql(ctx, hostname, dst, backup_copy): """Verify backup""" LOG.debug('mysql: %r', ctx.obj['twindb_config']) try: if not backup_copy: list_available_backups(ctx.obj['twindb_config']) exit(1) print( verify_mysql_backup( ctx.obj['twindb_config'], dst, backup_copy, hostname ) ) finally: shutil.rmtree(dst, ignore_errors=True)
def restore_mysql(cfg, dst, backup_copy, cache): """Restore from mysql backup""" LOG.debug('mysql: %r', cfg) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(cfg) exit(1) try: ensure_empty(dst) if cache: restore_from_mysql(cfg, backup_copy, dst, cache=Cache(cache)) else: restore_from_mysql(cfg, backup_copy, dst) except (TwinDBBackupError, CacheException) as err: LOG.error(err) exit(1) except (OSError, IOError) as err: LOG.error(err) exit(1)
def restore_file(cfg, dst, backup_copy): """Restore from file backup""" LOG.debug('file: %r', cfg) if not backup_copy: LOG.info('No backup copy specified. Choose one from below:') list_available_backups(cfg) exit(1) try: ensure_empty(dst) copy = FileCopy( get_hostname_from_backup_copy(backup_copy), basename(backup_copy), get_run_type_from_backup_copy(backup_copy) ) restore_from_file(cfg, copy, dst) except TwinDBBackupError as err: LOG.error(err) exit(1) except KeyboardInterrupt: LOG.info('Exiting...') kill_children() exit(1)
def test_list_available_backups_ssh(mock_popen, mock_get_destination, mock_os): mock_os.path.exists.return_value = True mock_config = mock.Mock() mock_config.get.return_value = "/foo/bar" mock_dst = mock.Mock() mock_dst.remote_path = '/foo/bar' mock_get_destination.return_value = mock_dst mock_dst.find_files.return_value = [] list_available_backups(mock_config) mock_popen.assert_called_once_with(["find", '/foo/bar', '-type', 'f']) calls = [ mock.call('/foo/bar', 'hourly'), mock.call('/foo/bar', 'daily'), mock.call('/foo/bar', 'weekly'), mock.call('/foo/bar', 'monthly'), mock.call('/foo/bar', 'yearly'), ] mock_dst.find_files.assert_has_calls(calls)
def test_list_available_backups_ssh(): mock_config = mock.Mock() mock_config.keep_local_path = None # Ssh destination mock_dst = mock.Mock() mock_dst.remote_path = '/foo/bar' mock_dst.list_files.return_value = [] mock_config.destination.return_value = mock_dst list_available_backups(mock_config) calls = [ mock.call('/foo/bar', pattern='/hourly/files/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/daily/files/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/weekly/files/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/monthly/files/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/yearly/files/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/hourly/mysql/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/daily/mysql/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/weekly/mysql/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/monthly/mysql/', recursive=True, files_only=True), mock.call('/foo/bar', pattern='/yearly/mysql/', recursive=True, files_only=True), mock.call('/foo/bar', files_only=True, pattern='/binlog/', recursive=True) ] mock_dst.list_files.assert_has_calls(calls)
def list_backups(ctx, copy_type): """List available backup copies""" list_available_backups( ctx.obj['twindb_config'], copy_type=copy_type )
def list_backups(ctx, copy_type): """List available backup copies""" list_available_backups(ctx.obj['twindb_config'], copy_type=copy_type)
def list_backups(cfg, copy_type): """List available backup copies""" list_available_backups( cfg, copy_type=copy_type )
def list_backups(cfg): """List available backup copies""" list_available_backups(cfg)