daemon: refactoring to load emane models one time during startup, updates to account for this change

This commit is contained in:
Blake Harnden 2021-05-07 10:40:18 -07:00
parent 1ddb7b7b24
commit 50e3aadc6b
32 changed files with 271 additions and 332 deletions

View file

@ -31,7 +31,6 @@ from core.api.grpc.emane_pb2 import (
GetEmaneConfigRequest, GetEmaneConfigRequest,
GetEmaneEventChannelRequest, GetEmaneEventChannelRequest,
GetEmaneModelConfigRequest, GetEmaneModelConfigRequest,
GetEmaneModelsRequest,
SetEmaneConfigRequest, SetEmaneConfigRequest,
SetEmaneModelConfigRequest, SetEmaneModelConfigRequest,
) )
@ -943,18 +942,6 @@ class CoreGrpcClient:
response = self.stub.SetEmaneConfig(request) response = self.stub.SetEmaneConfig(request)
return response.result return response.result
def get_emane_models(self, session_id: int) -> List[str]:
"""
Get session emane models.
:param session_id: session id
:return: list of emane models
:raises grpc.RpcError: when session doesn't exist
"""
request = GetEmaneModelsRequest(session_id=session_id)
response = self.stub.GetEmaneModels(request)
return list(response.models)
def get_emane_model_config( def get_emane_model_config(
self, session_id: int, node_id: int, model: str, iface_id: int = -1 self, session_id: int, node_id: int, model: str, iface_id: int = -1
) -> Dict[str, wrappers.ConfigOption]: ) -> Dict[str, wrappers.ConfigOption]:

View file

