mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-10-12 04:16:16 +00:00
Improve EOSdash.
Make EOSdash use UI components from MonsterUI to ease further development. - Add a first menu with some dummy pages and the configuration page. - Make the configuration scrollable. - Add markdown component that uses markdown-it-py (same as used by the myth-parser for documentation generation). - Add bokeh (https://docs.bokeh.org/) component for charts - Added several prediction charts to demo - Add a footer that displays connection status with EOS server - Add logo and favicon Update EOS server: - Move error message generation to extra module - Use redirect instead of proxy Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
"""Server Module."""
|
||||
|
||||
import os
|
||||
from typing import Optional
|
||||
import time
|
||||
from typing import Optional, Union
|
||||
|
||||
import psutil
|
||||
from pydantic import Field, IPvAnyAddress, field_validator
|
||||
|
||||
from akkudoktoreos.config.configabc import SettingsBaseModel
|
||||
@@ -17,12 +19,78 @@ def get_default_host() -> str:
|
||||
return "0.0.0.0"
|
||||
|
||||
|
||||
class ServerCommonSettings(SettingsBaseModel):
|
||||
"""Server Configuration.
|
||||
def wait_for_port_free(port: int, timeout: int = 0, waiting_app_name: str = "App") -> bool:
|
||||
"""Wait for a network port to become free, with timeout.
|
||||
|
||||
Attributes:
|
||||
To be added
|
||||
Checks if the port is currently in use and logs warnings with process details.
|
||||
Retries every 3 seconds until timeout is reached.
|
||||
|
||||
Args:
|
||||
port: The network port number to check
|
||||
timeout: Maximum seconds to wait (0 means check once without waiting)
|
||||
waiting_app_name: Name of the application waiting for the port
|
||||
|
||||
Returns:
|
||||
bool: True if port is free, False if port is still in use after timeout
|
||||
|
||||
Raises:
|
||||
ValueError: If port number or timeout is invalid
|
||||
psutil.Error: If there are problems accessing process information
|
||||
"""
|
||||
if not 0 <= port <= 65535:
|
||||
raise ValueError(f"Invalid port number: {port}")
|
||||
if timeout < 0:
|
||||
raise ValueError(f"Invalid timeout: {timeout}")
|
||||
|
||||
def get_processes_using_port() -> list[dict]:
|
||||
"""Get info about processes using the specified port."""
|
||||
processes: list[dict] = []
|
||||
seen_pids: set[int] = set()
|
||||
|
||||
try:
|
||||
for conn in psutil.net_connections(kind="inet"):
|
||||
if conn.laddr.port == port and conn.pid not in seen_pids:
|
||||
try:
|
||||
process = psutil.Process(conn.pid)
|
||||
seen_pids.add(conn.pid)
|
||||
processes.append(process.as_dict(attrs=["pid", "cmdline"]))
|
||||
except psutil.NoSuchProcess:
|
||||
continue
|
||||
except psutil.Error as e:
|
||||
logger.error(f"Error checking port {port}: {e}")
|
||||
raise
|
||||
|
||||
return processes
|
||||
|
||||
retries = max(int(timeout / 3), 1) if timeout > 0 else 1
|
||||
|
||||
for _ in range(retries):
|
||||
process_info = get_processes_using_port()
|
||||
|
||||
if not process_info:
|
||||
return True
|
||||
|
||||
if timeout <= 0:
|
||||
break
|
||||
|
||||
logger.info(f"{waiting_app_name} waiting for port {port} to become free...")
|
||||
time.sleep(3)
|
||||
|
||||
if process_info:
|
||||
logger.warning(
|
||||
f"{waiting_app_name} port {port} still in use after waiting {timeout} seconds."
|
||||
)
|
||||
for info in process_info:
|
||||
logger.warning(
|
||||
f"Process using port - PID: {info['pid']}, Command: {' '.join(info['cmdline'])}"
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ServerCommonSettings(SettingsBaseModel):
|
||||
"""Server Configuration."""
|
||||
|
||||
host: Optional[IPvAnyAddress] = Field(
|
||||
default=get_default_host(), description="EOS server IP address."
|
||||
@@ -37,6 +105,15 @@ class ServerCommonSettings(SettingsBaseModel):
|
||||
)
|
||||
eosdash_port: Optional[int] = Field(default=8504, description="EOSdash server IP port number.")
|
||||
|
||||
@field_validator("host", "eosdash_host", mode="before")
|
||||
def validate_server_host(
|
||||
cls, value: Optional[Union[str, IPvAnyAddress]]
|
||||
) -> Optional[Union[str, IPvAnyAddress]]:
|
||||
if isinstance(value, str):
|
||||
if value.lower() in ("localhost", "loopback"):
|
||||
value = "127.0.0.1"
|
||||
return value
|
||||
|
||||
@field_validator("port", "eosdash_port")
|
||||
def validate_server_port(cls, value: Optional[int]) -> Optional[int]:
|
||||
if value is not None and not (1024 <= value <= 49151):
|
||||
|
Reference in New Issue
Block a user