コード例 #1
0
ファイル: cmd.py プロジェクト: zurikus/wal-e
def main():
    parser = build_parser()
    args = parser.parse_args()
    subcommand = args.subcommand

    # Adjust logging level if terse output is set.
    if args.terse:
        log_help.set_level(logging.WARNING)

    # Handle version printing specially, because it doesn't need
    # credentials.
    if subcommand == 'version':
        import pkgutil

        print(pkgutil.get_data('wal_e', 'VERSION').decode('ascii').strip())
        sys.exit(0)

    # Print a start-up message right away.
    #
    # Otherwise, it is hard to tell when and how WAL-E started in logs
    # because often emits status output too late.
    rendered = render_subcommand(args)
    if rendered is not None:
        logger.info(msg='starting WAL-E',
                    detail='The subcommand is "{0}".'.format(rendered))

    try:
        backup_cxt = configure_backup_cxt(args)

        if subcommand == 'backup-fetch':
            monkeypatch_tarfile_copyfileobj()

            external_program_check([LZOP_BIN])
            backup_cxt.database_fetch(args.PG_CLUSTER_DIRECTORY,
                                      args.BACKUP_NAME,
                                      blind_restore=args.blind_restore,
                                      restore_spec=args.restore_spec,
                                      pool_size=args.pool_size)
        elif subcommand == 'backup-list':
            backup_cxt.backup_list(query=args.QUERY, detail=args.detail)
        elif subcommand == 'backup-push':
            monkeypatch_tarfile_copyfileobj()

            if args.while_offline:
                # we need to query pg_config first for the
                # pg_controldata's bin location
                external_program_check([CONFIG_BIN])
                parser = PgControlDataParser(args.PG_CLUSTER_DIRECTORY)
                controldata_bin = parser.controldata_bin()
                external_programs = [LZOP_BIN, PV_BIN, controldata_bin]
            else:
                external_programs = [LZOP_BIN, PSQL_BIN, PV_BIN]

            external_program_check(external_programs)
            rate_limit = args.rate_limit

            while_offline = args.while_offline
            backup_cxt.database_backup(args.PG_CLUSTER_DIRECTORY,
                                       rate_limit=rate_limit,
                                       while_offline=while_offline,
                                       pool_size=args.pool_size)
        elif subcommand == 'wal-fetch':
            external_program_check([LZOP_BIN])
            res = backup_cxt.wal_restore(args.WAL_SEGMENT,
                                         args.WAL_DESTINATION, args.prefetch)
            if not res:
                sys.exit(1)
        elif subcommand == 'wal-prefetch':
            external_program_check([LZOP_BIN])
            backup_cxt.wal_prefetch(args.BASE_DIRECTORY, args.SEGMENT)
        elif subcommand == 'wal-push':
            external_program_check([LZOP_BIN])
            backup_cxt.wal_archive(args.WAL_SEGMENT,
                                   concurrency=args.pool_size)
        elif subcommand == 'delete':
            # Set up pruning precedence, optimizing for *not* deleting data
            #
            # Canonicalize the passed arguments into the value
            # "is_dry_run_really"
            if args.dry_run is False and args.confirm is True:
                # Actually delete data *only* if there are *no* --dry-runs
                # present and --confirm is present.
                logger.info(msg='deleting data in the store')
                is_dry_run_really = False
            else:
                logger.info(msg='performing dry run of data deletion')
                is_dry_run_really = True

                # This is not necessary, but "just in case" to find bugs.
                def just_error(*args, **kwargs):
                    assert False, ('About to delete something in '
                                   'dry-run mode.  Please report a bug.')

            # Handle the subcommands and route them to the right
            # implementations.
            if args.delete_subcommand == 'old-versions':
                backup_cxt.delete_old_versions(is_dry_run_really)
            elif args.delete_subcommand == 'everything':
                backup_cxt.delete_all(is_dry_run_really)
            elif args.delete_subcommand == 'retain':
                backup_cxt.delete_with_retention(is_dry_run_really,
                                                 args.NUM_TO_RETAIN)
            elif args.delete_subcommand == 'before':
                segment_info = extract_segment(args.BEFORE_SEGMENT_EXCLUSIVE)
                assert segment_info is not None
                backup_cxt.delete_before(is_dry_run_really, segment_info)
            else:
                assert False, 'Should be rejected by argument parsing.'
        else:
            logger.error(
                msg='subcommand not implemented',
                detail=(
                    'The submitted subcommand was {0}.'.format(subcommand)),
                hint='Check for typos or consult wal-e --help.')
            sys.exit(127)

        # Report on all encountered exceptions, and raise the last one
        # to take advantage of the final catch-all reporting and exit
        # code management.
        if backup_cxt.exceptions:
            for exc in backup_cxt.exceptions[:-1]:
                if isinstance(exc, UserException):
                    logger.log(level=exc.severity,
                               msg=exc.msg,
                               detail=exc.detail,
                               hint=exc.hint)
                else:
                    logger.error(msg=exc)

            raise backup_cxt.exceptions[-1]

    except UserException as e:
        logger.log(level=e.severity, msg=e.msg, detail=e.detail, hint=e.hint)
        sys.exit(1)
    except Exception as e:
        logger.critical(
            msg='An unprocessed exception has avoided all error handling',
            detail=''.join(traceback.format_exception(*sys.exc_info())))
        sys.exit(2)
