mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-04-19 08:55:15 +00:00
Fix EOSdash startup. (#394)
Some checks are pending
docker-build / platform-excludes (push) Waiting to run
docker-build / build (push) Blocked by required conditions
docker-build / merge (push) Blocked by required conditions
pre-commit / pre-commit (push) Waiting to run
Run Pytest on Pull Request / test (push) Waiting to run
Some checks are pending
docker-build / platform-excludes (push) Waiting to run
docker-build / build (push) Blocked by required conditions
docker-build / merge (push) Blocked by required conditions
pre-commit / pre-commit (push) Waiting to run
Run Pytest on Pull Request / test (push) Waiting to run
Revert to EOSdash startup as a sub-process. Add arguments to control the complete startup of both servers. Also development reload can now be given as an argument. Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
parent
e255e97141
commit
9c91a64c1b
6
Makefile
6
Makefile
@ -84,12 +84,12 @@ clean: clean-docs
|
|||||||
@echo "Deletion complete."
|
@echo "Deletion complete."
|
||||||
|
|
||||||
run:
|
run:
|
||||||
@echo "Starting EOS server, please wait..."
|
@echo "Starting EOS production server, please wait..."
|
||||||
.venv/bin/fastapi run --port 8503 src/akkudoktoreos/server/eos.py
|
.venv/bin/python src/akkudoktoreos/server/eos.py
|
||||||
|
|
||||||
run-dev:
|
run-dev:
|
||||||
@echo "Starting EOS development server, please wait..."
|
@echo "Starting EOS development server, please wait..."
|
||||||
.venv/bin/fastapi dev --port 8503 src/akkudoktoreos/server/eos.py
|
.venv/bin/python src/akkudoktoreos/server/eos.py --host localhost --port 8503 --reload true
|
||||||
|
|
||||||
# Target to setup tests.
|
# Target to setup tests.
|
||||||
test-setup: pip-dev
|
test-setup: pip-dev
|
||||||
|
10
README.md
10
README.md
@ -27,23 +27,23 @@ python -m venv .venv
|
|||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
||||||
```bash
|
```cmd
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
.venv\Scripts\pip install -r requirements.txt
|
.venv\Scripts\pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, start EOS fastapi server:
|
Finally, start the EOS server:
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
.venv/bin/fastapi run --port 8503 src/akkudoktoreos/server/eos.py
|
.venv/bin/python src/akkudoktoreos/server/eos.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
|
|
||||||
```
|
```cmd
|
||||||
.venv\Scripts\fastapi run --port 8503 src/akkudoktoreos/server/eos.py
|
.venv\Scripts\python src/akkudoktoreos/server/eos.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
@ -38,13 +38,13 @@ Start the EOS fastapi server:
|
|||||||
|
|
||||||
.. code-block:: powershell
|
.. code-block:: powershell
|
||||||
|
|
||||||
.venv\Scripts\fastapi run src/akkudoktoreos/server/eos.py
|
.venv\Scripts\python src/akkudoktoreos/server/eos.py
|
||||||
|
|
||||||
.. tab:: Linux
|
.. tab:: Linux
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
.venv/bin/fastapi run src/akkudoktoreos/server/eos.py
|
.venv/bin/python src/akkudoktoreos/server/eos.py
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
@ -36,6 +37,9 @@ measurement_eos = get_measurement()
|
|||||||
prediction_eos = get_prediction()
|
prediction_eos = get_prediction()
|
||||||
ems_eos = get_ems()
|
ems_eos = get_ems()
|
||||||
|
|
||||||
|
# Command line arguments
|
||||||
|
args = None
|
||||||
|
|
||||||
ERROR_PAGE_TEMPLATE = """
|
ERROR_PAGE_TEMPLATE = """
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
@ -129,27 +133,76 @@ def create_error_page(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# EOSdash server startup
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
|
||||||
def start_eosdash() -> subprocess.Popen:
|
def start_eosdash() -> subprocess.Popen:
|
||||||
"""Start the fasthtml server as a subprocess."""
|
"""Start the EOSdash server as a subprocess.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
server_process: The process of the EOSdash server
|
||||||
|
"""
|
||||||
|
eosdash_path = Path(__file__).parent.resolve().joinpath("eosdash.py")
|
||||||
|
|
||||||
|
if args is None:
|
||||||
|
# No command line arguments
|
||||||
|
host = config_eos.server_eosdash_host
|
||||||
|
port = config_eos.server_eosdash_port
|
||||||
|
eos_host = config_eos.server_eos_host
|
||||||
|
eos_port = config_eos.server_eos_port
|
||||||
|
log_level = "info"
|
||||||
|
access_log = False
|
||||||
|
reload = False
|
||||||
|
else:
|
||||||
|
host = args.host
|
||||||
|
port = config_eos.server_eosdash_port if config_eos.server_eosdash_port else (args.port + 1)
|
||||||
|
eos_host = args.host
|
||||||
|
eos_port = args.port
|
||||||
|
log_level = args.log_level
|
||||||
|
access_log = args.access_log
|
||||||
|
reload = args.reload
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
sys.executable,
|
||||||
|
str(eosdash_path),
|
||||||
|
"--host",
|
||||||
|
str(host),
|
||||||
|
"--port",
|
||||||
|
str(port),
|
||||||
|
"--eos-host",
|
||||||
|
str(eos_host),
|
||||||
|
"--eos-port",
|
||||||
|
str(eos_port),
|
||||||
|
"--log_level",
|
||||||
|
log_level,
|
||||||
|
"--access_log",
|
||||||
|
str(access_log),
|
||||||
|
"--reload",
|
||||||
|
str(reload),
|
||||||
|
]
|
||||||
server_process = subprocess.Popen(
|
server_process = subprocess.Popen(
|
||||||
[sys.executable, str(server_dir.joinpath("eosdash.py"))],
|
cmd,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
)
|
)
|
||||||
|
|
||||||
return server_process
|
return server_process
|
||||||
|
|
||||||
|
|
||||||
|
# ----------------------
|
||||||
|
# EOS REST Server
|
||||||
|
# ----------------------
|
||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||||
"""Lifespan manager for the app."""
|
"""Lifespan manager for the app."""
|
||||||
# On startup
|
# On startup
|
||||||
if (
|
if config_eos.server_eos_startup_eosdash:
|
||||||
config_eos.server_eos_startup_eosdash
|
|
||||||
and config_eos.server_eosdash_host
|
|
||||||
and config_eos.server_eosdash_port
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
fasthtml_process = start_eosdash()
|
eosdash_process = start_eosdash()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to start EOSdash server. Error: {e}")
|
logger.error(f"Failed to start EOSdash server. Error: {e}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -169,8 +222,10 @@ app = FastAPI(
|
|||||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html",
|
"url": "https://www.apache.org/licenses/LICENSE-2.0.html",
|
||||||
},
|
},
|
||||||
lifespan=lifespan,
|
lifespan=lifespan,
|
||||||
|
root_path=str(Path(__file__).parent),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# That's the problem
|
# That's the problem
|
||||||
opt_class = optimization_problem(verbose=bool(config_eos.server_eos_verbose))
|
opt_class = optimization_problem(verbose=bool(config_eos.server_eos_verbose))
|
||||||
|
|
||||||
@ -827,7 +882,7 @@ async def proxy_put(request: Request, path: str) -> Response:
|
|||||||
|
|
||||||
async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]:
|
async def proxy(request: Request, path: str) -> Union[Response | RedirectResponse | HTMLResponse]:
|
||||||
if config_eos.server_eosdash_host and config_eos.server_eosdash_port:
|
if config_eos.server_eosdash_host and config_eos.server_eosdash_port:
|
||||||
# Proxy to fasthtml server
|
# Proxy to EOSdash server
|
||||||
url = f"http://{config_eos.server_eosdash_host}:{config_eos.server_eosdash_port}/{path}"
|
url = f"http://{config_eos.server_eosdash_host}:{config_eos.server_eosdash_port}/{path}"
|
||||||
headers = dict(request.headers)
|
headers = dict(request.headers)
|
||||||
|
|
||||||
@ -869,22 +924,102 @@ set 'server_eosdash_host' or 'server_eosdash_port' to None.
|
|||||||
return RedirectResponse(url="/docs")
|
return RedirectResponse(url="/docs")
|
||||||
|
|
||||||
|
|
||||||
def start_eos() -> None:
|
def run_eos(host: str, port: int, log_level: str, access_log: bool, reload: bool) -> None:
|
||||||
"""Start EOS server."""
|
"""Run the EOS server with the specified configurations.
|
||||||
|
|
||||||
|
This function starts the EOS server using the Uvicorn ASGI server. It accepts
|
||||||
|
arguments for the host, port, log level, access log, and reload options. The
|
||||||
|
log level is converted to lowercase to ensure compatibility with Uvicorn's
|
||||||
|
expected log level format. If an error occurs while attempting to bind the
|
||||||
|
server to the specified host and port, an error message is logged and the
|
||||||
|
application exits.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
host (str): The hostname to bind the server to.
|
||||||
|
port (int): The port number to bind the server to.
|
||||||
|
log_level (str): The log level for the server. Options include "critical", "error",
|
||||||
|
"warning", "info", "debug", and "trace".
|
||||||
|
access_log (bool): Whether to enable or disable the access log. Set to True to enable.
|
||||||
|
reload (bool): Whether to enable or disable auto-reload. Set to True for development.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
# Make hostname human (and Windows) friendly
|
||||||
|
if host == "0.0.0.0":
|
||||||
|
host = "localhost"
|
||||||
try:
|
try:
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app,
|
"akkudoktoreos.server.eos:app",
|
||||||
host=str(config_eos.server_eos_host),
|
host=host,
|
||||||
port=config_eos.server_eos_port,
|
port=port,
|
||||||
log_level="debug",
|
log_level=log_level.lower(), # Convert log_level to lowercase
|
||||||
access_log=True,
|
access_log=access_log,
|
||||||
|
reload=reload,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(
|
logger.error(f"Could not bind to host {host}:{port}. Error: {e}")
|
||||||
f"Could not bind to host {config_eos.server_eos_host}:{config_eos.server_eos_port}. Error: {e}"
|
raise e
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Parse command-line arguments and start the EOS server with the specified options.
|
||||||
|
|
||||||
|
This function sets up the argument parser to accept command-line arguments for
|
||||||
|
host, port, log_level, access_log, and reload. It uses default values from the
|
||||||
|
config_eos module if arguments are not provided. After parsing the arguments,
|
||||||
|
it starts the EOS server with the specified configurations.
|
||||||
|
|
||||||
|
Command-line Arguments:
|
||||||
|
--host (str): Host for the EOS server (default: value from config_eos).
|
||||||
|
--port (int): Port for the EOS server (default: value from config_eos).
|
||||||
|
--log_level (str): Log level for the server. Options: "critical", "error", "warning", "info", "debug", "trace" (default: "info").
|
||||||
|
--access_log (bool): Enable or disable access log. Options: True or False (default: False).
|
||||||
|
--reload (bool): Enable or disable auto-reload. Useful for development. Options: True or False (default: False).
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(description="Start EOS server.")
|
||||||
|
|
||||||
|
# Host and port arguments with defaults from config_eos
|
||||||
|
parser.add_argument(
|
||||||
|
"--host",
|
||||||
|
type=str,
|
||||||
|
default=str(config_eos.server_eos_host),
|
||||||
|
help="Host for the EOS server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=config_eos.server_eos_port,
|
||||||
|
help="Port for the EOS server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Optional arguments for log_level, access_log, and reload
|
||||||
|
parser.add_argument(
|
||||||
|
"--log_level",
|
||||||
|
type=str,
|
||||||
|
default="info",
|
||||||
|
help='Log level for the server. Options: "critical", "error", "warning", "info", "debug", "trace" (default: "info")',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--access_log",
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
help="Enable or disable access log. Options: True or False (default: True)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--reload",
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
help="Enable or disable auto-reload. Useful for development. Options: True or False (default: False)",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_eos(args.host, args.port, args.log_level, args.access_log, args.reload)
|
||||||
|
except:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
start_eos()
|
main()
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
import uvicorn
|
import uvicorn
|
||||||
from fasthtml.common import H1, FastHTML, Table, Td, Th, Thead, Titled, Tr
|
from fasthtml.common import H1, FastHTML, Table, Td, Th, Thead, Titled, Tr
|
||||||
|
|
||||||
@ -8,6 +10,8 @@ logger = get_logger(__name__)
|
|||||||
|
|
||||||
config_eos = get_config()
|
config_eos = get_config()
|
||||||
|
|
||||||
|
# Command line arguments
|
||||||
|
args = None
|
||||||
|
|
||||||
configs = []
|
configs = []
|
||||||
for field_name in config_eos.model_fields:
|
for field_name in config_eos.model_fields:
|
||||||
@ -44,15 +48,118 @@ def get(): # type: ignore
|
|||||||
return Titled("EOS Dashboard", H1("Configuration"), config_table())
|
return Titled("EOS Dashboard", H1("Configuration"), config_table())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def run_eosdash(host: str, port: int, log_level: str, access_log: bool, reload: bool) -> None:
|
||||||
|
"""Run the EOSdash server with the specified configurations.
|
||||||
|
|
||||||
|
This function starts the EOSdash server using the Uvicorn ASGI server. It accepts
|
||||||
|
arguments for the host, port, log level, access log, and reload options. The
|
||||||
|
log level is converted to lowercase to ensure compatibility with Uvicorn's
|
||||||
|
expected log level format. If an error occurs while attempting to bind the
|
||||||
|
server to the specified host and port, an error message is logged and the
|
||||||
|
application exits.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
host (str): The hostname to bind the server to.
|
||||||
|
port (int): The port number to bind the server to.
|
||||||
|
log_level (str): The log level for the server. Options include "critical", "error",
|
||||||
|
"warning", "info", "debug", and "trace".
|
||||||
|
access_log (bool): Whether to enable or disable the access log. Set to True to enable.
|
||||||
|
reload (bool): Whether to enable or disable auto-reload. Set to True for development.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
# Make hostname human (and Windows) friendly
|
||||||
|
if host == "0.0.0.0":
|
||||||
|
host = "localhost"
|
||||||
try:
|
try:
|
||||||
logger.info(f"Starting {config_eos.server_eosdash_host}:{config_eos.server_eosdash_port}.")
|
|
||||||
uvicorn.run(
|
uvicorn.run(
|
||||||
app, host=str(config_eos.server_eosdash_host), port=config_eos.server_eosdash_port
|
"akkudoktoreos.server.eosdash:app",
|
||||||
|
host=host,
|
||||||
|
port=port,
|
||||||
|
log_level=log_level.lower(), # Convert log_level to lowercase
|
||||||
|
access_log=access_log,
|
||||||
|
reload=reload,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Error handling for binding issues
|
logger.error(f"Could not bind to host {host}:{port}. Error: {e}")
|
||||||
logger.error(
|
raise e
|
||||||
f"Could not bind to host {config_eos.server_eosdash_host}:{config_eos.server_eosdash_port}. Error: {e}"
|
|
||||||
)
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Parse command-line arguments and start the EOSdash server with the specified options.
|
||||||
|
|
||||||
|
This function sets up the argument parser to accept command-line arguments for
|
||||||
|
host, port, log_level, access_log, and reload. It uses default values from the
|
||||||
|
config_eos module if arguments are not provided. After parsing the arguments,
|
||||||
|
it starts the EOSdash server with the specified configurations.
|
||||||
|
|
||||||
|
Command-line Arguments:
|
||||||
|
--host (str): Host for the EOSdash server (default: value from config_eos).
|
||||||
|
--port (int): Port for the EOSdash server (default: value from config_eos).
|
||||||
|
--eos-host (str): Host for the EOS server (default: value from config_eos).
|
||||||
|
--eos-port (int): Port for the EOS server (default: value from config_eos).
|
||||||
|
--log_level (str): Log level for the server. Options: "critical", "error", "warning", "info", "debug", "trace" (default: "info").
|
||||||
|
--access_log (bool): Enable or disable access log. Options: True or False (default: False).
|
||||||
|
--reload (bool): Enable or disable auto-reload. Useful for development. Options: True or False (default: False).
|
||||||
|
"""
|
||||||
|
parser = argparse.ArgumentParser(description="Start EOSdash server.")
|
||||||
|
|
||||||
|
# Host and port arguments with defaults from config_eos
|
||||||
|
parser.add_argument(
|
||||||
|
"--host",
|
||||||
|
type=str,
|
||||||
|
default=str(config_eos.server_eosdash_host),
|
||||||
|
help="Host for the EOSdash server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=config_eos.server_eosdash_port,
|
||||||
|
help="Port for the EOSdash server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
|
||||||
|
# EOS Host and port arguments with defaults from config_eos
|
||||||
|
parser.add_argument(
|
||||||
|
"--eos-host",
|
||||||
|
type=str,
|
||||||
|
default=str(config_eos.server_eos_host),
|
||||||
|
help="Host for the EOS server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--eos-port",
|
||||||
|
type=int,
|
||||||
|
default=config_eos.server_eos_port,
|
||||||
|
help="Port for the EOS server (default: value from config_eos)",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Optional arguments for log_level, access_log, and reload
|
||||||
|
parser.add_argument(
|
||||||
|
"--log_level",
|
||||||
|
type=str,
|
||||||
|
default="info",
|
||||||
|
help='Log level for the server. Options: "critical", "error", "warning", "info", "debug", "trace" (default: "info")',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--access_log",
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
help="Enable or disable access log. Options: True or False (default: True)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--reload",
|
||||||
|
type=bool,
|
||||||
|
default=False,
|
||||||
|
help="Enable or disable auto-reload. Useful for development. Options: True or False (default: False)",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
run_eosdash(args.host, args.port, args.log_level, args.access_log, args.reload)
|
||||||
|
except:
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user