feat: implement resolve_storage_dir for consistent storage paths

This commit is contained in:
Lloyd
2026-05-05 17:17:12 +01:00
parent ebfc629218
commit e4efc8045d
4 changed files with 43 additions and 26 deletions
+34
View File
@@ -9,6 +9,30 @@ import yaml
logger = logging.getLogger("Config")
def resolve_storage_dir(
config: Dict[str, Any],
*,
config_path: Optional[str] = None,
default: str = "/var/lib/pymc_repeater",
) -> Path:
storage_dir_cfg = (
config.get("storage", {}).get("storage_dir")
or config.get("storage_dir")
or default
)
storage_dir = Path(str(storage_dir_cfg)).expanduser()
if not storage_dir.is_absolute():
if config_path:
base_dir = Path(config_path).expanduser().resolve().parent
storage_dir = (base_dir / storage_dir).resolve()
else:
storage_dir = storage_dir.resolve()
return storage_dir
def get_node_info(config: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract node name, radio configuration, and MQTT settings from config.
@@ -65,6 +89,16 @@ def load_config(config_path: Optional[str] = None) -> Dict[str, Any]:
except Exception as e:
raise RuntimeError(f"Failed to load configuration from {config_path}: {e}") from e
storage_dir = resolve_storage_dir(config, config_path=config_path)
if "storage" not in config or not isinstance(config.get("storage"), dict):
config["storage"] = {}
config["storage"]["storage_dir"] = str(storage_dir)
if config.get("storage_dir"):
logger.warning(
"Deprecated config key 'storage_dir' detected; prefer 'storage.storage_dir'."
)
if "mesh" not in config:
config["mesh"] = {}
@@ -6,6 +6,8 @@ from datetime import datetime
from pathlib import Path
from typing import Any, Dict, Optional
from repeater.config import resolve_storage_dir
from .mqtt_handler import MeshCoreToMqttPusher
from .rrdtool_handler import RRDToolHandler
from .sqlite_handler import SQLiteHandler
@@ -21,12 +23,7 @@ class StorageCollector:
self.glass_publish_callback = None
self._pending_tasks = set()
storage_dir_cfg = (
config.get("storage", {}).get("storage_dir")
or config.get("storage_dir")
or "/var/lib/pymc_repeater"
)
self.storage_dir = Path(storage_dir_cfg)
self.storage_dir = resolve_storage_dir(config)
self.storage_dir.mkdir(parents=True, exist_ok=True)
self.sqlite_handler = SQLiteHandler(self.storage_dir)
+4 -19
View File
@@ -15,7 +15,7 @@ from repeater.companion.identity_resolve import (
find_companion_index,
heal_companion_empty_names,
)
from repeater.config import update_unscoped_flood_policy
from repeater.config import resolve_storage_dir, update_unscoped_flood_policy
from repeater.service_utils import get_buildroot_image_info
from .auth.middleware import require_auth
@@ -337,12 +337,7 @@ class APIEndpoints:
import json
# Check config-based location first, then development location
storage_dir_cfg = (
self.config.get("storage", {}).get("storage_dir")
or self.config.get("storage_dir")
or "/var/lib/pymc_repeater"
)
config_dir = Path(storage_dir_cfg)
config_dir = resolve_storage_dir(self.config, config_path=self._config_path)
installed_path = config_dir / "radio-settings.json"
dev_path = os.path.join(os.path.dirname(__file__), "..", "..", "radio-settings.json")
@@ -387,12 +382,7 @@ class APIEndpoints:
import json
# Check config-based location first, then development location
storage_dir_cfg = (
self.config.get("storage", {}).get("storage_dir")
or self.config.get("storage_dir")
or "/var/lib/pymc_repeater"
)
config_dir = Path(storage_dir_cfg)
config_dir = resolve_storage_dir(self.config, config_path=self._config_path)
installed_path = config_dir / "radio-presets.json"
dev_path = os.path.join(os.path.dirname(__file__), "..", "..", "radio-presets.json")
@@ -448,12 +438,7 @@ class APIEndpoints:
import json
storage_dir_cfg = (
self.config.get("storage", {}).get("storage_dir")
or self.config.get("storage_dir")
or "/var/lib/pymc_repeater"
)
config_dir = Path(storage_dir_cfg)
config_dir = resolve_storage_dir(self.config, config_path=self._config_path)
installed_path = config_dir / "radio-settings.json"
dev_path = os.path.join(os.path.dirname(__file__), "..", "..", "radio-settings.json")
hardware_file = str(installed_path) if installed_path.exists() else dev_path
+2 -1
View File
@@ -13,6 +13,7 @@ import cherrypy_cors
from pymc_core.protocol.utils import PAYLOAD_TYPES, ROUTE_TYPES
from repeater import __version__
from repeater.config import resolve_storage_dir
from repeater.data_acquisition import SQLiteHandler
from .api_endpoints import APIEndpoints
@@ -261,7 +262,7 @@ class HTTPStatsServer:
logger.info(f"JWT handler initialized (token expiry: {jwt_expiry_minutes} minutes)")
# Initialize API token manager
storage_dir = self.config.get("storage", {}).get("storage_dir", ".")
storage_dir = resolve_storage_dir(self.config, config_path=self.config_path)
# Ensure storage directory exists
os.makedirs(storage_dir, exist_ok=True)