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

detect & give user option to set app runtime directory

This commit is contained in:
checktheroads
2020-02-14 16:30:40 -07:00
parent 498ad0ba01
commit 96df5469de
4 changed files with 70 additions and 49 deletions

View File

@@ -37,23 +37,62 @@ POSSIBILITY OF SUCH DAMAGE.
"""
# Standard Library
# Standard Library Imports
import os
import sys
from datetime import datetime
import getpass
from pathlib import Path
# Third Party
import uvloop
# Third Party Imports
import stackprinter
# Project
# Project Imports
# flake8: noqa: F401
from hyperglass import api, cli, util, constants, execution, exceptions, configuration
from hyperglass.constants import METADATA
stackprinter.set_excepthook()
try:
import stackprinter
except ImportError:
pass
else:
if sys.stdout.isatty():
_style = "darkbg2"
else:
_style = "plaintext"
stackprinter.set_excepthook(style=_style)
config_path = None
_CONFIG_PATHS = (Path.home() / "hyperglass", Path("/etc/hyperglass/"))
for path in _CONFIG_PATHS:
try:
if not isinstance(path, Path):
path = Path(path)
if path.exists():
tmp = path / "test.tmp"
tmp.touch()
if tmp.exists():
config_path = path
tmp.unlink()
break
except Exception:
config_path = None
if config_path is None:
raise RuntimeError(
"""
No configuration directories were determined to both exist and be readable
by hyperglass. hyperglass is running as user '{un}' (UID '{uid}'), and tried to access
the following directories:
{dir}""".format(
un=getpass.getuser(),
uid=os.getuid(),
dir="\n".join([" - " + str(p) for p in _CONFIG_PATHS]),
)
)
os.environ["hyperglass_directory"] = str(config_path)
uvloop.install()
__name__, __version__, __author__, __copyright__, __license__ = constants.METADATA
__name__, __version__, __author__, __copyright__, __license__ = METADATA

View File

@@ -19,7 +19,7 @@ from hyperglass.constants import __version__
from hyperglass.api.events import on_startup, on_shutdown
from hyperglass.api.routes import docs, query, queries, routers
from hyperglass.exceptions import HyperglassError
from hyperglass.configuration import URL_DEV, params
from hyperglass.configuration import URL_DEV, STATIC_PATH, params
from hyperglass.api.error_handlers import (
app_handler,
http_handler,
@@ -35,10 +35,12 @@ from hyperglass.api.models.response import (
WORKING_DIR = Path(__file__).parent
STATIC_DIR = WORKING_DIR.parent / "static"
UI_DIR = STATIC_DIR / "ui"
IMAGES_DIR = STATIC_DIR / "images"
EXAMPLES_DIR = WORKING_DIR / "examples"
UI_DIR = STATIC_PATH / "ui"
CUSTOM_DIR = STATIC_PATH / "custom"
EXAMPLE_DEVICES_PY = EXAMPLES_DIR / "devices.py"
EXAMPLE_QUERIES_PY = EXAMPLES_DIR / "queries.py"
EXAMPLE_QUERY_PY = EXAMPLES_DIR / "query.py"
@@ -59,6 +61,11 @@ if params.docs.enable:
elif params.docs.mode == "swagger":
DOCS_PARAMS.update({"docs_url": params.docs.uri, "redoc_url": None})
for directory in (UI_DIR, IMAGES_DIR):
if not directory.exists():
log.warning("Directory '{d}' does not exist, creating...", d=str(directory))
directory.mkdir()
# Main App Definition
app = FastAPI(
debug=params.debug,
@@ -200,6 +207,7 @@ if params.docs.enable:
log.debug(f"API Docs config: {app.openapi()}")
app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images")
app.mount("/custom", StaticFiles(directory=CUSTOM_DIR), name="custom")
app.mount("/", StaticFiles(directory=UI_DIR, html=True), name="ui")

View File

@@ -14,6 +14,7 @@ from hyperglass.exceptions import HyperglassError
from hyperglass.configuration import (
URL_DEV,
URL_PROD,
CONFIG_PATH,
REDIS_CONFIG,
params,
frontend_params,
@@ -66,6 +67,7 @@ async def build_ui():
dev_url=URL_DEV,
prod_url=URL_PROD,
params=frontend_params,
app_path=CONFIG_PATH,
)
except RuntimeError as e:
raise HTTPException(detail=str(e), status_code=500)

View File

@@ -5,7 +5,6 @@ import os
import copy
import math
import asyncio
import getpass
from pathlib import Path
# Third Party
@@ -32,15 +31,11 @@ from hyperglass.configuration.models import routers as _routers
from hyperglass.configuration.models import commands as _commands
from hyperglass.configuration.markdown import get_markdown
CONFIG_PATH = Path(os.environ["hyperglass_directory"])
log.info("Configuration directory: {d}", d=str(CONFIG_PATH))
# Project Directories
WORKING_DIR = Path(__file__).resolve().parent
CONFIG_PATHS = (
Path("/etc/hyperglass/"),
Path.home() / "hyperglass",
WORKING_DIR.parent.parent,
WORKING_DIR.parent,
WORKING_DIR,
)
CONFIG_FILES = (
("hyperglass.yaml", False),
("devices.yaml", True),
@@ -48,30 +43,6 @@ CONFIG_FILES = (
)
async def _check_config_paths():
"""Verify supported configuration directories exist and are readable."""
config_path = None
for path in CONFIG_PATHS:
checked = await check_path(path)
if checked is not None:
config_path = checked
break
if config_path is None:
raise ConfigError(
"""
No configuration directories were determined to both exist and be readable
by hyperglass. hyperglass is running as user '{un}' (UID '{uid}'), and tried to access
the following directories:
{dir}""".format(
un=getpass.getuser(),
uid=os.getuid(),
dir="\n".join([" - " + str(p) for p in CONFIG_PATHS]),
)
)
log.info("Configuration directory: {d}", d=str(config_path))
return config_path
async def _check_config_files(directory):
"""Verify config files exist and are readable.
@@ -105,7 +76,7 @@ async def _check_config_files(directory):
return files
CONFIG_PATH = asyncio.run(_check_config_paths())
STATIC_PATH = CONFIG_PATH / "static"
CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = asyncio.run(
_check_config_files(CONFIG_PATH)
@@ -171,7 +142,7 @@ async def _config_commands():
async with AIOFile(CONFIG_COMMANDS, "r") as cf:
raw = await cf.read()
config = yaml.safe_load(raw) or {}
log.debug(f"Unvalidated commands: {config}")
log.debug("Unvalidated commands: {c}", c=config)
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(error_msg=str(yaml_error)) from None
return config
@@ -187,7 +158,7 @@ async def _config_devices():
async with AIOFile(CONFIG_DEVICES, "r") as cf:
raw = await cf.read()
config = yaml.safe_load(raw)
log.debug(f"Unvalidated device config: {config}")
log.debug("Unvalidated device config: {c}", c=config)
except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error:
raise ConfigError(error_msg=str(yaml_error)) from None
return config
@@ -197,7 +168,7 @@ user_config = asyncio.run(_config_main())
# Logging Config
try:
_debug = user_config["general"]["debug"]
_debug = user_config["debug"]
except KeyError:
_debug = True
@@ -454,6 +425,7 @@ frontend_networks = _build_frontend_networks()
frontend_devices = _build_frontend_devices()
_frontend_fields = {
"debug": ...,
"developer_mode": ...,
"primary_asn": ...,
"request_timeout": ...,
"org_name": ...,
@@ -479,7 +451,7 @@ _frontend_params.update(
)
frontend_params = _frontend_params
URL_DEV = f"http://localhost:{str(params.listen_port)}/api/"
URL_DEV = f"http://localhost:{str(params.listen_port)}/"
URL_PROD = "/api/"
REDIS_CONFIG = {