Exemplo n.º 1
0
def create_dir(path, **kwargs) -> bool:
    """Validate and attempt to create a directory, if it does not exist."""

    # If input path is not a path object, try to make it one
    if not isinstance(path, Path):
        try:
            path = Path(path)
        except TypeError:
            error("{p} is not a valid path", p=path)

    # If path does not exist, try to create it
    if not path.exists():
        try:
            path.mkdir(**kwargs)
        except PermissionError:
            error(
                "{u} does not have permission to create {p}. Try running with sudo?",
                u=os.getlogin(),
                p=path,
            )

        # Verify the path was actually created
        if path.exists():
            success("Created {p}", p=path)

    # If the path already exists, inform the user
    elif path.exists():
        info("{p} already exists", p=path)

    return True
Exemplo n.º 2
0
def migrate_config(config_dir):
    """Copy example config files and remove .example extensions."""
    status("Migrating example config files...")

    import shutil

    examples = Path(PROJECT_ROOT / "examples").glob("*.yaml.example")

    if not isinstance(config_dir, Path):
        config_dir = Path(config_dir)

    if not config_dir.exists():
        error("'{d}' does not exist", d=str(config_dir))

    migrated = 0
    for file in examples:
        target_file = config_dir / file.with_suffix("").name
        try:
            if target_file.exists():
                info("{f} already exists", f=str(target_file))
            else:
                shutil.copyfile(file, target_file)
                migrated += 1
                info("Migrated {f}", f=str(target_file))
        except Exception as e:
            error("Failed to migrate '{f}': {e}", f=str(target_file), e=e)

    if migrated == 0:
        info("Migrated {n} example config files", n=migrated)
    elif migrated > 0:
        success("Successfully migrated {n} example config files", n=migrated)
Exemplo n.º 3
0
def build_ui(timeout: int) -> None:
    """Create a new UI build."""
    try:
        # Project
        from hyperglass.configuration import CONFIG_PATH, params, frontend_params
        from hyperglass.util.frontend import build_frontend
        from hyperglass.compat._asyncio import aiorun
    except ImportError as e:
        error("Error importing UI builder: {e}", e=e)

    status("Starting new UI build with a {t} second timeout...", t=timeout)

    if params.developer_mode:
        dev_mode = "development"
    else:
        dev_mode = "production"

    try:
        build_success = aiorun(
            build_frontend(
                dev_mode=params.developer_mode,
                dev_url=f"http://localhost:{str(params.listen_port)}/",
                prod_url="/api/",
                params=frontend_params,
                force=True,
                app_path=CONFIG_PATH,
            ))
        if build_success:
            success("Completed UI build in {m} mode", m=dev_mode)

    except Exception as e:
        error("Error building UI: {e}", e=e)

    return True
Exemplo n.º 4
0
def start(build, direct, workers):
    """Start web server and optionally build frontend assets."""
    try:
        from hyperglass.main import start
        from hyperglass.api import start as uvicorn_start
    except ImportError as e:
        error("Error importing hyperglass: {}", str(e))

    kwargs = {}
    if workers != 0:
        kwargs["workers"] = workers

    try:

        if build:
            build_complete = build_ui()

            if build_complete and not direct:
                start(**kwargs)
            elif build_complete and direct:
                uvicorn_start(**kwargs)

        if not build and not direct:
            start(**kwargs)
        elif not build and direct:
            uvicorn_start(**kwargs)

    except Exception as err:
        error(str(err))
Exemplo n.º 5
0
def install_systemd(app_path):
    """Installs generated systemd file to system's systemd directory.

    Arguments:
        app_path {Path} -- hyperglass runtime path

    Raises:
        ClickException: Raised if the /etc/systemd/system does not exist
        ClickException: Raised if the symlinked file does not exit

    Returns:
        {bool} -- True if successful
    """
    service = app_path / "hyperglass.service"
    systemd = Path("/etc/systemd/system")
    installed = systemd / "hyperglass.service"

    if not systemd.exists():
        error("{e} does not exist. Unable to install systemd service.",
              e=systemd)

    installed.symlink_to(service)

    if not installed.exists():
        error("Unable to symlink {s} to {d}", s=service, d=installed)

    success("Symlinked {s} to {d}", s=service, d=installed)
    return True