コード例 #2
0
ファイル: cmd.py プロジェクト: DikangGu/wal-e
def main():
    parser = build_parser()
    args = parser.parse_args()
    subcommand = args.subcommand

    # Adjust logging level if terse output is set.
    if args.terse:
        log_help.set_level(logging.WARNING)

    # Handle version printing specially, because it doesn't need
    # credentials.
    if subcommand == 'version':
        import pkgutil

        print pkgutil.get_data('wal_e', 'VERSION').strip()
        sys.exit(0)

    # Print a start-up message right away.
    #
    # Otherwise, it is hard to tell when and how WAL-E started in logs
    # because often emits status output too late.
    logger.info(msg='starting WAL-E',
                detail=('The subcommand is "{0}".'
                        .format(render_subcommand(args))))

    try:
        backup_cxt = configure_backup_cxt(args)

        if subcommand == 'backup-fetch':
            monkeypatch_tarfile_copyfileobj()

            external_program_check([LZOP_BIN])
            backup_cxt.database_fetch(
                args.PG_CLUSTER_DIRECTORY,
                args.BACKUP_NAME,
                blind_restore=args.blind_restore,
                restore_spec=args.restore_spec,
                pool_size=args.pool_size)
        elif subcommand == 'backup-list':
            backup_cxt.backup_list(query=args.QUERY, detail=args.detail)
        elif subcommand == 'backup-push':
            monkeypatch_tarfile_copyfileobj()

            if args.while_offline:
                # we need to query pg_config first for the
                # pg_controldata's bin location
                external_program_check([CONFIG_BIN])
                parser = PgControlDataParser(args.PG_CLUSTER_DIRECTORY)
                controldata_bin = parser.controldata_bin()
                external_programs = [
                    LZOP_BIN,
                    PV_BIN,
                    controldata_bin]
            else:
                external_programs = [LZOP_BIN, PSQL_BIN, PV_BIN]

            external_program_check(external_programs)
            rate_limit = args.rate_limit

            while_offline = args.while_offline
            backup_cxt.database_backup(
                args.PG_CLUSTER_DIRECTORY,
                rate_limit=rate_limit,
                while_offline=while_offline,
                pool_size=args.pool_size)
        elif subcommand == 'wal-fetch':
            external_program_check([LZOP_BIN])
            res = backup_cxt.wal_restore(args.WAL_SEGMENT,
                                         args.WAL_DESTINATION)
            if not res:
                sys.exit(1)
        elif subcommand == 'wal-push':
            external_program_check([LZOP_BIN])
            backup_cxt.wal_archive(args.WAL_SEGMENT,
                                   concurrency=args.pool_size)
        elif subcommand == 'delete':
            # Set up pruning precedence, optimizing for *not* deleting data
            #
            # Canonicalize the passed arguments into the value
            # "is_dry_run_really"
            if args.dry_run is False and args.confirm is True:
                # Actually delete data *only* if there are *no* --dry-runs
                # present and --confirm is present.
                logger.info(msg='deleting data in the store')
                is_dry_run_really = False
            else:
                logger.info(msg='performing dry run of data deletion')
                is_dry_run_really = True

                import boto.s3.key
                import boto.s3.bucket

                # This is not necessary, but "just in case" to find bugs.
                def just_error(*args, **kwargs):
                    assert False, ('About to delete something in '
                                   'dry-run mode.  Please report a bug.')

                boto.s3.key.Key.delete = just_error
                boto.s3.bucket.Bucket.delete_keys = just_error

            # Handle the subcommands and route them to the right
            # implementations.
            if args.delete_subcommand == 'old-versions':
                backup_cxt.delete_old_versions(is_dry_run_really)
            elif args.delete_subcommand == 'everything':
                backup_cxt.delete_all(is_dry_run_really)
            elif args.delete_subcommand == 'retain':
                backup_cxt.delete_with_retention(is_dry_run_really,
                                                 args.NUM_TO_RETAIN)
            elif args.delete_subcommand == 'before':
                segment_info = extract_segment(args.BEFORE_SEGMENT_EXCLUSIVE)
                assert segment_info is not None
                backup_cxt.delete_before(is_dry_run_really, segment_info)
            else:
                assert False, 'Should be rejected by argument parsing.'
        else:
            logger.error(msg='subcommand not implemented',
                         detail=('The submitted subcommand was {0}.'
                                 .format(subcommand)),
                         hint='Check for typos or consult wal-e --help.')
            sys.exit(127)

        # Report on all encountered exceptions, and raise the last one
        # to take advantage of the final catch-all reporting and exit
        # code management.
        if backup_cxt.exceptions:
            for exc in backup_cxt.exceptions[:-1]:
                if isinstance(exc, UserException):
                    logger.log(level=exc.severity,
                               msg=exc.msg, detail=exc.detail, hint=exc.hint)
                else:
                    logger.error(msg=exc)

            raise backup_cxt.exceptions[-1]

    except UserException, e:
        logger.log(level=e.severity,
                   msg=e.msg, detail=e.detail, hint=e.hint)
        sys.exit(1)