Exemple #1
0
def backup():
    install_path = config.install_path.value
    data_path = config.data_path.value

    args = _parse_args(data_path)

    # This command has to be run as root for now because some BrainFrame
    # services write files as the root user.
    if not os_utils.is_root():
        print_utils.fail_translate("general.user-not-root")

    docker_compose.assert_installed(install_path)

    dependencies.rsync.ensure(args.noninteractive, args.install_rsync)

    if not args.noninteractive:
        stop_brainframe = print_utils.ask_yes_no("backup.ask-stop-brainframe")
        if not stop_brainframe:
            # BrainFrame needs to be stopped before a backup. If the user
            # doesn't want that, stop the backup
            sys.exit(1)

    docker_compose.run(install_path, ["stop"])

    if args.destination is None:
        now_str = datetime.now().strftime(BACKUP_DIR_FORMAT)
        backup_path = data_path / "backups" / now_str
    else:
        backup_path = args.destination

    try:
        backup_path.mkdir(parents=True, exist_ok=True)
    except PermissionError:
        print_utils.fail_translate("backup.mkdir-permission-denied")

    os_utils.run(
        [
            "rsync",
            "--archive",
            "--verbose",
            "--progress",
            # Avoid backing up backups
            "--exclude",
            "backups",
            str(data_path),
            str(backup_path),
        ]
    )

    # Give the brainframe group access to the resulting backup, to make
    # managing and restoring it easier
    os_utils.give_brainframe_group_rw_access([backup_path])

    print()
    print_utils.translate("backup.complete", color=print_utils.Color.GREEN)
Exemple #2
0
def info():
    args = _parse_args()

    docker_compose.assert_installed(config.install_path.value)

    server_version = docker_compose.check_existing_version(
        config.install_path.value)

    fields = {
        "install_path": config.install_path.value,
        "data_path": config.data_path.value,
        "server_version": server_version,
    }

    if args.field is None:
        # Print all fields
        for name, value in fields.items():
            print(f"{name}: {value}")
    elif args.field in fields:
        # Print just this field's value
        print(fields[args.field])
    else:
        print_utils.fail_translate("info.no-such-field", field=args.field)
Exemple #3
0
def install():
    args = _parse_args()

    if not os_utils.is_root():
        print_utils.fail_translate("general.user-not-root")

    # Print some introductory text
    if not args.noninteractive:
        print_utils.art()
        print_utils.translate("install.thanks")
        print()
    if not os_utils.is_supported():
        print_utils.warning_translate("install.unsupported-os")
        print()

    # Check all dependencies
    dependencies.curl.ensure(args.noninteractive, args.install_curl)
    dependencies.docker.ensure(args.noninteractive, args.install_docker)

    _, _, download_version = docker_compose.check_download_version()
    print_utils.translate("install.install-version", version=download_version)

    if not os_utils.added_to_group("docker"):
        if args.noninteractive:
            add_to_group = args.add_to_docker_group
        else:
            add_to_group = print_utils.ask_yes_no(
                "install.ask-add-to-docker-group")

        if add_to_group:
            os_utils.add_to_group("docker")

    use_default_paths = False
    if not args.noninteractive:
        # Ask the user if they want to specify special paths for installation
        print_utils.translate(
            "install.default-paths",
            default_install_path=config.install_path.default,
            default_data_path=config.data_path.default,
        )
        use_default_paths = print_utils.ask_yes_no(
            "install.ask-use-default-paths", )

    # Set up the install path
    if args.noninteractive:
        install_path = args.install_path
    elif use_default_paths:
        install_path = config.install_path.default
    else:
        install_path = print_utils.ask_path(
            "install.ask-brainframe-install-path",
            config.install_path.default,
        )
    install_path.mkdir(exist_ok=True, parents=True)

    # Set up the data path
    if args.noninteractive:
        data_path = args.data_path
    elif use_default_paths:
        data_path = config.data_path.default
    else:
        data_path = print_utils.ask_path("install.ask-data-path",
                                         config.data_path.default)
    data_path.mkdir(exist_ok=True, parents=True)

    # Set up permissions with the 'brainframe' group
    print_utils.translate("install.create-group-justification")
    os_utils.create_group("brainframe", os_utils.BRAINFRAME_GROUP_ID)
    os_utils.give_brainframe_group_rw_access([data_path, install_path])

    # Optionally add the user to the "brainframe" group
    if not os_utils.added_to_group("brainframe"):
        if args.noninteractive:
            add_to_group = args.add_to_group
        else:
            add_to_group = print_utils.ask_yes_no("install.ask-add-to-group")

        if add_to_group:
            os_utils.add_to_group("brainframe")

    docker_compose.download(install_path / "docker-compose.yml",
                            version=args.version)

    print_utils.translate("install.downloading-images")
    docker_compose.run(install_path, ["pull"])

    print()
    print_utils.translate("install.complete", print_utils.Color.GREEN)

    if not args.noninteractive and print_utils.ask_yes_no("install.ask-start"):
        docker_compose.run(install_path, ["up", "-d"])
        print()
        print_utils.translate("install.running", print_utils.Color.GREEN)
    else:
        print_utils.translate("install.how-to-start")

    # Recommend to the user to add their custom paths to environment variables
    # so that future invocations of the program will know where to look.
    if (install_path != config.install_path.default
            or data_path != config.data_path.default):
        print()
        print_utils.translate("install.set-custom-directory-env-vars")
        print(f"\n"
              f'export {config.install_path.name}="{install_path}"\n'
              f'export {config.data_path.name}="{data_path}"\n')
Exemple #4
0
def update():
    args = _parse_args()

    install_path = config.install_path.value

    docker_compose.assert_installed(install_path)

    if args.version == "latest":
        _, _, requested_version_str = docker_compose.check_download_version()
    else:
        requested_version_str = args.version

    existing_version_str = docker_compose.check_existing_version(install_path)

    existing_version = version.parse(existing_version_str)
    requested_version = version.parse(requested_version_str)

    force_downgrade = False
    if args.noninteractive:
        # Use the --force flag to decide if downgrades are allowed
        force_downgrade = args.force
    else:
        # Ask the user if downgrades should be allowed
        if existing_version >= requested_version:
            force_downgrade = print_utils.ask_yes_no(
                "update.ask-force-downgrade")

    if not force_downgrade:
        # Fail if the requested version is not an upgrade
        if existing_version == requested_version:
            print_utils.fail_translate(
                "update.version-already-installed",
                existing_version=existing_version_str,
                requested_version=requested_version_str,
            )
        elif existing_version > requested_version:
            print_utils.fail_translate(
                "update.downgrade-not-allowed",
                existing_version=existing_version_str,
                requested_version=requested_version_str,
            )

    print_utils.translate(
        "update.upgrade-version",
        existing_version=existing_version_str,
        requested_version=requested_version_str,
    )

    print_utils.translate("general.downloading-docker-compose")
    docker_compose_path = install_path / "docker-compose.yml"
    docker_compose.download(docker_compose_path, version=requested_version_str)

    docker_compose.run(install_path, ["pull"])

    if args.noninteractive:
        restart = args.restart
    else:
        restart = print_utils.ask_yes_no("update.ask-restart")
    if restart:
        docker_compose.run(install_path, ["down"])
        docker_compose.run(install_path, ["up", "-d"])

    print()
    print_utils.translate("update.complete", color=print_utils.Color.GREEN)
Exemple #5
0
 def on_sigint(_sig, _frame):
     print()
     if os_utils.current_command is not None:
         os_utils.current_command.send_signal(_sig)
     print_utils.fail_translate("portal.interrupted")