Exemplo n.º 6
0
def write_to_file(file, data) -> bool:
    """Write string data to a file."""
    try:
        with file.open("w+") as f:
            f.write(data.strip())
    except PermissionError:
        error(
            "{u} does not have permission to write to {f}. Try running with sudo?",
            u=os.getlogin(),
            f=file,
        )
    if not file.exists():
        error("Error writing file {f}", f=file)
    elif file.exists():
        success("Wrote systemd file {f}", f=file)
    return True
Exemplo n.º 7
0
def fix_permissions(directory):
    """Make directory readable by public."""
    import os

    try:
        for root, dirs, files in os.walk(directory):
            for d in dirs:
                full_path = os.path.join(root, d)
                os.chmod(full_path, 0o744)
            for f in files:
                full_path = os.path.join(root, f)
                os.chmod(full_path, 0o744)
            os.chmod(root, 0o744)
    except Exception as e:
        error("Failed to change '{d}' ownership: {e}", d="hyperglass/", e=e)

    success("Successfully changed '{d}' ownership", d="hyperglass/")
Exemplo n.º 8
0
def start_web_server(start, params):
    """Start web server."""
    msg_start = "Starting hyperglass web server on"
    msg_uri = "http://"
    msg_host = str(params["host"])
    msg_port = str(params["port"])
    msg_len = len("".join(
        [msg_start, WS[1], msg_uri, msg_host, CL[1], msg_port]))
    try:
        echo(NL[1] + WS[msg_len + 8] + E.ROCKET + NL[1] + E.CHECK +
             style(msg_start, fg="green", bold=True) + WS[1] +
             style(msg_uri, fg="white") +
             style(msg_host, fg="blue", bold=True) + style(CL[1], fg="white") +
             style(msg_port, fg="magenta", bold=True) + WS[1] + E.ROCKET +
             NL[1] + WS[1] + NL[1])
        start()

    except Exception as e:
        error("Failed to start web server: {e}", e=e)
Exemplo n.º 9
0
def migrate_systemd(source, destination):
    """Copy example systemd service file to /etc/systemd/system/."""
    import os
    import shutil

    basefile, extension = os.path.splitext(source)
    newfile = os.path.join(destination, basefile)

    try:
        status("Migrating example systemd service...")

        if os.path.exists(newfile):
            info("'{f}' already exists", f=str(newfile))
        else:
            shutil.copyfile(source, newfile)

    except Exception as e:
        error("Error migrating example systemd service: {e}", e=e)

    success("Successfully migrated systemd service to: {f}", f=str(newfile))
Exemplo n.º 10
0
def fix_ownership(user, group, directory):
    """Make user & group the owner of the directory."""
    import grp
    import pwd
    import os

    uid = pwd.getpwnam(user).pw_uid
    gid = grp.getgrnam(group).gr_gid
    try:
        for root, dirs, files in os.walk(directory):
            for d in dirs:
                full_path = os.path.join(root, d)
                os.chown(full_path, uid, gid)
            for f in files:
                full_path = os.path.join(root, f)
                os.chown(full_path, uid, gid)
            os.chown(root, uid, gid)
    except Exception as e:
        error("Failed to change '{d}' ownership: {e}", d="hyperglass/", e=e)

    success("Successfully changed '{d}' ownership", d="hyperglass/")
Exemplo n.º 11
0
def build_ui():
    """Create a new UI build.

    Raises:
        ClickException: Raised on any errors.
    """
    try:
        from hyperglass.compat._asyncio import aiorun
        from hyperglass.util import build_frontend
        from hyperglass.configuration import params, frontend_params, CONFIG_PATH
    except ImportError as e:
        error("Error importing UI builder: {e}", e=e)

    status("Starting new UI build...")

    if params.developer_mode:
        dev_mode = "development"
    else:
        dev_mode = "production"

    try:
        build_success = aiorun(
            build_frontend(
                dev_mode=params.developer_mode,
                dev_url=f"http://localhost:{str(params.listen_port)}/",
                prod_url="/api/",
                params=frontend_params,
                force=True,
                app_path=CONFIG_PATH,
            ))
        if build_success:
            success("Completed UI build in {m} mode", m=dev_mode)

    except Exception as e:
        error("Error building UI: {e}", e=e)

    return True
Exemplo n.º 12
0
def write_to_file(file, data):
    """Write string data to a file.

    Arguments:
        file {Path} -- File path
        data {str} -- String data to write

    Returns:
        {bool} -- True if successful
    """
    try:
        with file.open("w+") as f:
            f.write(data.strip())
    except PermissionError:
        error(
            "{u} does not have permission to write to {f}. Try running with sudo?",
            u=os.getlogin(),
            f=file,
        )
    if not file.exists():
        error("Error writing file {f}", f=file)
    elif file.exists():
        success("Wrote systemd file {f}", f=file)
    return True
Exemplo n.º 13
0
def setup(unattended):
    """Define application directory, move example files, generate systemd service."""
    from hyperglass.cli.util import (
        create_dir,
        move_files,
        make_systemd,
        write_to_file,
        migrate_static_assets,
        install_systemd,
    )

    user_path = Path.home() / "hyperglass"
    root_path = Path("/etc/hyperglass/")

    install_paths = [
        inquirer.List(
            "install_path",
            message="Choose a directory for hyperglass",
            choices=[user_path, root_path],
        )
    ]
    if not unattended:
        answer = inquirer.prompt(install_paths)
        if answer is None:
            error("A directory for hyperglass is required")
        install_path = answer["install_path"]

    elif unattended:
        install_path = user_path

    ui_dir = install_path / "static" / "ui"
    images_dir = install_path / "static" / "images"
    favicon_dir = images_dir / "favicons"
    custom_dir = install_path / "static" / "custom"

    create_dir(install_path)

    for path in (ui_dir, images_dir, custom_dir, favicon_dir):
        create_dir(path, parents=True)

    migrate_static_assets(install_path)

    example_dir = WORKING_DIR.parent / "examples"
    files = example_dir.iterdir()

    do_move = True
    if not unattended and not confirm(
            "Do you want to install example configuration files? (This is non-destructive)"
    ):
        do_move = False

    if do_move:
        move_files(example_dir, install_path, files)

    if install_path == user_path:
        user = getuser()
    else:
        user = "******"

    do_systemd = True
    if not unattended and not confirm(
            "Do you want to generate a systemd service file?"):
        do_systemd = False

    if do_systemd:
        systemd_file = install_path / "hyperglass.service"
        systemd = make_systemd(user)
        write_to_file(systemd_file, systemd)
        install_systemd(install_path)
Exemplo n.º 14
0
def move_files(src, dst, files):  # noqa: C901
    """Move iterable of files from source to destination.

    Arguments:
        src {Path} -- Current directory of files
        dst {Path} -- Target destination directory
        files {Iterable} -- Iterable of files
    """

    if not isinstance(src, Path):
        try:
            src = Path(src)
        except TypeError:
            error("{p} is not a valid path", p=src)
    if not isinstance(dst, Path):
        try:
            dst = Path(dst)
        except TypeError:
            error("{p} is not a valid path", p=dst)

    if not isinstance(files, Iterable):
        error(
            "{fa} must be an iterable (list, tuple, or generator). Received {f}",
            fa="Files argument",
            f=files,
        )

    for path in (src, dst):
        if not path.exists():
            error("{p} does not exist", p=str(path))

    migrated = 0

    for file in files:
        dst_file = dst / file.name

        if not file.exists():
            error("{f} does not exist", f=file)

        try:
            if dst_file.exists():
                warning("{f} already exists", f=dst_file)
            else:
                shutil.copyfile(file, dst_file)
                migrated += 1
                info("Migrated {f}", f=dst_file)
        except Exception as e:
            error("Failed to migrate {f}: {e}", f=dst_file, e=e)

    if migrated == 0:
        warning("Migrated {n} files", n=migrated)
    elif migrated > 0:
        success("Successfully migrated {n} files", n=migrated)
    return True