@ -532,14 +532,11 @@ def get_nem_id(
def get_emane_model_configs(session: Session) -> List[GetEmaneModelConfig]: def get_emane_model_configs(session: Session) -> List[GetEmaneModelConfig]:
configs = [] configs = []
for _id in session.emane.node_configurations: for _id, model_configs in session.emane.node_configs.items():
if _id == -1:
continue
model_configs = session.emane.node_configurations[_id]
for model_name in model_configs: for model_name in model_configs:
model = session.emane.models[model_name] model_class = session.emane.get_model(model_name)
current_config = session.emane.get_model_config(_id, model_name) current_config = session.emane.get_config(_id, model_name)
config = get_config_options(current_config, model) config = get_config_options(current_config, model_class)
node_id, iface_id = utils.parse_iface_config_id(_id) node_id, iface_id = utils.parse_iface_config_id(_id)
iface_id = iface_id if iface_id is not None else -1 iface_id = iface_id if iface_id is not None else -1
model_config = GetEmaneModelConfig( model_config = GetEmaneModelConfig(
@ -591,15 +588,6 @@ def get_hooks(session: Session) -> List[core_pb2.Hook]:
return hooks return hooks
def get_emane_models(session: Session) -> List[str]:
emane_models = []
for model in session.emane.models.keys():
if len(model.split("_")) != 2:
continue
emane_models.append(model)
return emane_models
def get_default_services(session: Session) -> List[ServiceDefaults]: def get_default_services(session: Session) -> List[ServiceDefaults]:
default_services = [] default_services = []
for name, services in session.services.default_services.items(): for name, services in session.services.default_services.items():
@ -643,8 +631,7 @@ def get_node_config_service_configs(session: Session) -> List[ConfigServiceConfi
def get_emane_config(session: Session) -> Dict[str, common_pb2.ConfigOption]: def get_emane_config(session: Session) -> Dict[str, common_pb2.ConfigOption]:
current_config = session.emane.get_configs() return get_config_options(session.emane.config, session.emane.emane_config)
return get_config_options(current_config, session.emane.emane_config)
def get_mobility_node( def get_mobility_node(
@ -676,7 +663,6 @@ def convert_session(session: Session) -> wrappers.Session:
x=x, y=y, z=z, lat=lat, lon=lon, alt=alt, scale=session.location.refscale x=x, y=y, z=z, lat=lat, lon=lon, alt=alt, scale=session.location.refscale
) )
hooks = get_hooks(session) hooks = get_hooks(session)
emane_models = get_emane_models(session)
emane_config = get_emane_config(session) emane_config = get_emane_config(session)
emane_model_configs = get_emane_model_configs(session) emane_model_configs = get_emane_model_configs(session)
wlan_configs = get_wlan_configs(session) wlan_configs = get_wlan_configs(session)
@ -699,7 +685,6 @@ def convert_session(session: Session) -> wrappers.Session:
default_services=default_services, default_services=default_services,
location=location, location=location,
hooks=hooks, hooks=hooks,
emane_models=emane_models,
emane_config=emane_config, emane_config=emane_config,
emane_model_configs=emane_model_configs, emane_model_configs=emane_model_configs,
wlan_configs=wlan_configs, wlan_configs=wlan_configs,

View file

@ -39,8 +39,6 @@ from core.api.grpc.emane_pb2 import (
GetEmaneEventChannelResponse, GetEmaneEventChannelResponse,
GetEmaneModelConfigRequest, GetEmaneModelConfigRequest,
GetEmaneModelConfigResponse, GetEmaneModelConfigResponse,
GetEmaneModelsRequest,
GetEmaneModelsResponse,
SetEmaneConfigRequest, SetEmaneConfigRequest,
SetEmaneConfigResponse, SetEmaneConfigResponse,
SetEmaneModelConfigRequest, SetEmaneModelConfigRequest,
@ -79,6 +77,7 @@ from core.api.grpc.wlan_pb2 import (
WlanLinkRequest, WlanLinkRequest,
WlanLinkResponse, WlanLinkResponse,
) )
from core.emane.modelmanager import EmaneModelManager
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import ( from core.emulator.enumerations import (
@ -211,8 +210,11 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
validation_period=service.validation_period, validation_period=service.validation_period,
) )
config_services.append(service_proto) config_services.append(service_proto)
emane_models = [x.name for x in EmaneModelManager.models.values()]
return core_pb2.GetConfigResponse( return core_pb2.GetConfigResponse(
services=services, config_services=config_services services=services,
config_services=config_services,
emane_models=emane_models,
) )
def StartSession( def StartSession(
@ -264,11 +266,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions) return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
# emane configs # emane configs
config = session.emane.get_configs() session.emane.config.update(request.emane_config)
config.update(request.emane_config)
for config in request.emane_model_configs: for config in request.emane_model_configs:
_id = utils.iface_config_id(config.node_id, config.iface_id) _id = utils.iface_config_id(config.node_id, config.iface_id)
session.emane.set_model_config(_id, config.model, config.config) session.emane.set_config(_id, config.model, config.config)
# wlan configs # wlan configs
for config in request.wlan_configs: for config in request.wlan_configs:
@ -426,57 +427,6 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logger.debug("get session: %s", request) logger.debug("get session: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
# links = []
# nodes = []
# for _id in session.nodes:
# node = session.nodes[_id]
# if not isinstance(node, (PtpNet, CtrlNet)):
# node_proto = grpcutils.get_node_proto(session, node)
# nodes.append(node_proto)
# node_links = get_links(node)
# links.extend(node_links)
# default_services = grpcutils.get_default_services(session)
# x, y, z = session.location.refxyz
# lat, lon, alt = session.location.refgeo
# location = core_pb2.SessionLocation(
# x=x, y=y, z=z, lat=lat, lon=lon, alt=alt, scale=session.location.refscale
# )
# hooks = grpcutils.get_hooks(session)
# emane_models = grpcutils.get_emane_models(session)
# emane_config = grpcutils.get_emane_config(session)
# emane_model_configs = grpcutils.get_emane_model_configs(session)
# wlan_configs = grpcutils.get_wlan_configs(session)
# mobility_configs = grpcutils.get_mobility_configs(session)
# service_configs = grpcutils.get_node_service_configs(session)
# config_service_configs = grpcutils.get_node_config_service_configs(session)
# session_file = str(session.file_path) if session.file_path else None
# options = get_config_options(session.options.get_configs(), session.options)
# servers = [
# core_pb2.Server(name=x.name, host=x.host)
# for x in session.distributed.servers.values()
# ]
# session_proto = core_pb2.Session(
# id=session.id,
# state=session.state.value,
# nodes=nodes,
# links=links,
# dir=str(session.directory),
# user=session.user,
# default_services=default_services,
# location=location,
# hooks=hooks,
# emane_models=emane_models,
# emane_config=emane_config,
# emane_model_configs=emane_model_configs,
# wlan_configs=wlan_configs,
# service_configs=service_configs,
# config_service_configs=config_service_configs,
# mobility_configs=mobility_configs,
# metadata=session.metadata,
# file=session_file,
# options=options,
# servers=servers,
# )
session_proto = grpcutils.convert_session(session) session_proto = grpcutils.convert_session(session)
return core_pb2.GetSessionResponse(session=session_proto) return core_pb2.GetSessionResponse(session=session_proto)
@ -1122,25 +1072,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logger.debug("set emane config: %s", request) logger.debug("set emane config: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
config = session.emane.get_configs() session.emane.config.update(request.config)
config.update(request.config)
return SetEmaneConfigResponse(result=True) return SetEmaneConfigResponse(result=True)
def GetEmaneModels(
self, request: GetEmaneModelsRequest, context: ServicerContext
) -> GetEmaneModelsResponse:
"""
Retrieve all the EMANE models in the session
:param request: get-emane-model request
:param context: context object
:return: get-EMANE-models response that has all the models
"""
logger.debug("get emane models: %s", request)
session = self.get_session(request.session_id, context)
models = grpcutils.get_emane_models(session)
return GetEmaneModelsResponse(models=models)
def GetEmaneModelConfig( def GetEmaneModelConfig(
self, request: GetEmaneModelConfigRequest, context: ServicerContext self, request: GetEmaneModelConfigRequest, context: ServicerContext
) -> GetEmaneModelConfigResponse: ) -> GetEmaneModelConfigResponse:
@ -1154,11 +1088,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logger.debug("get emane model config: %s", request) logger.debug("get emane model config: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
model = session.emane.models.get(request.model) model = session.emane.get_model(request.model)
if not model:
raise CoreError(f"invalid emane model: {request.model}")
_id = utils.iface_config_id(request.node_id, request.iface_id) _id = utils.iface_config_id(request.node_id, request.iface_id)
current_config = session.emane.get_model_config(_id, request.model) current_config = session.emane.get_config(_id, request.model)
config = get_config_options(current_config, model) config = get_config_options(current_config, model)
return GetEmaneModelConfigResponse(config=config) return GetEmaneModelConfigResponse(config=config)
@ -1177,7 +1109,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
model_config = request.emane_model_config model_config = request.emane_model_config
_id = utils.iface_config_id(model_config.node_id, model_config.iface_id) _id = utils.iface_config_id(model_config.node_id, model_config.iface_id)
session.emane.set_model_config(_id, model_config.model, model_config.config) session.emane.set_config(_id, model_config.model, model_config.config)
return SetEmaneModelConfigResponse(result=True) return SetEmaneModelConfigResponse(result=True)
def SaveXml( def SaveXml(
@ -1192,13 +1124,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logger.debug("save xml: %s", request) logger.debug("save xml: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
_, temp_path = tempfile.mkstemp() _, temp_path = tempfile.mkstemp()
session.save_xml(temp_path) session.save_xml(temp_path)
with open(temp_path, "r") as xml_file: with open(temp_path, "r") as xml_file:
data = xml_file.read() data = xml_file.read()
return core_pb2.SaveXmlResponse(data=data) return core_pb2.SaveXmlResponse(data=data)
def OpenXml( def OpenXml(

View file

@ -783,7 +783,6 @@ class Session:
x=0.0, y=0.0, z=0.0, lat=47.57917, lon=-122.13232, alt=2.0, scale=150.0 x=0.0, y=0.0, z=0.0, lat=47.57917, lon=-122.13232, alt=2.0, scale=150.0
) )
hooks: Dict[str, Hook] = field(default_factory=dict) hooks: Dict[str, Hook] = field(default_factory=dict)
emane_models: List[str] = field(default_factory=list)
emane_config: Dict[str, ConfigOption] = field(default_factory=dict) emane_config: Dict[str, ConfigOption] = field(default_factory=dict)
metadata: Dict[str, str] = field(default_factory=dict) metadata: Dict[str, str] = field(default_factory=dict)
file: Path = None file: Path = None
@ -837,7 +836,6 @@ class Session:
default_services=default_services, default_services=default_services,
location=SessionLocation.from_proto(proto.location), location=SessionLocation.from_proto(proto.location),
hooks=hooks, hooks=hooks,
emane_models=list(proto.emane_models),
emane_config=ConfigOption.from_dict(proto.emane_config), emane_config=ConfigOption.from_dict(proto.emane_config),
metadata=dict(proto.metadata), metadata=dict(proto.metadata),
file=file_path, file=file_path,
@ -906,12 +904,17 @@ class Session:
class CoreConfig: class CoreConfig:
services: List[Service] = field(default_factory=list) services: List[Service] = field(default_factory=list)
config_services: List[ConfigService] = field(default_factory=list) config_services: List[ConfigService] = field(default_factory=list)
emane_models: List[str] = field(default_factory=list)
@classmethod @classmethod
def from_proto(cls, proto: core_pb2.GetConfigResponse) -> "CoreConfig": def from_proto(cls, proto: core_pb2.GetConfigResponse) -> "CoreConfig":
services = [Service.from_proto(x) for x in proto.services] services = [Service.from_proto(x) for x in proto.services]
config_services = [ConfigService.from_proto(x) for x in proto.config_services] config_services = [ConfigService.from_proto(x) for x in proto.config_services]
return CoreConfig(services=services, config_services=config_services) return CoreConfig(
services=services,
config_services=config_services,
emane_models=list(proto.emane_models),
)
@dataclass @dataclass

View file

@ -29,6 +29,7 @@ from core.api.tlv.enumerations import (
NodeTlvs, NodeTlvs,
SessionTlvs, SessionTlvs,
) )
from core.emane.modelmanager import EmaneModelManager
from core.emulator.data import ( from core.emulator.data import (
ConfigData, ConfigData,
EventData, EventData,
@ -419,8 +420,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
tlv_data += coreapi.CoreRegisterTlv.pack( tlv_data += coreapi.CoreRegisterTlv.pack(
self.session.emane.config_type.value, self.session.emane.name self.session.emane.config_type.value, self.session.emane.name
) )
for model_name in self.session.emane.models: for model_name, model_class in EmaneModelManager.models.items():
model_class = self.session.emane.models[model_name]
tlv_data += coreapi.CoreRegisterTlv.pack( tlv_data += coreapi.CoreRegisterTlv.pack(
model_class.config_type.value, model_class.name model_class.config_type.value, model_class.name
) )
@ -1048,7 +1048,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
replies = self.handle_config_mobility_models(message_type, config_data) replies = self.handle_config_mobility_models(message_type, config_data)
elif config_data.object == self.session.emane.name: elif config_data.object == self.session.emane.name:
replies = self.handle_config_emane(message_type, config_data) replies = self.handle_config_emane(message_type, config_data)
elif config_data.object in self.session.emane.models: elif config_data.object in EmaneModelManager.models:
replies = self.handle_config_emane_models(message_type, config_data) replies = self.handle_config_emane_models(message_type, config_data)
else: else:
raise Exception("no handler for configuration: %s", config_data.object) raise Exception("no handler for configuration: %s", config_data.object)
@ -1393,7 +1393,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
if message_type == ConfigFlags.REQUEST: if message_type == ConfigFlags.REQUEST:
logger.info("replying to configure request for %s model", object_name) logger.info("replying to configure request for %s model", object_name)
typeflags = ConfigFlags.NONE.value typeflags = ConfigFlags.NONE.value
config = self.session.emane.get_configs() config = self.session.emane.config
config_response = ConfigShim.config_data( config_response = ConfigShim.config_data(
0, node_id, typeflags, self.session.emane.emane_config, config 0, node_id, typeflags, self.session.emane.emane_config, config
) )
@ -1405,7 +1405,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
if values_str: if values_str:
config = ConfigShim.str_to_dict(values_str) config = ConfigShim.str_to_dict(values_str)
self.session.emane.set_configs(config) self.session.emane.config = config
return replies return replies
@ -1424,12 +1424,12 @@ class CoreHandler(socketserver.BaseRequestHandler):
logger.info("replying to configure request for model: %s", object_name) logger.info("replying to configure request for model: %s", object_name)
typeflags = ConfigFlags.NONE.value typeflags = ConfigFlags.NONE.value
model_class = self.session.emane.models.get(object_name) model_class = self.session.emane.get_model(object_name)
if not model_class: if not model_class:
logger.warning("model class does not exist: %s", object_name) logger.warning("model class does not exist: %s", object_name)
return [] return []
config = self.session.emane.get_model_config(node_id, object_name) config = self.session.emane.get_config(node_id, object_name)
config_response = ConfigShim.config_data( config_response = ConfigShim.config_data(
0, node_id, typeflags, model_class, config 0, node_id, typeflags, model_class, config
) )
@ -1439,12 +1439,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
if not object_name: if not object_name:
logger.warning("no configuration object for node: %s", node_id) logger.warning("no configuration object for node: %s", node_id)
return [] return []
parsed_config = {} parsed_config = {}
if values_str: if values_str:
parsed_config = ConfigShim.str_to_dict(values_str) parsed_config = ConfigShim.str_to_dict(values_str)
self.session.emane.node_models[node_id] = object_name
self.session.emane.set_model_config(node_id, object_name, parsed_config) self.session.emane.set_config(node_id, object_name, parsed_config)
return replies return replies
@ -1853,7 +1852,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
self.session.broadcast_config(config_data) self.session.broadcast_config(config_data)
# send global emane config # send global emane config
config = self.session.emane.get_configs() config = self.session.emane.config
logger.debug("global emane config: values(%s)", config) logger.debug("global emane config: values(%s)", config)
config_data = ConfigShim.config_data( config_data = ConfigShim.config_data(
0, None, ConfigFlags.UPDATE.value, self.session.emane.emane_config, config 0, None, ConfigFlags.UPDATE.value, self.session.emane.emane_config, config
@ -1861,11 +1860,9 @@ class CoreHandler(socketserver.BaseRequestHandler):
self.session.broadcast_config(config_data) self.session.broadcast_config(config_data)
# send emane model configs # send emane model configs
for node_id in self.session.emane.nodes(): for node_id, model_configs in self.session.emane.node_configs.items():
emane_configs = self.session.emane.get_all_configs(node_id) for model_name, config in model_configs.items():
for model_name in emane_configs: model_class = self.session.emane.get_model(model_name)
config = emane_configs[model_name]
model_class = self.session.emane.models[model_name]
logger.debug( logger.debug(
"emane config: node(%s) class(%s) values(%s)", "emane config: node(%s) class(%s) values(%s)",
node_id, node_id,

View file

@ -31,7 +31,7 @@ class ConfigServiceManager:
""" """
service_class = self.services.get(name) service_class = self.services.get(name)
if service_class is None: if service_class is None:
raise CoreError(f"service does not exit {name}") raise CoreError(f"service does not exist {name}")
return service_class return service_class
def add(self, service: Type[ConfigService]) -> None: def add(self, service: Type[ConfigService]) -> None:

View file

@ -12,16 +12,12 @@ from pathlib import Path
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type
from core import utils from core import utils
from core.config import ConfigGroup, Configuration, ModelManager from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest from core.emane import emanemanifest
from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel
from core.emane.emanemodel import EmaneModel from core.emane.emanemodel import EmaneModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel
from core.emane.linkmonitor import EmaneLinkMonitor from core.emane.linkmonitor import EmaneLinkMonitor
from core.emane.modelmanager import EmaneModelManager
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.data import LinkData from core.emulator.data import LinkData
from core.emulator.enumerations import ( from core.emulator.enumerations import (
ConfigDataTypes, ConfigDataTypes,
@ -55,15 +51,9 @@ except ImportError:
EventServiceException = None EventServiceException = None
logger.debug("compatible emane python bindings not installed") logger.debug("compatible emane python bindings not installed")
EMANE_MODELS = [
EmaneRfPipeModel,
EmaneIeee80211abgModel,
EmaneCommEffectModel,
EmaneBypassModel,
EmaneTdmaModel,
]
DEFAULT_EMANE_PREFIX = "/usr" DEFAULT_EMANE_PREFIX = "/usr"
DEFAULT_DEV = "ctrl0" DEFAULT_DEV = "ctrl0"
DEFAULT_LOG_LEVEL: int = 3
class EmaneState(Enum): class EmaneState(Enum):
@ -78,7 +68,7 @@ class StartData:
ifaces: List[CoreInterface] = field(default_factory=list) ifaces: List[CoreInterface] = field(default_factory=list)
class EmaneManager(ModelManager): class EmaneManager:
""" """
EMANE controller object. Lives in a Session instance and is used for EMANE controller object. Lives in a Session instance and is used for
building EMANE config files for all EMANE networks in this emulation, and for building EMANE config files for all EMANE networks in this emulation, and for
@ -87,9 +77,6 @@ class EmaneManager(ModelManager):
name: str = "emane" name: str = "emane"
config_type: RegisterTlvs = RegisterTlvs.EMULATION_SERVER config_type: RegisterTlvs = RegisterTlvs.EMULATION_SERVER
NOT_READY: int = 2
EVENTCFGVAR: str = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL: int = 3
def __init__(self, session: "Session") -> None: def __init__(self, session: "Session") -> None:
""" """
@ -116,7 +103,9 @@ class EmaneManager(ModelManager):
# model for global EMANE configuration options # model for global EMANE configuration options
self.emane_config: EmaneGlobalModel = EmaneGlobalModel(session) self.emane_config: EmaneGlobalModel = EmaneGlobalModel(session)
self.set_configs(self.emane_config.default_values()) self.config: Dict[str, str] = self.emane_config.default_values()
self.node_configs: Dict[int, Dict[str, Dict[str, str]]] = {}
self.node_models: Dict[int, str] = {}
# link monitor # link monitor
self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self) self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self)
@ -124,14 +113,63 @@ class EmaneManager(ModelManager):
self.service: Optional[EventService] = None self.service: Optional[EventService] = None
self.eventchannel: Optional[Tuple[str, int, str]] = None self.eventchannel: Optional[Tuple[str, int, str]] = None
self.event_device: Optional[str] = None self.event_device: Optional[str] = None
self.emane_check()
def next_nem_id(self) -> int: def next_nem_id(self) -> int:
nem_id = int(self.get_config("nem_id_start")) nem_id = int(self.config["nem_id_start"])
while nem_id in self.nems_to_ifaces: while nem_id in self.nems_to_ifaces:
nem_id += 1 nem_id += 1
return nem_id return nem_id
def get_config(
self, key: int, model: str, default: bool = True
) -> Optional[Dict[str, str]]:
"""
Get the current or default configuration for an emane model.
:param key: key to get configuration for
:param model: emane model to get configuration for
:param default: True to return default configuration when none exists, False
otherwise
:return: emane model configuration
:raises CoreError: when model does not exist
"""
model_class = self.get_model(model)
model_configs = self.node_configs.get(key)
config = None
if model_configs:
config = model_configs.get(model)
if config is None and default:
config = model_class.default_values()
return config
def set_config(self, key: int, model: str, config: Dict[str, str] = None) -> None:
"""
Sets and update the provided configuration against the default model
or currently set emane model configuration.
:param key: configuration key to set
:param model: model to set configuration for
:param config: configuration to update current configuration with
:return: nothing
:raises CoreError: when model does not exist
"""
self.get_model(model)
model_config = self.get_config(key, model)
config = config if config else {}
model_config.update(config)
model_configs = self.node_configs.setdefault(key, {})
model_configs[model] = model_config
def get_model(self, model_name: str) -> Type[EmaneModel]:
"""
Convenience method for getting globally loaded emane models.
:param model_name: name of model to retrieve
:return: emane model class
:raises CoreError: when model does not exist
"""
return EmaneModelManager.get(model_name)
def get_iface_config( def get_iface_config(
self, emane_net: EmaneNet, iface: CoreInterface self, emane_net: EmaneNet, iface: CoreInterface
) -> Dict[str, str]: ) -> Dict[str, str]:
@ -149,46 +187,28 @@ class EmaneManager(ModelManager):
# try to retrieve interface specific configuration # try to retrieve interface specific configuration
if iface.node_id is not None: if iface.node_id is not None:
key = utils.iface_config_id(iface.node.id, iface.node_id) key = utils.iface_config_id(iface.node.id, iface.node_id)
config = self.get_configs(node_id=key, config_type=model_name) config = self.get_config(key, model_name, default=False)
# attempt to retrieve node specific config, when iface config is not present # attempt to retrieve node specific config, when iface config is not present
if not config: if not config:
config = self.get_configs(node_id=iface.node.id, config_type=model_name) config = self.get_config(iface.node.id, model_name, default=False)
# attempt to get emane net specific config, when node config is not present # attempt to get emane net specific config, when node config is not present
if not config: if not config:
# with EMANE 0.9.2+, we need an extra NEM XML from # with EMANE 0.9.2+, we need an extra NEM XML from
# model.buildnemxmlfiles(), so defaults are returned here # model.buildnemxmlfiles(), so defaults are returned here
config = self.get_configs(node_id=emane_net.id, config_type=model_name) config = self.get_config(emane_net.id, model_name, default=False)
# return default config values, when a config is not present # return default config values, when a config is not present
if not config: if not config:
config = emane_net.model.default_values() config = emane_net.model.default_values()
return config return config
def config_reset(self, node_id: int = None) -> None: def config_reset(self, node_id: int = None) -> None:
super().config_reset(node_id) if node_id is None:
self.set_configs(self.emane_config.default_values()) self.config = self.emane_config.default_values()
self.node_configs.clear()
def emane_check(self) -> None: self.node_models.clear()
""" else:
Check if emane is installed and load models. self.node_configs.get(node_id, {}).clear()
del self.node_models[node_id]
:return: nothing
"""
# check for emane
path = utils.which("emane", required=False)
if not path:
logger.info("emane is not installed")
return
# get version
emane_version = utils.cmd("emane --version")
logger.info("using emane: %s", emane_version)
# load default emane models
self.load_models(EMANE_MODELS)
# load custom models
custom_models_path = self.session.options.get_config("emane_models_dir")
if custom_models_path is not None:
custom_models_path = Path(custom_models_path)
emane_models = utils.load_classes(custom_models_path, EmaneModel)
self.load_models(emane_models)
def deleteeventservice(self) -> None: def deleteeventservice(self) -> None:
if self.service: if self.service:
@ -207,13 +227,12 @@ class EmaneManager(ModelManager):
The multicast group and/or port may be configured. The multicast group and/or port may be configured.
""" """
self.deleteeventservice() self.deleteeventservice()
if shutdown: if shutdown:
return return
# Get the control network to be used for events # Get the control network to be used for events
group, port = self.get_config("eventservicegroup").split(":") group, port = self.config["eventservicegroup"].split(":")
self.event_device = self.get_config("eventservicedevice") self.event_device = self.config["eventservicedevice"]
eventnetidx = self.session.get_control_net_index(self.event_device) eventnetidx = self.session.get_control_net_index(self.event_device)
if eventnetidx < 0: if eventnetidx < 0:
logger.error( logger.error(
@ -238,19 +257,6 @@ class EmaneManager(ModelManager):
except EventServiceException: except EventServiceException:
logger.exception("error instantiating emane EventService") logger.exception("error instantiating emane EventService")
def load_models(self, emane_models: List[Type[EmaneModel]]) -> None:
"""
Load EMANE models and make them available.
"""
for emane_model in emane_models:
logger.debug("loading emane model: %s", emane_model.__name__)
emane_prefix = self.session.options.get_config(
"emane_prefix", default=DEFAULT_EMANE_PREFIX
)
emane_prefix = Path(emane_prefix)
emane_model.load(emane_prefix)
self.models[emane_model.name] = emane_model
def add_node(self, emane_net: EmaneNet) -> None: def add_node(self, emane_net: EmaneNet) -> None:
""" """
Add EMANE network object to this manager. Add EMANE network object to this manager.
@ -302,7 +308,7 @@ class EmaneManager(ModelManager):
# control network bridge required for EMANE 0.9.2 # control network bridge required for EMANE 0.9.2
# - needs to exist when eventservice binds to it (initeventservice) # - needs to exist when eventservice binds to it (initeventservice)
otadev = self.get_config("otamanagerdevice") otadev = self.config["otamanagerdevice"]
netidx = self.session.get_control_net_index(otadev) netidx = self.session.get_control_net_index(otadev)
logger.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev) logger.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev)
if netidx < 0: if netidx < 0:
@ -315,7 +321,7 @@ class EmaneManager(ModelManager):
self.session.add_remove_control_net( self.session.add_remove_control_net(
net_index=netidx, remove=False, conf_required=False net_index=netidx, remove=False, conf_required=False
) )
eventdev = self.get_config("eventservicedevice") eventdev = self.config["eventservicedevice"]
logger.debug("emane event service device: eventdev(%s)", eventdev) logger.debug("emane event service device: eventdev(%s)", eventdev)
if eventdev != otadev: if eventdev != otadev:
netidx = self.session.get_control_net_index(eventdev) netidx = self.session.get_control_net_index(eventdev)
@ -408,7 +414,7 @@ class EmaneManager(ModelManager):
logger.exception("error writing to emane nem file") logger.exception("error writing to emane nem file")
def links_enabled(self) -> bool: def links_enabled(self) -> bool:
return self.get_config("link_enabled") == "1" return self.config["link_enabled"] == "1"
def poststartup(self) -> None: def poststartup(self) -> None:
""" """
@ -470,14 +476,12 @@ class EmaneManager(ModelManager):
for node_id in self._emane_nets: for node_id in self._emane_nets:
emane_net = self._emane_nets[node_id] emane_net = self._emane_nets[node_id]
logger.debug("checking emane model for node: %s", node_id) logger.debug("checking emane model for node: %s", node_id)
# skip nodes that already have a model set # skip nodes that already have a model set
if emane_net.model: if emane_net.model:
logger.debug( logger.debug(
"node(%s) already has model(%s)", emane_net.id, emane_net.model.name "node(%s) already has model(%s)", emane_net.id, emane_net.model.name
) )
continue continue
# set model configured for node, due to legacy messaging configuration # set model configured for node, due to legacy messaging configuration
# before nodes exist # before nodes exist
model_name = self.node_models.get(node_id) model_name = self.node_models.get(node_id)
@ -485,9 +489,9 @@ class EmaneManager(ModelManager):
logger.error("emane node(%s) has no node model", node_id) logger.error("emane node(%s) has no node model", node_id)
raise ValueError("emane node has no model set") raise ValueError("emane node has no model set")
config = self.get_model_config(node_id=node_id, model_name=model_name) config = self.get_config(node_id, model_name)
logger.debug("setting emane model(%s) config(%s)", model_name, config) logger.debug("setting emane model(%s) config(%s)", model_name, config)
model_class = self.models[model_name] model_class = self.get_model(model_name)
emane_net.setmodel(model_class, config) emane_net.setmodel(model_class, config)
def get_nem_link( def get_nem_link(
@ -525,22 +529,19 @@ class EmaneManager(ModelManager):
default_values = self.emane_config.default_values() default_values = self.emane_config.default_values()
for name in ["eventservicegroup", "eventservicedevice"]: for name in ["eventservicegroup", "eventservicedevice"]:
a = default_values[name] a = default_values[name]
b = self.get_config(name) b = self.config[name]
if a != b: if a != b:
need_xml = True need_xml = True
if not need_xml: if not need_xml:
# reset to using default config # reset to using default config
self.initeventservice() self.initeventservice()
return return
try: try:
group, port = self.get_config("eventservicegroup").split(":") group, port = self.config["eventservicegroup"].split(":")
except ValueError: except ValueError:
logger.exception("invalid eventservicegroup in EMANE config") logger.exception("invalid eventservicegroup in EMANE config")
return return
dev = self.config["eventservicedevice"]
dev = self.get_config("eventservicedevice")
emanexml.create_event_service_xml(group, port, dev, self.session.directory) emanexml.create_event_service_xml(group, port, dev, self.session.directory)
self.session.distributed.execute( self.session.distributed.execute(
lambda x: emanexml.create_event_service_xml( lambda x: emanexml.create_event_service_xml(
@ -554,7 +555,7 @@ class EmaneManager(ModelManager):
Add a control network even if the user has not configured one. Add a control network even if the user has not configured one.
""" """
logger.info("starting emane daemons...") logger.info("starting emane daemons...")
loglevel = str(EmaneManager.DEFAULT_LOG_LEVEL) loglevel = str(DEFAULT_LOG_LEVEL)
cfgloglevel = self.session.options.get_config_int("emane_log_level") cfgloglevel = self.session.options.get_config_int("emane_log_level")
realtime = self.session.options.get_config_bool("emane_realtime", default=True) realtime = self.session.options.get_config_bool("emane_realtime", default=True)
if cfgloglevel: if cfgloglevel:
@ -564,11 +565,11 @@ class EmaneManager(ModelManager):
if realtime: if realtime:
emanecmd += " -r" emanecmd += " -r"
if isinstance(node, CoreNode): if isinstance(node, CoreNode):
otagroup, _otaport = self.get_config("otamanagergroup").split(":") otagroup, _otaport = self.config["otamanagergroup"].split(":")
otadev = self.get_config("otamanagerdevice") otadev = self.config["otamanagerdevice"]
otanetidx = self.session.get_control_net_index(otadev) otanetidx = self.session.get_control_net_index(otadev)
eventgroup, _eventport = self.get_config("eventservicegroup").split(":") eventgroup, _eventport = self.config["eventservicegroup"].split(":")
eventdev = self.get_config("eventservicedevice") eventdev = self.config["eventservicedevice"]
eventservicenetidx = self.session.get_control_net_index(eventdev) eventservicenetidx = self.session.get_control_net_index(eventdev)
# control network not yet started here # control network not yet started here

View file

@ -189,9 +189,9 @@ class EmaneLinkMonitor:
self.running: bool = False self.running: bool = False
def start(self) -> None: def start(self) -> None:
self.loss_threshold = int(self.emane_manager.get_config("loss_threshold")) self.loss_threshold = int(self.emane_manager.config["loss_threshold"])
self.link_interval = int(self.emane_manager.get_config("link_interval")) self.link_interval = int(self.emane_manager.config["link_interval"])
self.link_timeout = int(self.emane_manager.get_config("link_timeout")) self.link_timeout = int(self.emane_manager.config["link_timeout"])
self.initialize() self.initialize()
if not self.clients: if not self.clients:
logger.info("no valid emane models to monitor links") logger.info("no valid emane models to monitor links")

View file

@ -0,0 +1,41 @@
import logging
from pathlib import Path
from typing import Dict, List, Type
from core import utils
from core.emane.emanemodel import EmaneModel
from core.errors import CoreError
logger = logging.getLogger(__name__)
class EmaneModelManager:
models: Dict[str, Type[EmaneModel]] = {}
@classmethod
def load(cls, path: Path, prefix: Path) -> List[str]:
"""
Load EMANE models and make them available.
"""
subdirs = [x for x in path.iterdir() if x.is_dir()]
subdirs.append(path)
errors = []
for subdir in subdirs:
logger.debug("loading emane models from: %s", subdir)
models = utils.load_classes(subdir, EmaneModel)
for model in models:
logger.debug("loading emane model: %s", model.name)
try:
model.load(prefix)
cls.models[model.name] = model
except CoreError as e:
errors.append(model.name)
logger.debug("not loading service(%s): %s", model.name, e)
return errors
@classmethod
def get(cls, name: str) -> Type[EmaneModel]:
model = cls.models.get(name)
if model is None:
raise CoreError(f"emame model does not exist {name}")
return model

View file

View file

@ -51,17 +51,16 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
:return: nothing :return: nothing
""" """
# get configured schedule # get configured schedule
config = self.session.emane.get_configs(node_id=self.id, config_type=self.name) config = self.session.emane.get_config(self.id, self.name)
if not config: if not config:
return return
schedule = config[self.schedule_name] schedule = Path(config[self.schedule_name])
if not schedule.is_file():
# get the set event device logger.warning("ignoring invalid tdma schedule: %s", schedule)
event_device = self.session.emane.event_device return
# initiate tdma schedule # initiate tdma schedule
event_device = self.session.emane.event_device
logger.info( logger.info(
"setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device "setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device
) )
args = f"emaneevent-tdmaschedule -i {event_device} {schedule}" utils.cmd(f"emaneevent-tdmaschedule -i {event_device} {schedule}")
utils.cmd(args)

View file

@ -9,12 +9,16 @@ from typing import Dict, List, Type
import core.services import core.services
from core import configservices, utils from core import configservices, 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.emulator.session import Session from core.emulator.session import Session
from core.executables import get_requirements from core.executables import get_requirements
from core.services.coreservices import ServiceManager from core.services.coreservices import ServiceManager
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
DEFAULT_EMANE_PREFIX: str = "/usr"
def signal_handler(signal_number: int, _) -> None: def signal_handler(signal_number: int, _) -> None:
""" """
@ -61,6 +65,10 @@ class CoreEmu:
self.service_manager: ConfigServiceManager = ConfigServiceManager() self.service_manager: ConfigServiceManager = ConfigServiceManager()
self._load_services() self._load_services()
# check and load emane
self.has_emane: bool = False
self._load_emane()
# check executables exist on path # check executables exist on path
self._validate_env() self._validate_env()
@ -103,6 +111,32 @@ class CoreEmu:
custom_dir = Path(custom_dir) custom_dir = Path(custom_dir)
self.service_manager.load(custom_dir) self.service_manager.load(custom_dir)
def _load_emane(self) -> None:
"""
Check if emane is installed and load models.
:return: nothing
"""
# check for emane
path = utils.which("emane", required=False)
self.has_emane = path is not None
if not self.has_emane:
logger.info("emane is not installed, emane functionality disabled")
return
# 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)
# 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)
def shutdown(self) -> None: def shutdown(self) -> None:
""" """
Shutdown all CORE session. Shutdown all CORE session.

View file

@ -560,12 +560,8 @@ class Session:
# ensure default emane configuration # ensure default emane configuration
if isinstance(node, EmaneNet) and options.emane: if isinstance(node, EmaneNet) and options.emane:
model = self.emane.models.get(options.emane) model_class = self.emane.get_model(options.emane)
if not model: node.model = model_class(self, node.id)
raise CoreError(
f"node({node.name}) emane model({options.emane}) does not exist"
)
node.model = model(self, node.id)
if self.state == EventTypes.RUNTIME_STATE: if self.state == EventTypes.RUNTIME_STATE:
self.emane.add_node(node) self.emane.add_node(node)
# set default wlan config if needed # set default wlan config if needed

View file

@ -77,6 +77,7 @@ class CoreClient:
self.config_services: Dict[str, ConfigService] = {} self.config_services: Dict[str, ConfigService] = {}
# loaded configuration data # loaded configuration data
self.emane_models: List[str] = []
self.servers: Dict[str, CoreServer] = {} self.servers: Dict[str, CoreServer] = {}
self.custom_nodes: Dict[str, NodeDraw] = {} self.custom_nodes: Dict[str, NodeDraw] = {}
self.custom_observers: Dict[str, Observer] = {} self.custom_observers: Dict[str, Observer] = {}
@ -392,6 +393,7 @@ class CoreClient:
self.client.connect() self.client.connect()
# get current core configurations services/config services # get current core configurations services/config services
core_config = self.client.get_config() core_config = self.client.get_config()
self.emane_models = core_config.emane_models
for service in core_config.services: for service in core_config.services:
group_services = self.services.setdefault(service.group, set()) group_services = self.services.setdefault(service.group, set())
group_services.add(service.name) group_services.add(service.name)
@ -639,11 +641,11 @@ class CoreClient:
image = "ubuntu:latest" image = "ubuntu:latest"
emane = None emane = None
if node_type == NodeType.EMANE: if node_type == NodeType.EMANE:
if not self.session.emane_models: if not self.emane_models:
dialog = EmaneInstallDialog(self.app) dialog = EmaneInstallDialog(self.app)
dialog.show() dialog.show()
return return
emane = self.session.emane_models[0] emane = self.emane_models[0]
name = f"emane{node_id}" name = f"emane{node_id}"
elif node_type == NodeType.WIRELESS_LAN: elif node_type == NodeType.WIRELESS_LAN:
name = f"wlan{node_id}" name = f"wlan{node_id}"

View file

@ -115,7 +115,7 @@ class EmaneConfigDialog(Dialog):
self.radiovar: tk.IntVar = tk.IntVar() self.radiovar: tk.IntVar = tk.IntVar()
self.radiovar.set(1) self.radiovar.set(1)
self.emane_models: List[str] = [ self.emane_models: List[str] = [
x.split("_")[1] for x in self.app.core.session.emane_models x.split("_")[1] for x in self.app.core.emane_models
] ]
model = self.node.emane.split("_")[1] model = self.node.emane.split("_")[1]
self.emane_model: tk.StringVar = tk.StringVar(value=model) self.emane_model: tk.StringVar = tk.StringVar(value=model)

View file

@ -82,7 +82,7 @@ def create_iface_data(iface_element: etree.Element) -> InterfaceData:
def create_emane_config(session: "Session") -> etree.Element: def create_emane_config(session: "Session") -> etree.Element:
emane_configuration = etree.Element("emane_global_configuration") emane_configuration = etree.Element("emane_global_configuration")
config = session.emane.get_configs() config = session.emane.config
emulator_element = etree.SubElement(emane_configuration, "emulator") emulator_element = etree.SubElement(emane_configuration, "emulator")
for emulator_config in session.emane.emane_config.emulator_config: for emulator_config in session.emane.emane_config.emulator_config:
value = config[emulator_config.id] value = config[emulator_config.id]
@ -379,19 +379,15 @@ class CoreXmlWriter:
emane_global_configuration = create_emane_config(self.session) emane_global_configuration = create_emane_config(self.session)
self.scenario.append(emane_global_configuration) self.scenario.append(emane_global_configuration)
emane_configurations = etree.Element("emane_configurations") emane_configurations = etree.Element("emane_configurations")
for node_id in self.session.emane.nodes(): for node_id, model_configs in self.session.emane.node_configs.items():
all_configs = self.session.emane.get_all_configs(node_id)
if not all_configs:
continue
node_id, iface_id = utils.parse_iface_config_id(node_id) node_id, iface_id = utils.parse_iface_config_id(node_id)
for model_name in all_configs: for model_name, config in model_configs.items():
config = all_configs[model_name]
logger.debug( logger.debug(
"writing emane config node(%s) model(%s)", node_id, model_name "writing emane config node(%s) model(%s)", node_id, model_name
) )
model = self.session.emane.models[model_name] model_class = self.session.emane.get_model(model_name)
emane_configuration = create_emane_model_config( emane_configuration = create_emane_model_config(
node_id, model, config, iface_id node_id, model_class, config, iface_id
) )
emane_configurations.append(emane_configuration) emane_configurations.append(emane_configuration)
if emane_configurations.getchildren(): if emane_configurations.getchildren():
@ -748,7 +744,7 @@ class CoreXmlReader:
name = config.get("name") name = config.get("name")
value = config.get("value") value = config.get("value")
configs[name] = value configs[name] = value
self.session.emane.set_configs(config=configs) self.session.emane.config = configs
def read_emane_configs(self) -> None: def read_emane_configs(self) -> None:
emane_configurations = self.scenario.find("emane_configurations") emane_configurations = self.scenario.find("emane_configurations")
@ -765,9 +761,7 @@ class CoreXmlReader:
node = self.session.nodes.get(node_id) node = self.session.nodes.get(node_id)
if not node: if not node:
raise CoreXmlError(f"node for emane config doesn't exist: {node_id}") raise CoreXmlError(f"node for emane config doesn't exist: {node_id}")
model = self.session.emane.models.get(model_name) self.session.emane.get_model(model_name)
if not model:
raise CoreXmlError(f"invalid emane model: {model_name}")
if iface_id is not None and iface_id not in node.ifaces: if iface_id is not None and iface_id not in node.ifaces:
raise CoreXmlError( raise CoreXmlError(
f"invalid interface id({iface_id}) for node({node.name})" f"invalid interface id({iface_id}) for node({node.name})"
@ -796,7 +790,7 @@ class CoreXmlReader:
"reading emane configuration node(%s) model(%s)", node_id, model_name "reading emane configuration node(%s) model(%s)", node_id, model_name
) )
node_id = utils.iface_config_id(node_id, iface_id) node_id = utils.iface_config_id(node_id, iface_id)
self.session.emane.set_model_config(node_id, model_name, configs) self.session.emane.set_config(node_id, model_name, configs)
def read_mobility_configs(self) -> None: def read_mobility_configs(self) -> None:
mobility_configurations = self.scenario.find("mobility_configurations") mobility_configurations = self.scenario.find("mobility_configurations")

View file

@ -166,7 +166,7 @@ def build_platform_xml(
if not isinstance(data.node, CoreNode) and name in transport_configs: if not isinstance(data.node, CoreNode) and name in transport_configs:
value = control_net.brname value = control_net.brname
else: else:
value = emane_manager.get_config(name) value = emane_manager.config[name]
add_param(platform_element, name, value) add_param(platform_element, name, value)
# create nem xml entries for all interfaces # create nem xml entries for all interfaces

View file

@ -1,7 +1,7 @@
# required imports # required imports
from core.api.grpc import client from core.api.grpc import client
from core.api.grpc.wrappers import NodeType, Position from core.api.grpc.wrappers import NodeType, Position
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
# interface helper # interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64") iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")

View file

@ -6,7 +6,7 @@ with the GUI.
import argparse import argparse
import logging import logging
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.data import IpPrefixes, NodeOptions from core.emulator.data import IpPrefixes, NodeOptions

View file

@ -1,5 +1,5 @@
# required imports # required imports
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.data import IpPrefixes, NodeOptions from core.emulator.data import IpPrefixes, NodeOptions

View file

@ -123,8 +123,6 @@ service CoreApi {
} }
// globals // globals
rpc GetEmaneModels (emane.GetEmaneModelsRequest) returns (emane.GetEmaneModelsResponse) {
}
rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) { rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) {
} }
} }
@ -584,17 +582,16 @@ message Session {
repeated services.ServiceDefaults default_services = 7; repeated services.ServiceDefaults default_services = 7;
SessionLocation location = 8; SessionLocation location = 8;
repeated Hook hooks = 9; repeated Hook hooks = 9;
repeated string emane_models = 10; map<string, common.ConfigOption> emane_config = 10;
map<string, common.ConfigOption> emane_config = 11; repeated emane.GetEmaneModelConfig emane_model_configs = 11;
repeated emane.GetEmaneModelConfig emane_model_configs = 12; map<int32, common.MappedConfig> wlan_configs = 12;
map<int32, common.MappedConfig> wlan_configs = 13; repeated services.NodeServiceConfig service_configs = 13;
repeated services.NodeServiceConfig service_configs = 14; repeated configservices.ConfigServiceConfig config_service_configs = 14;
repeated configservices.ConfigServiceConfig config_service_configs = 15; map<int32, common.MappedConfig> mobility_configs = 15;
map<int32, common.MappedConfig> mobility_configs = 16; map<string, string> metadata = 16;
map<string, string> metadata = 17; string file = 17;
string file = 18; map<string, common.ConfigOption> options = 18;
map<string, common.ConfigOption> options = 19; repeated Server servers = 19;
repeated Server servers = 20;
} }
message SessionSummary { message SessionSummary {

View file

@ -21,14 +21,6 @@ message SetEmaneConfigResponse {
bool result = 1; bool result = 1;
} }
message GetEmaneModelsRequest {
int32 session_id = 1;
}
message GetEmaneModelsResponse {
repeated string models = 1;
}
message GetEmaneModelConfigRequest { message GetEmaneModelConfigRequest {
int32 session_id = 1; int32 session_id = 1;
int32 node_id = 2; int32 node_id = 2;

View file

@ -9,13 +9,13 @@ from xml.etree import ElementTree
import pytest import pytest
from core import utils from core import utils
from core.emane.bypass import EmaneBypassModel
from core.emane.commeffect import EmaneCommEffectModel
from core.emane.emanemodel import EmaneModel from core.emane.emanemodel import EmaneModel
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.bypass import EmaneBypassModel
from core.emane.models.commeffect import EmaneCommEffectModel
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.models.rfpipe import EmaneRfPipeModel
from core.emane.models.tdma import EmaneTdmaModel
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel
from core.emulator.data import IpPrefixes, NodeOptions from core.emulator.data import IpPrefixes, NodeOptions
from core.emulator.session import Session from core.emulator.session import Session
from core.errors import CoreCommandError, CoreError from core.errors import CoreCommandError, CoreError
@ -100,14 +100,13 @@ class TestEmane:
# create emane node for networking the core nodes # create emane node for networking the core nodes
session.set_location(47.57917, -122.13232, 2.00000, 1.0) session.set_location(47.57917, -122.13232, 2.00000, 1.0)
options = NodeOptions() options = NodeOptions(emane=model.name)
options.set_position(80, 50) options.set_position(80, 50)
emane_network = session.add_node(EmaneNet, options=options) emane_network = session.add_node(EmaneNet, options=options)
session.emane.set_model(emane_network, model)
# configure tdma # configure tdma
if model == EmaneTdmaModel: if model == EmaneTdmaModel:
session.emane.set_model_config( session.emane.set_config(
emane_network.id, EmaneTdmaModel.name, {"schedule": str(_SCHEDULE)} emane_network.id, EmaneTdmaModel.name, {"schedule": str(_SCHEDULE)}
) )
@ -142,13 +141,13 @@ class TestEmane:
""" """
# create emane node for networking the core nodes # create emane node for networking the core nodes
session.set_location(47.57917, -122.13232, 2.00000, 1.0) session.set_location(47.57917, -122.13232, 2.00000, 1.0)
options = NodeOptions() options = NodeOptions(emane=EmaneIeee80211abgModel.name)
options.set_position(80, 50) options.set_position(80, 50)
emane_network = session.add_node(EmaneNet, options=options) emane_network = session.add_node(EmaneNet, options=options)
config_key = "txpower" config_key = "txpower"
config_value = "10" config_value = "10"
session.emane.set_model( session.emane.set_config(
emane_network, EmaneIeee80211abgModel, {config_key: config_value} emane_network.id, EmaneIeee80211abgModel.name, {config_key: config_value}
) )
# create nodes # create nodes
@ -174,7 +173,7 @@ class TestEmane:
# save xml # save xml
xml_file = tmpdir.join("session.xml") xml_file = tmpdir.join("session.xml")
file_path = xml_file.strpath file_path = xml_file.strpath
session.save_xml(file_path) session.save_xml(Path(file_path))
# verify xml file was created and can be parsed # verify xml file was created and can be parsed
assert xml_file.isfile() assert xml_file.isfile()
@ -190,12 +189,11 @@ class TestEmane:
assert not session.get_node(node2_id, CoreNode) assert not session.get_node(node2_id, CoreNode)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(Path(file_path), start=True)
# retrieve configuration we set originally # retrieve configuration we set originally
value = str( config = session.emane.get_config(emane_id, EmaneIeee80211abgModel.name)
session.emane.get_config(config_key, emane_id, EmaneIeee80211abgModel.name) value = config[config_key]
)
# verify nodes and configuration were restored # verify nodes and configuration were restored
assert session.get_node(node1_id, CoreNode) assert session.get_node(node1_id, CoreNode)
@ -221,9 +219,9 @@ class TestEmane:
session.add_link(node1.id, emane_node.id, iface1_data) session.add_link(node1.id, emane_node.id, iface1_data)
session.add_link(node2.id, emane_node.id, iface2_data) session.add_link(node2.id, emane_node.id, iface2_data)
# set node specific conifg # set node specific config
datarate = "101" datarate = "101"
session.emane.set_model_config( session.emane.set_config(
node1.id, EmaneRfPipeModel.name, {"datarate": datarate} node1.id, EmaneRfPipeModel.name, {"datarate": datarate}
) )
@ -233,7 +231,7 @@ class TestEmane:
# save xml # save xml
xml_file = tmpdir.join("session.xml") xml_file = tmpdir.join("session.xml")
file_path = xml_file.strpath file_path = xml_file.strpath
session.save_xml(file_path) session.save_xml(Path(file_path))
# verify xml file was created and can be parsed # verify xml file was created and can be parsed
assert xml_file.isfile() assert xml_file.isfile()
@ -251,7 +249,7 @@ class TestEmane:
assert not session.get_node(emane_node.id, EmaneNet) assert not session.get_node(emane_node.id, EmaneNet)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(Path(file_path), start=True)
# verify nodes have been recreated # verify nodes have been recreated
assert session.get_node(node1.id, CoreNode) assert session.get_node(node1.id, CoreNode)
@ -262,7 +260,7 @@ class TestEmane:
node = session.nodes[node_id] node = session.nodes[node_id]
links += node.links() links += node.links()
assert len(links) == 2 assert len(links) == 2
config = session.emane.get_model_config(node1.id, EmaneRfPipeModel.name) config = session.emane.get_config(node1.id, EmaneRfPipeModel.name)
assert config["datarate"] == datarate assert config["datarate"] == datarate
def test_xml_emane_interface_config( def test_xml_emane_interface_config(
@ -286,7 +284,7 @@ class TestEmane:
# set node specific conifg # set node specific conifg
datarate = "101" datarate = "101"
config_id = utils.iface_config_id(node1.id, iface1_data.id) config_id = utils.iface_config_id(node1.id, iface1_data.id)
session.emane.set_model_config( session.emane.set_config(
config_id, EmaneRfPipeModel.name, {"datarate": datarate} config_id, EmaneRfPipeModel.name, {"datarate": datarate}
) )
@ -296,7 +294,7 @@ class TestEmane:
# save xml # save xml
xml_file = tmpdir.join("session.xml") xml_file = tmpdir.join("session.xml")
file_path = xml_file.strpath file_path = xml_file.strpath
session.save_xml(file_path) session.save_xml(Path(file_path))
# verify xml file was created and can be parsed # verify xml file was created and can be parsed
assert xml_file.isfile() assert xml_file.isfile()
@ -314,7 +312,7 @@ class TestEmane:
assert not session.get_node(emane_node.id, EmaneNet) assert not session.get_node(emane_node.id, EmaneNet)
# load saved xml # load saved xml
session.open_xml(file_path, start=True) session.open_xml(Path(file_path), start=True)
# verify nodes have been recreated # verify nodes have been recreated
assert session.get_node(node1.id, CoreNode) assert session.get_node(node1.id, CoreNode)
@ -325,5 +323,5 @@ class TestEmane:
node = session.nodes[node_id] node = session.nodes[node_id]
links += node.links() links += node.links()
assert len(links) == 2 assert len(links) == 2
config = session.emane.get_model_config(config_id, EmaneRfPipeModel.name) config = session.emane.get_config(config_id, EmaneRfPipeModel.name)
assert config["datarate"] == datarate assert config["datarate"] == datarate

View file

@ -6,7 +6,7 @@ from core.config import (
Configuration, Configuration,
ModelManager, ModelManager,
) )
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.emulator.session import Session from core.emulator.session import Session
from core.location.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel

View file

@ -33,7 +33,7 @@ from core.api.grpc.wrappers import (
) )
from core.api.tlv.dataconversion import ConfigShim from core.api.tlv.dataconversion import ConfigShim
from core.api.tlv.enumerations import ConfigFlags from core.api.tlv.enumerations import ConfigFlags
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions from core.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions
from core.emulator.enumerations import EventTypes, ExceptionLevels from core.emulator.enumerations import EventTypes, ExceptionLevels
@ -151,7 +151,7 @@ class TestGrpc:
location_alt, location_alt,
) )
assert real_session.location.refscale == location_scale assert real_session.location.refscale == location_scale
assert real_session.emane.get_config(emane_config_key) == emane_config_value assert real_session.emane.config[emane_config_key] == emane_config_value
set_wlan_config = real_session.mobility.get_model_config( set_wlan_config = real_session.mobility.get_model_config(
wlan_node.id, BasicRangeModel.name wlan_node.id, BasicRangeModel.name
) )
@ -543,7 +543,7 @@ class TestGrpc:
# then # then
assert result is True assert result is True
config = session.emane.get_configs() config = session.emane.config
assert len(config) > 1 assert len(config) > 1
assert config[config_key] == config_value assert config[config_key] == config_value
@ -554,7 +554,7 @@ class TestGrpc:
session.set_location(47.57917, -122.13232, 2.00000, 1.0) session.set_location(47.57917, -122.13232, 2.00000, 1.0)
options = NodeOptions(emane=EmaneIeee80211abgModel.name) options = NodeOptions(emane=EmaneIeee80211abgModel.name)
emane_network = session.add_node(EmaneNet, options=options) emane_network = session.add_node(EmaneNet, options=options)
session.emane.set_model(emane_network, EmaneIeee80211abgModel) session.emane.node_models[emane_network.id] = EmaneIeee80211abgModel.name
config_key = "bandwidth" config_key = "bandwidth"
config_value = "900000" config_value = "900000"
option = ConfigOption( option = ConfigOption(
@ -574,9 +574,7 @@ class TestGrpc:
# then # then
assert result is True assert result is True
config = session.emane.get_model_config( config = session.emane.get_config(emane_network.id, EmaneIeee80211abgModel.name)
emane_network.id, EmaneIeee80211abgModel.name
)
assert config[config_key] == config_value assert config[config_key] == config_value
def test_get_emane_model_config(self, grpc_server: CoreGrpcServer): def test_get_emane_model_config(self, grpc_server: CoreGrpcServer):
@ -586,7 +584,7 @@ class TestGrpc:
session.set_location(47.57917, -122.13232, 2.00000, 1.0) session.set_location(47.57917, -122.13232, 2.00000, 1.0)
options = NodeOptions(emane=EmaneIeee80211abgModel.name) options = NodeOptions(emane=EmaneIeee80211abgModel.name)
emane_network = session.add_node(EmaneNet, options=options) emane_network = session.add_node(EmaneNet, options=options)
session.emane.set_model(emane_network, EmaneIeee80211abgModel) session.emane.node_models[emane_network.id] = EmaneIeee80211abgModel.name
# then # then
with client.context_connect(): with client.context_connect():
@ -597,18 +595,6 @@ class TestGrpc:
# then # then
assert len(config) > 0 assert len(config) > 0
def test_get_emane_models(self, grpc_server: CoreGrpcServer):
# given
client = CoreGrpcClient()
session = grpc_server.coreemu.create_session()
# then
with client.context_connect():
models = client.get_emane_models(session.id)
# then
assert len(models) > 0
def test_get_mobility_config(self, grpc_server: CoreGrpcServer): def test_get_mobility_config(self, grpc_server: CoreGrpcServer):
# given # given
client = CoreGrpcClient() client = CoreGrpcClient()

View file

@ -22,7 +22,7 @@ from core.api.tlv.enumerations import (
NodeTlvs, NodeTlvs,
SessionTlvs, SessionTlvs,
) )
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs
from core.errors import CoreError from core.errors import CoreError
from core.location.mobility import BasicRangeModel from core.location.mobility import BasicRangeModel
@ -939,9 +939,7 @@ class TestGui:
coretlv.handle_message(message) coretlv.handle_message(message)
config = coretlv.session.emane.get_model_config( config = coretlv.session.emane.get_config(wlan.id, EmaneIeee80211abgModel.name)
wlan.id, EmaneIeee80211abgModel.name
)
assert config[config_key] == config_value assert config[config_key] == config_value
def test_config_emane_request(self, coretlv: CoreHandler): def test_config_emane_request(self, coretlv: CoreHandler):
@ -973,5 +971,5 @@ class TestGui:
coretlv.handle_message(message) coretlv.handle_message(message)
config = coretlv.session.emane.get_configs() config = coretlv.session.emane.config
assert config[config_key] == config_value assert config[config_key] == config_value

View file

@ -300,7 +300,7 @@ will use the defaults. When no configuration is used, the defaults are used.
# required imports # required imports
from core.api.grpc import client from core.api.grpc import client
from core.api.grpc.core_pb2 import NodeType, Position from core.api.grpc.core_pb2 import NodeType, Position
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
# interface helper # interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64") iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
@ -315,7 +315,7 @@ session = core.create_session()
# create nodes # create nodes
position = Position(x=200, y=200) position = Position(x=200, y=200)
emane = session.add_node( emane = session.add_node(
1, _type=NodeType.EMANE, position=position, emane=EmaneIeee80211abgModel.name 1, _type=NodeType.EMANE, position=position, emane=EmaneIeee80211abgModel.name
) )
position = Position(x=100, y=100) position = Position(x=100, y=100)
node1 = session.add_node(2, model="mdr", position=position) node1 = session.add_node(2, model="mdr", position=position)

View file

@ -278,7 +278,7 @@ will use the defaults. When no configuration is used, the defaults are used.
```python ```python
# required imports # required imports
from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.coreemu import CoreEmu from core.emulator.coreemu import CoreEmu
from core.emulator.data import IpPrefixes, NodeOptions from core.emulator.data import IpPrefixes, NodeOptions
@ -312,13 +312,13 @@ n2 = session.add_node(CoreNode, options=options)
# configure general emane settings # configure general emane settings
config = session.emane.get_configs() config = session.emane.get_configs()
config.update({ config.update({
"eventservicettl": "2" "eventservicettl": "2"
}) })
# configure emane model settings # configure emane model settings
# using a dict mapping currently support values as strings # using a dict mapping currently support values as strings
session.emane.set_model_config(emane.id, EmaneIeee80211abgModel.name, { session.emane.set_model_config(emane.id, EmaneIeee80211abgModel.name, {
"unicastrate": "3", "unicastrate": "3",
}) })
# link nodes to emane # link nodes to emane