daemon: adjustments to load local emane models and config services better using a full import

This commit is contained in:
Blake Harnden 2021-05-07 22:49:58 -07:00
parent 3a08b13d6e
commit 85c5ad22e4
4 changed files with 80 additions and 27 deletions

View file

@ -1,9 +1,10 @@
import logging
import pathlib
import pkgutil
from pathlib import Path
from typing import Dict, List, Type
from core import utils
from core import configservices, utils
from core.configservice.base import ConfigService
from core.errors import CoreError
@ -61,12 +62,31 @@ class ConfigServiceManager:
# make service available
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]:
"""
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
:return: list errors when loading and adding services
:return: list errors when loading services
"""
path = pathlib.Path(path)
subdirs = [x for x in path.iterdir() if x.is_dir()]

View file

@ -1,8 +1,10 @@
import logging
import pkgutil
from pathlib import Path
from typing import Dict, List, Type
from core import utils
from core.emane import models as emane_models
from core.emane.emanemodel import EmaneModel
from core.errors import CoreError
@ -13,9 +15,36 @@ class EmaneModelManager:
models: Dict[str, Type[EmaneModel]] = {}
@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.append(path)
@ -26,11 +55,11 @@ class EmaneModelManager:
for model in models:
logger.debug("loading emane model: %s", model.name)
try:
model.load(prefix)
model.load(emane_prefix)
cls.models[model.name] = model
except CoreError as e:
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
@classmethod

View file

@ -7,9 +7,8 @@ from pathlib import Path
from typing import Dict, List, Type
import core.services
from core import configservices, utils
from core import utils
from core.configservice.manager import ConfigServiceManager
from core.emane import models
from core.emane.modelmanager import EmaneModelManager
from core.emulator.session import Session
from core.executables import get_requirements
@ -103,8 +102,7 @@ class CoreEmu:
custom_service_errors = ServiceManager.add_services(service_path)
self.service_errors.extend(custom_service_errors)
# load default config services
config_services_path = Path(configservices.__file__).resolve().parent
self.service_manager.load(config_services_path)
self.service_manager.load_locals()
# load custom config services
custom_dir = self.config.get("custom_config_services_dir")
if custom_dir is not None:
@ -126,16 +124,15 @@ class CoreEmu:
# get version
emane_version = utils.cmd("emane --version")
logger.info("using emane: %s", emane_version)
prefix = self.config.get("emane_prefix", DEFAULT_EMANE_PREFIX)
prefix = Path(prefix)
default_path = Path(models.__file__).resolve().parent
EmaneModelManager.load(default_path, prefix)
emane_prefix = self.config.get("emane_prefix", DEFAULT_EMANE_PREFIX)
emane_prefix = Path(emane_prefix)
EmaneModelManager.load_locals(emane_prefix)
# load custom models
custom_path = self.config.get("emane_models_dir")
if custom_path is not None:
logger.info("loading custom emane models: %s", custom_path)
custom_path = Path(custom_path)
EmaneModelManager.load(custom_path, prefix)
EmaneModelManager.load(custom_path, emane_prefix)
def shutdown(self) -> None:
"""

View file

@ -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)
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.
@ -352,16 +367,8 @@ def load_classes(path: Path, clazz: Generic[T]) -> T:
continue
import_statement = f"{path.name}.{p.stem}"
logger.debug("importing custom module: %s", import_statement)
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
)
loaded = load_module(import_statement, clazz)
classes.extend(loaded)
return classes