1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

216 lines
5.5 KiB
Python
Raw Normal View History

2020-01-21 01:08:28 -07:00
"""CLI utility functions."""
2020-02-03 02:35:11 -07:00
# Standard Library
2020-02-14 16:27:08 -07:00
import os
from pathlib import Path
2020-02-03 02:35:11 -07:00
# Third Party
2020-02-14 16:27:08 -07:00
from click import echo, style
2020-01-21 01:08:28 -07:00
2020-02-03 02:35:11 -07:00
# Project
from hyperglass.cli.echo import info, error, status, success
2020-02-14 16:27:08 -07:00
from hyperglass.cli.static import CL, NL, WS, E
2020-01-21 01:08:28 -07:00
PROJECT_ROOT = Path(__file__).parent.parent
2020-01-21 01:08:28 -07:00
def async_command(func):
2020-02-14 16:27:08 -07:00
"""Decororator for to make async functions runable from synchronous code."""
# Standard Library
2020-01-21 01:08:28 -07:00
import asyncio
from functools import update_wrapper
func = asyncio.coroutine(func)
def wrapper(*args, **kwargs):
loop = asyncio.get_event_loop()
return loop.run_until_complete(func(*args, **kwargs))
return update_wrapper(wrapper, func)
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:
2020-02-14 16:27:08 -07:00
echo(
2020-01-21 01:08:28 -07:00
NL[1]
+ WS[msg_len + 8]
+ E.ROCKET
+ NL[1]
+ E.CHECK
2020-02-14 16:27:08 -07:00
+ style(msg_start, fg="green", bold=True)
2020-01-21 01:08:28 -07:00
+ WS[1]
2020-02-14 16:27:08 -07:00
+ style(msg_uri, fg="white")
+ style(msg_host, fg="blue", bold=True)
+ style(CL[1], fg="white")
+ style(msg_port, fg="magenta", bold=True)
2020-01-21 01:08:28 -07:00
+ WS[1]
+ E.ROCKET
+ NL[1]
+ WS[1]
+ NL[1]
)
start()
except Exception as e:
2020-02-14 16:27:08 -07:00
error("Failed to start web server: {e}", e=e)
2020-01-21 01:08:28 -07:00
2020-01-21 17:28:32 -07:00
def build_ui():
"""Create a new UI build.
Raises:
2020-02-14 16:27:08 -07:00
ClickException: Raised on any errors.
2020-01-21 17:28:32 -07:00
"""
try:
# Project
2020-01-21 17:28:32 -07:00
from hyperglass.util import build_frontend
from hyperglass.configuration import CONFIG_PATH, params, frontend_params
from hyperglass.compat._asyncio import aiorun
2020-01-21 17:28:32 -07:00
except ImportError as e:
2020-02-14 16:27:08 -07:00
error("Error importing UI builder: {e}", e=e)
2020-01-21 17:28:32 -07:00
status("Starting new UI build...")
2020-01-28 12:03:47 -07:00
if params.developer_mode:
2020-01-21 17:28:32 -07:00
dev_mode = "development"
2020-03-19 09:26:20 -07:00
else:
dev_mode = "production"
2020-01-21 17:28:32 -07:00
try:
build_success = aiorun(
2020-01-21 17:28:32 -07:00
build_frontend(
2020-01-28 12:03:47 -07:00
dev_mode=params.developer_mode,
2020-02-14 16:27:08 -07:00
dev_url=f"http://localhost:{str(params.listen_port)}/",
2020-01-21 17:28:32 -07:00
prod_url="/api/",
params=frontend_params,
force=True,
2020-02-14 16:27:08 -07:00
app_path=CONFIG_PATH,
2020-01-21 17:28:32 -07:00
)
)
2020-02-14 16:27:08 -07:00
if build_success:
success("Completed UI build in {m} mode", m=dev_mode)
2020-01-21 17:28:32 -07:00
except Exception as e:
2020-02-14 16:27:08 -07:00
error("Error building UI: {e}", e=e)
return True
def create_dir(path, **kwargs):
"""Validate and attempt to create a directory, if it does not exist."""
2020-02-15 21:56:40 -07:00
# If input path is not a path object, try to make it one
2020-02-14 16:27:08 -07:00
if not isinstance(path, Path):
try:
path = Path(path)
except TypeError:
error("{p} is not a valid path", p=path)
2020-02-15 21:56:40 -07:00
# If path does not exist, try to create it
2020-02-14 16:27:08 -07:00
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,
)
2020-02-15 21:56:40 -07:00
# Verify the path was actually created
2020-02-14 16:27:08 -07:00
if path.exists():
success("Created {p}", p=path)
2020-02-15 21:56:40 -07:00
# If the path already exists, inform the user
2020-02-14 16:27:08 -07:00
elif path.exists():
info("{p} already exists", p=path)
return True
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)
2020-01-21 17:28:32 -07:00
return True
2020-02-15 20:02:47 -07:00
def system_info():
"""Create a markdown table of various system information.
Returns:
{str}: Markdown table
"""
# Project
from hyperglass.util.system_info import get_system_info
values = get_system_info()
def _code(val):
return f"`{str(val)}`"
def _bold(val):
return f"**{str(val)}**"
def _suffix(val, suffix):
return f"{str(val)}{str(suffix)}"
columns = (
("hyperglass Version", _bold),
("hyperglass Path", _code),
("Python Version", _code),
("Platform Info", _code),
("CPU Info", None),
("Logical Cores", _code),
("Physical Cores", _code),
("Processor Speed", "GHz"),
("Total Memory", " GB"),
("Memory Utilization", "%"),
("Total Disk Space", " GB"),
("Disk Utilization", "%"),
)
md_table_lines = ("| Metric | Value |", "| ------ | ----- |")
for i, metric in enumerate(values):
title, mod = columns[i]
value = metric
if isinstance(mod, str):
value = _suffix(value, mod)
elif callable(mod):
value = mod(value)
md_table_lines += (f"| **{title}** | {value} |",)
md_table = "\n".join(md_table_lines)
info("Please copy & paste this table in your bug report:\n")
echo(md_table + "\n")
return True