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 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()]

View file

@ -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

View file

@ -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:
""" """

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) 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