daemon: adjustments to load local emane models and config services better using a full import
This commit is contained in:
parent
3a08b13d6e
commit
85c5ad22e4
4 changed files with 80 additions and 27 deletions
|
@ -1,9 +1,10 @@
|
||||||
import logging
|
import logging
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import pkgutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
from core import utils
|
from core import configservices, utils
|
||||||
from core.configservice.base import ConfigService
|
from core.configservice.base import ConfigService
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
|
|
||||||
|
@ -61,12 +62,31 @@ class ConfigServiceManager:
|
||||||
# make service available
|
# make service available
|
||||||
self.services[name] = service
|
self.services[name] = service
|
||||||
|
|
||||||
|
def load_locals(self) -> List[str]:
|
||||||
|
"""
|
||||||
|
Search and add config service from local core module.
|
||||||
|
|
||||||
|
:return: list of errors when loading services
|
||||||
|
"""
|
||||||
|
errors = []
|
||||||
|
for module_info in pkgutil.walk_packages(
|
||||||
|
configservices.__path__, f"{configservices.__name__}."
|
||||||
|
):
|
||||||
|
services = utils.load_module(module_info.name, ConfigService)
|
||||||
|
for service in services:
|
||||||
|
try:
|
||||||
|
self.add(service)
|
||||||
|
except CoreError as e:
|
||||||
|
errors.append(service.name)
|
||||||
|
logger.debug("not loading config service(%s): %s", service.name, e)
|
||||||
|
return errors
|
||||||
|
|
||||||
def load(self, path: Path) -> List[str]:
|
def load(self, path: Path) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Search path provided for configurable services and add them for being managed.
|
Search path provided for config services and add them for being managed.
|
||||||
|
|
||||||
:param path: path to search configurable services
|
:param path: path to search configurable services
|
||||||
:return: list errors when loading and adding services
|
:return: list errors when loading services
|
||||||
"""
|
"""
|
||||||
path = pathlib.Path(path)
|
path = pathlib.Path(path)
|
||||||
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import logging
|
import logging
|
||||||
|
import pkgutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
|
from core.emane import models as emane_models
|
||||||
from core.emane.emanemodel import EmaneModel
|
from core.emane.emanemodel import EmaneModel
|
||||||
from core.errors import CoreError
|
from core.errors import CoreError
|
||||||
|
|
||||||
|
@ -13,9 +15,36 @@ class EmaneModelManager:
|
||||||
models: Dict[str, Type[EmaneModel]] = {}
|
models: Dict[str, Type[EmaneModel]] = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, path: Path, prefix: Path) -> List[str]:
|
def load_locals(cls, emane_prefix: Path) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Load EMANE models and make them available.
|
Load local core emane models and make them available.
|
||||||
|
|
||||||
|
:param emane_prefix: installed emane prefix
|
||||||
|
:return: list of errors encountered loading emane models
|
||||||
|
"""
|
||||||
|
errors = []
|
||||||
|
for module_info in pkgutil.walk_packages(
|
||||||
|
emane_models.__path__, f"{emane_models.__name__}."
|
||||||
|
):
|
||||||
|
models = utils.load_module(module_info.name, EmaneModel)
|
||||||
|
for model in models:
|
||||||
|
logger.debug("loading emane model: %s", model.name)
|
||||||
|
try:
|
||||||
|
model.load(emane_prefix)
|
||||||
|
cls.models[model.name] = model
|
||||||
|
except CoreError as e:
|
||||||
|
errors.append(model.name)
|
||||||
|
logger.debug("not loading emane model(%s): %s", model.name, e)
|
||||||
|
return errors
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load(cls, path: Path, emane_prefix: Path) -> List[str]:
|
||||||
|
"""
|
||||||
|
Search and load custom emane models and make them available.
|
||||||
|
|
||||||
|
:param path: path to search for custom emane models
|
||||||
|
:param emane_prefix: installed emane prefix
|
||||||
|
:return: list of errors encountered loading emane models
|
||||||
"""
|
"""
|
||||||
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
subdirs = [x for x in path.iterdir() if x.is_dir()]
|
||||||
subdirs.append(path)
|
subdirs.append(path)
|
||||||
|
@ -26,11 +55,11 @@ class EmaneModelManager:
|
||||||
for model in models:
|
for model in models:
|
||||||
logger.debug("loading emane model: %s", model.name)
|
logger.debug("loading emane model: %s", model.name)
|
||||||
try:
|
try:
|
||||||
model.load(prefix)
|
model.load(emane_prefix)
|
||||||
cls.models[model.name] = model
|
cls.models[model.name] = model
|
||||||
except CoreError as e:
|
except CoreError as e:
|
||||||
errors.append(model.name)
|
errors.append(model.name)
|
||||||
logger.debug("not loading service(%s): %s", model.name, e)
|
logger.debug("not loading emane model(%s): %s", model.name, e)
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -7,9 +7,8 @@ from pathlib import Path
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
import core.services
|
import core.services
|
||||||
from core import configservices, utils
|
from core import utils
|
||||||
from core.configservice.manager import ConfigServiceManager
|
from core.configservice.manager import ConfigServiceManager
|
||||||
from core.emane import models
|
|
||||||
from core.emane.modelmanager import EmaneModelManager
|
from core.emane.modelmanager import EmaneModelManager
|
||||||
from core.emulator.session import Session
|
from core.emulator.session import Session
|
||||||
from core.executables import get_requirements
|
from core.executables import get_requirements
|
||||||
|
@ -103,8 +102,7 @@ class CoreEmu:
|
||||||
custom_service_errors = ServiceManager.add_services(service_path)
|
custom_service_errors = ServiceManager.add_services(service_path)
|
||||||
self.service_errors.extend(custom_service_errors)
|
self.service_errors.extend(custom_service_errors)
|
||||||
# load default config services
|
# load default config services
|
||||||
config_services_path = Path(configservices.__file__).resolve().parent
|
self.service_manager.load_locals()
|
||||||
self.service_manager.load(config_services_path)
|
|
||||||
# load custom config services
|
# load custom config services
|
||||||
custom_dir = self.config.get("custom_config_services_dir")
|
custom_dir = self.config.get("custom_config_services_dir")
|
||||||
if custom_dir is not None:
|
if custom_dir is not None:
|
||||||
|
@ -126,16 +124,15 @@ class CoreEmu:
|
||||||
# get version
|
# get version
|
||||||
emane_version = utils.cmd("emane --version")
|
emane_version = utils.cmd("emane --version")
|
||||||
logger.info("using emane: %s", emane_version)
|
logger.info("using emane: %s", emane_version)
|
||||||
prefix = self.config.get("emane_prefix", DEFAULT_EMANE_PREFIX)
|
emane_prefix = self.config.get("emane_prefix", DEFAULT_EMANE_PREFIX)
|
||||||
prefix = Path(prefix)
|
emane_prefix = Path(emane_prefix)
|
||||||
default_path = Path(models.__file__).resolve().parent
|
EmaneModelManager.load_locals(emane_prefix)
|
||||||
EmaneModelManager.load(default_path, prefix)
|
|
||||||
# load custom models
|
# load custom models
|
||||||
custom_path = self.config.get("emane_models_dir")
|
custom_path = self.config.get("emane_models_dir")
|
||||||
if custom_path is not None:
|
if custom_path is not None:
|
||||||
logger.info("loading custom emane models: %s", custom_path)
|
logger.info("loading custom emane models: %s", custom_path)
|
||||||
custom_path = Path(custom_path)
|
custom_path = Path(custom_path)
|
||||||
EmaneModelManager.load(custom_path, prefix)
|
EmaneModelManager.load(custom_path, emane_prefix)
|
||||||
|
|
||||||
def shutdown(self) -> None:
|
def shutdown(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -328,7 +328,22 @@ def load_config(file_path: Path, d: Dict[str, str]) -> None:
|
||||||
logger.exception("error reading file to dict: %s", file_path)
|
logger.exception("error reading file to dict: %s", file_path)
|
||||||
|
|
||||||
|
|
||||||
def load_classes(path: Path, clazz: Generic[T]) -> T:
|
def load_module(import_statement: str, clazz: Generic[T]) -> List[T]:
|
||||||
|
classes = []
|
||||||
|
try:
|
||||||
|
module = importlib.import_module(import_statement)
|
||||||
|
members = inspect.getmembers(module, lambda x: _is_class(module, x, clazz))
|
||||||
|
for member in members:
|
||||||
|
valid_class = member[1]
|
||||||
|
classes.append(valid_class)
|
||||||
|
except Exception:
|
||||||
|
logger.exception(
|
||||||
|
"unexpected error during import, skipping: %s", import_statement
|
||||||
|
)
|
||||||
|
return classes
|
||||||
|
|
||||||
|
|
||||||
|
def load_classes(path: Path, clazz: Generic[T]) -> List[T]:
|
||||||
"""
|
"""
|
||||||
Dynamically load classes for use within CORE.
|
Dynamically load classes for use within CORE.
|
||||||
|
|
||||||
|
@ -352,16 +367,8 @@ def load_classes(path: Path, clazz: Generic[T]) -> T:
|
||||||
continue
|
continue
|
||||||
import_statement = f"{path.name}.{p.stem}"
|
import_statement = f"{path.name}.{p.stem}"
|
||||||
logger.debug("importing custom module: %s", import_statement)
|
logger.debug("importing custom module: %s", import_statement)
|
||||||
try:
|
loaded = load_module(import_statement, clazz)
|
||||||
module = importlib.import_module(import_statement)
|
classes.extend(loaded)
|
||||||
members = inspect.getmembers(module, lambda x: _is_class(module, x, clazz))
|
|
||||||
for member in members:
|
|
||||||
valid_class = member[1]
|
|
||||||
classes.append(valid_class)
|
|
||||||
except Exception:
|
|
||||||
logger.exception(
|
|
||||||
"unexpected error during import, skipping: %s", import_statement
|
|
||||||
)
|
|
||||||
return classes
|
return classes
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue