daemon: refactoring to load emane models one time during startup, updates to account for this change
This commit is contained in:
parent
1ddb7b7b24
commit
50e3aadc6b
32 changed files with 271 additions and 332 deletions
|
@ -31,7 +31,6 @@ from core.api.grpc.emane_pb2 import (
|
|||
GetEmaneConfigRequest,
|
||||
GetEmaneEventChannelRequest,
|
||||
GetEmaneModelConfigRequest,
|
||||
GetEmaneModelsRequest,
|
||||
SetEmaneConfigRequest,
|
||||
SetEmaneModelConfigRequest,
|
||||
)
|
||||
|
@ -943,18 +942,6 @@ class CoreGrpcClient:
|
|||
response = self.stub.SetEmaneConfig(request)
|
||||
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(
|
||||
self, session_id: int, node_id: int, model: str, iface_id: int = -1
|
||||
) -> Dict[str, wrappers.ConfigOption]:
|
||||
|
|
|
@ -532,14 +532,11 @@ def get_nem_id(
|
|||
|
||||
def get_emane_model_configs(session: Session) -> List[GetEmaneModelConfig]:
|
||||
configs = []
|
||||
for _id in session.emane.node_configurations:
|
||||
if _id == -1:
|
||||
continue
|
||||
model_configs = session.emane.node_configurations[_id]
|
||||
for _id, model_configs in session.emane.node_configs.items():
|
||||
for model_name in model_configs:
|
||||
model = session.emane.models[model_name]
|
||||
current_config = session.emane.get_model_config(_id, model_name)
|
||||
config = get_config_options(current_config, model)
|
||||
model_class = session.emane.get_model(model_name)
|
||||
current_config = session.emane.get_config(_id, model_name)
|
||||
config = get_config_options(current_config, model_class)
|
||||
node_id, iface_id = utils.parse_iface_config_id(_id)
|
||||
iface_id = iface_id if iface_id is not None else -1
|
||||
model_config = GetEmaneModelConfig(
|
||||
|
@ -591,15 +588,6 @@ def get_hooks(session: Session) -> List[core_pb2.Hook]:
|
|||
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]:
|
||||
default_services = []
|
||||
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]:
|
||||
current_config = session.emane.get_configs()
|
||||
return get_config_options(current_config, session.emane.emane_config)
|
||||
return get_config_options(session.emane.config, session.emane.emane_config)
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
hooks = get_hooks(session)
|
||||
emane_models = get_emane_models(session)
|
||||
emane_config = get_emane_config(session)
|
||||
emane_model_configs = get_emane_model_configs(session)
|
||||
wlan_configs = get_wlan_configs(session)
|
||||
|
@ -699,7 +685,6 @@ def convert_session(session: Session) -> wrappers.Session:
|
|||
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,
|
||||
|
|
|
@ -39,8 +39,6 @@ from core.api.grpc.emane_pb2 import (
|
|||
GetEmaneEventChannelResponse,
|
||||
GetEmaneModelConfigRequest,
|
||||
GetEmaneModelConfigResponse,
|
||||
GetEmaneModelsRequest,
|
||||
GetEmaneModelsResponse,
|
||||
SetEmaneConfigRequest,
|
||||
SetEmaneConfigResponse,
|
||||
SetEmaneModelConfigRequest,
|
||||
|
@ -79,6 +77,7 @@ from core.api.grpc.wlan_pb2 import (
|
|||
WlanLinkRequest,
|
||||
WlanLinkResponse,
|
||||
)
|
||||
from core.emane.modelmanager import EmaneModelManager
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
|
||||
from core.emulator.enumerations import (
|
||||
|
@ -211,8 +210,11 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
validation_period=service.validation_period,
|
||||
)
|
||||
config_services.append(service_proto)
|
||||
emane_models = [x.name for x in EmaneModelManager.models.values()]
|
||||
return core_pb2.GetConfigResponse(
|
||||
services=services, config_services=config_services
|
||||
services=services,
|
||||
config_services=config_services,
|
||||
emane_models=emane_models,
|
||||
)
|
||||
|
||||
def StartSession(
|
||||
|
@ -264,11 +266,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
return core_pb2.StartSessionResponse(result=False, exceptions=exceptions)
|
||||
|
||||
# emane configs
|
||||
config = session.emane.get_configs()
|
||||
config.update(request.emane_config)
|
||||
session.emane.config.update(request.emane_config)
|
||||
for config in request.emane_model_configs:
|
||||
_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
|
||||
for config in request.wlan_configs:
|
||||
|
@ -426,57 +427,6 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logger.debug("get session: %s", request)
|
||||
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)
|
||||
return core_pb2.GetSessionResponse(session=session_proto)
|
||||
|
||||
|
@ -1122,25 +1072,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logger.debug("set emane config: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
config = session.emane.get_configs()
|
||||
config.update(request.config)
|
||||
session.emane.config.update(request.config)
|
||||
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(
|
||||
self, request: GetEmaneModelConfigRequest, context: ServicerContext
|
||||
) -> GetEmaneModelConfigResponse:
|
||||
|
@ -1154,11 +1088,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logger.debug("get emane model config: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
model = session.emane.models.get(request.model)
|
||||
if not model:
|
||||
raise CoreError(f"invalid emane model: {request.model}")
|
||||
model = session.emane.get_model(request.model)
|
||||
_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)
|
||||
return GetEmaneModelConfigResponse(config=config)
|
||||
|
||||
|
@ -1177,7 +1109,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
session = self.get_session(request.session_id, context)
|
||||
model_config = request.emane_model_config
|
||||
_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)
|
||||
|
||||
def SaveXml(
|
||||
|
@ -1192,13 +1124,10 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
|
|||
"""
|
||||
logger.debug("save xml: %s", request)
|
||||
session = self.get_session(request.session_id, context)
|
||||
|
||||
_, temp_path = tempfile.mkstemp()
|
||||
session.save_xml(temp_path)
|
||||
|
||||
with open(temp_path, "r") as xml_file:
|
||||
data = xml_file.read()
|
||||
|
||||
return core_pb2.SaveXmlResponse(data=data)
|
||||
|
||||
def OpenXml(
|
||||
|
|
|
@ -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
|
||||
)
|
||||
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)
|
||||
metadata: Dict[str, str] = field(default_factory=dict)
|
||||
file: Path = None
|
||||
|
@ -837,7 +836,6 @@ class Session:
|
|||
default_services=default_services,
|
||||
location=SessionLocation.from_proto(proto.location),
|
||||
hooks=hooks,
|
||||
emane_models=list(proto.emane_models),
|
||||
emane_config=ConfigOption.from_dict(proto.emane_config),
|
||||
metadata=dict(proto.metadata),
|
||||
file=file_path,
|
||||
|
@ -906,12 +904,17 @@ class Session:
|
|||
class CoreConfig:
|
||||
services: List[Service] = field(default_factory=list)
|
||||
config_services: List[ConfigService] = field(default_factory=list)
|
||||
emane_models: List[str] = field(default_factory=list)
|
||||
|
||||
@classmethod
|
||||
def from_proto(cls, proto: core_pb2.GetConfigResponse) -> "CoreConfig":
|
||||
services = [Service.from_proto(x) for x in proto.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
|
||||
|
|
|
@ -29,6 +29,7 @@ from core.api.tlv.enumerations import (
|
|||
NodeTlvs,
|
||||
SessionTlvs,
|
||||
)
|
||||
from core.emane.modelmanager import EmaneModelManager
|
||||
from core.emulator.data import (
|
||||
ConfigData,
|
||||
EventData,
|
||||
|
@ -419,8 +420,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
tlv_data += coreapi.CoreRegisterTlv.pack(
|
||||
self.session.emane.config_type.value, self.session.emane.name
|
||||
)
|
||||
for model_name in self.session.emane.models:
|
||||
model_class = self.session.emane.models[model_name]
|
||||
for model_name, model_class in EmaneModelManager.models.items():
|
||||
tlv_data += coreapi.CoreRegisterTlv.pack(
|
||||
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)
|
||||
elif config_data.object == self.session.emane.name:
|
||||
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)
|
||||
else:
|
||||
raise Exception("no handler for configuration: %s", config_data.object)
|
||||
|
@ -1393,7 +1393,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
if message_type == ConfigFlags.REQUEST:
|
||||
logger.info("replying to configure request for %s model", object_name)
|
||||
typeflags = ConfigFlags.NONE.value
|
||||
config = self.session.emane.get_configs()
|
||||
config = self.session.emane.config
|
||||
config_response = ConfigShim.config_data(
|
||||
0, node_id, typeflags, self.session.emane.emane_config, config
|
||||
)
|
||||
|
@ -1405,7 +1405,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
|
||||
if values_str:
|
||||
config = ConfigShim.str_to_dict(values_str)
|
||||
self.session.emane.set_configs(config)
|
||||
self.session.emane.config = config
|
||||
|
||||
return replies
|
||||
|
||||
|
@ -1424,12 +1424,12 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
logger.info("replying to configure request for model: %s", object_name)
|
||||
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:
|
||||
logger.warning("model class does not exist: %s", object_name)
|
||||
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(
|
||||
0, node_id, typeflags, model_class, config
|
||||
)
|
||||
|
@ -1439,12 +1439,11 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
if not object_name:
|
||||
logger.warning("no configuration object for node: %s", node_id)
|
||||
return []
|
||||
|
||||
parsed_config = {}
|
||||
if values_str:
|
||||
parsed_config = ConfigShim.str_to_dict(values_str)
|
||||
|
||||
self.session.emane.set_model_config(node_id, object_name, parsed_config)
|
||||
self.session.emane.node_models[node_id] = object_name
|
||||
self.session.emane.set_config(node_id, object_name, parsed_config)
|
||||
|
||||
return replies
|
||||
|
||||
|
@ -1853,7 +1852,7 @@ class CoreHandler(socketserver.BaseRequestHandler):
|
|||
self.session.broadcast_config(config_data)
|
||||
|
||||
# send global emane config
|
||||
config = self.session.emane.get_configs()
|
||||
config = self.session.emane.config
|
||||
logger.debug("global emane config: values(%s)", config)
|
||||
config_data = ConfigShim.config_data(
|
||||
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)
|
||||
|
||||
# send emane model configs
|
||||
for node_id in self.session.emane.nodes():
|
||||
emane_configs = self.session.emane.get_all_configs(node_id)
|
||||
for model_name in emane_configs:
|
||||
config = emane_configs[model_name]
|
||||
model_class = self.session.emane.models[model_name]
|
||||
for node_id, model_configs in self.session.emane.node_configs.items():
|
||||
for model_name, config in model_configs.items():
|
||||
model_class = self.session.emane.get_model(model_name)
|
||||
logger.debug(
|
||||
"emane config: node(%s) class(%s) values(%s)",
|
||||
node_id,
|
||||
|
|
|
@ -31,7 +31,7 @@ class ConfigServiceManager:
|
|||
"""
|
||||
service_class = self.services.get(name)
|
||||
if service_class is None:
|
||||
raise CoreError(f"service does not exit {name}")
|
||||
raise CoreError(f"service does not exist {name}")
|
||||
return service_class
|
||||
|
||||
def add(self, service: Type[ConfigService]) -> None:
|
||||
|
|
|
@ -12,16 +12,12 @@ from pathlib import Path
|
|||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type
|
||||
|
||||
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.bypass import EmaneBypassModel
|
||||
from core.emane.commeffect import EmaneCommEffectModel
|
||||
from core.emane.emanemodel import EmaneModel
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.linkmonitor import EmaneLinkMonitor
|
||||
from core.emane.modelmanager import EmaneModelManager
|
||||
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.enumerations import (
|
||||
ConfigDataTypes,
|
||||
|
@ -55,15 +51,9 @@ except ImportError:
|
|||
EventServiceException = None
|
||||
logger.debug("compatible emane python bindings not installed")
|
||||
|
||||
EMANE_MODELS = [
|
||||
EmaneRfPipeModel,
|
||||
EmaneIeee80211abgModel,
|
||||
EmaneCommEffectModel,
|
||||
EmaneBypassModel,
|
||||
EmaneTdmaModel,
|
||||
]
|
||||
DEFAULT_EMANE_PREFIX = "/usr"
|
||||
DEFAULT_DEV = "ctrl0"
|
||||
DEFAULT_LOG_LEVEL: int = 3
|
||||
|
||||
|
||||
class EmaneState(Enum):
|
||||
|
@ -78,7 +68,7 @@ class StartData:
|
|||
ifaces: List[CoreInterface] = field(default_factory=list)
|
||||
|
||||
|
||||
class EmaneManager(ModelManager):
|
||||
class EmaneManager:
|
||||
"""
|
||||
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
|
||||
|
@ -87,9 +77,6 @@ class EmaneManager(ModelManager):
|
|||
|
||||
name: str = "emane"
|
||||
config_type: RegisterTlvs = RegisterTlvs.EMULATION_SERVER
|
||||
NOT_READY: int = 2
|
||||
EVENTCFGVAR: str = "LIBEMANEEVENTSERVICECONFIG"
|
||||
DEFAULT_LOG_LEVEL: int = 3
|
||||
|
||||
def __init__(self, session: "Session") -> None:
|
||||
"""
|
||||
|
@ -116,7 +103,9 @@ class EmaneManager(ModelManager):
|
|||
|
||||
# model for global EMANE configuration options
|
||||
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
|
||||
self.link_monitor: EmaneLinkMonitor = EmaneLinkMonitor(self)
|
||||
|
@ -124,14 +113,63 @@ class EmaneManager(ModelManager):
|
|||
self.service: Optional[EventService] = None
|
||||
self.eventchannel: Optional[Tuple[str, int, str]] = None
|
||||
self.event_device: Optional[str] = None
|
||||
self.emane_check()
|
||||
|
||||
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:
|
||||
nem_id += 1
|
||||
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(
|
||||
self, emane_net: EmaneNet, iface: CoreInterface
|
||||
) -> Dict[str, str]:
|
||||
|
@ -149,46 +187,28 @@ class EmaneManager(ModelManager):
|
|||
# try to retrieve interface specific configuration
|
||||
if iface.node_id is not None:
|
||||
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
|
||||
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
|
||||
if not config:
|
||||
# with EMANE 0.9.2+, we need an extra NEM XML from
|
||||
# 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
|
||||
if not config:
|
||||
config = emane_net.model.default_values()
|
||||
return config
|
||||
|
||||
def config_reset(self, node_id: int = None) -> None:
|
||||
super().config_reset(node_id)
|
||||
self.set_configs(self.emane_config.default_values())
|
||||
|
||||
def emane_check(self) -> None:
|
||||
"""
|
||||
Check if emane is installed and load models.
|
||||
|
||||
: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)
|
||||
if node_id is None:
|
||||
self.config = self.emane_config.default_values()
|
||||
self.node_configs.clear()
|
||||
self.node_models.clear()
|
||||
else:
|
||||
self.node_configs.get(node_id, {}).clear()
|
||||
del self.node_models[node_id]
|
||||
|
||||
def deleteeventservice(self) -> None:
|
||||
if self.service:
|
||||
|
@ -207,13 +227,12 @@ class EmaneManager(ModelManager):
|
|||
The multicast group and/or port may be configured.
|
||||
"""
|
||||
self.deleteeventservice()
|
||||
|
||||
if shutdown:
|
||||
return
|
||||
|
||||
# Get the control network to be used for events
|
||||
group, port = self.get_config("eventservicegroup").split(":")
|
||||
self.event_device = self.get_config("eventservicedevice")
|
||||
group, port = self.config["eventservicegroup"].split(":")
|
||||
self.event_device = self.config["eventservicedevice"]
|
||||
eventnetidx = self.session.get_control_net_index(self.event_device)
|
||||
if eventnetidx < 0:
|
||||
logger.error(
|
||||
|
@ -238,19 +257,6 @@ class EmaneManager(ModelManager):
|
|||
except EventServiceException:
|
||||
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:
|
||||
"""
|
||||
Add EMANE network object to this manager.
|
||||
|
@ -302,7 +308,7 @@ class EmaneManager(ModelManager):
|
|||
|
||||
# control network bridge required for EMANE 0.9.2
|
||||
# - 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)
|
||||
logger.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev)
|
||||
if netidx < 0:
|
||||
|
@ -315,7 +321,7 @@ class EmaneManager(ModelManager):
|
|||
self.session.add_remove_control_net(
|
||||
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)
|
||||
if eventdev != otadev:
|
||||
netidx = self.session.get_control_net_index(eventdev)
|
||||
|
@ -408,7 +414,7 @@ class EmaneManager(ModelManager):
|
|||
logger.exception("error writing to emane nem file")
|
||||
|
||||
def links_enabled(self) -> bool:
|
||||
return self.get_config("link_enabled") == "1"
|
||||
return self.config["link_enabled"] == "1"
|
||||
|
||||
def poststartup(self) -> None:
|
||||
"""
|
||||
|
@ -470,14 +476,12 @@ class EmaneManager(ModelManager):
|
|||
for node_id in self._emane_nets:
|
||||
emane_net = self._emane_nets[node_id]
|
||||
logger.debug("checking emane model for node: %s", node_id)
|
||||
|
||||
# skip nodes that already have a model set
|
||||
if emane_net.model:
|
||||
logger.debug(
|
||||
"node(%s) already has model(%s)", emane_net.id, emane_net.model.name
|
||||
)
|
||||
continue
|
||||
|
||||
# set model configured for node, due to legacy messaging configuration
|
||||
# before nodes exist
|
||||
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)
|
||||
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)
|
||||
model_class = self.models[model_name]
|
||||
model_class = self.get_model(model_name)
|
||||
emane_net.setmodel(model_class, config)
|
||||
|
||||
def get_nem_link(
|
||||
|
@ -525,22 +529,19 @@ class EmaneManager(ModelManager):
|
|||
default_values = self.emane_config.default_values()
|
||||
for name in ["eventservicegroup", "eventservicedevice"]:
|
||||
a = default_values[name]
|
||||
b = self.get_config(name)
|
||||
b = self.config[name]
|
||||
if a != b:
|
||||
need_xml = True
|
||||
|
||||
if not need_xml:
|
||||
# reset to using default config
|
||||
self.initeventservice()
|
||||
return
|
||||
|
||||
try:
|
||||
group, port = self.get_config("eventservicegroup").split(":")
|
||||
group, port = self.config["eventservicegroup"].split(":")
|
||||
except ValueError:
|
||||
logger.exception("invalid eventservicegroup in EMANE config")
|
||||
return
|
||||
|
||||
dev = self.get_config("eventservicedevice")
|
||||
dev = self.config["eventservicedevice"]
|
||||
emanexml.create_event_service_xml(group, port, dev, self.session.directory)
|
||||
self.session.distributed.execute(
|
||||
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.
|
||||
"""
|
||||
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")
|
||||
realtime = self.session.options.get_config_bool("emane_realtime", default=True)
|
||||
if cfgloglevel:
|
||||
|
@ -564,11 +565,11 @@ class EmaneManager(ModelManager):
|
|||
if realtime:
|
||||
emanecmd += " -r"
|
||||
if isinstance(node, CoreNode):
|
||||
otagroup, _otaport = self.get_config("otamanagergroup").split(":")
|
||||
otadev = self.get_config("otamanagerdevice")
|
||||
otagroup, _otaport = self.config["otamanagergroup"].split(":")
|
||||
otadev = self.config["otamanagerdevice"]
|
||||
otanetidx = self.session.get_control_net_index(otadev)
|
||||
eventgroup, _eventport = self.get_config("eventservicegroup").split(":")
|
||||
eventdev = self.get_config("eventservicedevice")
|
||||
eventgroup, _eventport = self.config["eventservicegroup"].split(":")
|
||||
eventdev = self.config["eventservicedevice"]
|
||||
eventservicenetidx = self.session.get_control_net_index(eventdev)
|
||||
|
||||
# control network not yet started here
|
||||
|
|
|
@ -189,9 +189,9 @@ class EmaneLinkMonitor:
|
|||
self.running: bool = False
|
||||
|
||||
def start(self) -> None:
|
||||
self.loss_threshold = int(self.emane_manager.get_config("loss_threshold"))
|
||||
self.link_interval = int(self.emane_manager.get_config("link_interval"))
|
||||
self.link_timeout = int(self.emane_manager.get_config("link_timeout"))
|
||||
self.loss_threshold = int(self.emane_manager.config["loss_threshold"])
|
||||
self.link_interval = int(self.emane_manager.config["link_interval"])
|
||||
self.link_timeout = int(self.emane_manager.config["link_timeout"])
|
||||
self.initialize()
|
||||
if not self.clients:
|
||||
logger.info("no valid emane models to monitor links")
|
||||
|
|
41
daemon/core/emane/modelmanager.py
Normal file
41
daemon/core/emane/modelmanager.py
Normal 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
|
0
daemon/core/emane/models/__init__.py
Normal file
0
daemon/core/emane/models/__init__.py
Normal file
|
@ -51,17 +51,16 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
|
|||
:return: nothing
|
||||
"""
|
||||
# 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:
|
||||
return
|
||||
schedule = config[self.schedule_name]
|
||||
|
||||
# get the set event device
|
||||
event_device = self.session.emane.event_device
|
||||
|
||||
schedule = Path(config[self.schedule_name])
|
||||
if not schedule.is_file():
|
||||
logger.warning("ignoring invalid tdma schedule: %s", schedule)
|
||||
return
|
||||
# initiate tdma schedule
|
||||
event_device = self.session.emane.event_device
|
||||
logger.info(
|
||||
"setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device
|
||||
)
|
||||
args = f"emaneevent-tdmaschedule -i {event_device} {schedule}"
|
||||
utils.cmd(args)
|
||||
utils.cmd(f"emaneevent-tdmaschedule -i {event_device} {schedule}")
|
|
@ -9,12 +9,16 @@ from typing import Dict, List, Type
|
|||
import core.services
|
||||
from core import configservices, 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
|
||||
from core.services.coreservices import ServiceManager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_EMANE_PREFIX: str = "/usr"
|
||||
|
||||
|
||||
def signal_handler(signal_number: int, _) -> None:
|
||||
"""
|
||||
|
@ -61,6 +65,10 @@ class CoreEmu:
|
|||
self.service_manager: ConfigServiceManager = ConfigServiceManager()
|
||||
self._load_services()
|
||||
|
||||
# check and load emane
|
||||
self.has_emane: bool = False
|
||||
self._load_emane()
|
||||
|
||||
# check executables exist on path
|
||||
self._validate_env()
|
||||
|
||||
|
@ -103,6 +111,32 @@ class CoreEmu:
|
|||
custom_dir = Path(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:
|
||||
"""
|
||||
Shutdown all CORE session.
|
||||
|
|
|
@ -560,12 +560,8 @@ class Session:
|
|||
|
||||
# ensure default emane configuration
|
||||
if isinstance(node, EmaneNet) and options.emane:
|
||||
model = self.emane.models.get(options.emane)
|
||||
if not model:
|
||||
raise CoreError(
|
||||
f"node({node.name}) emane model({options.emane}) does not exist"
|
||||
)
|
||||
node.model = model(self, node.id)
|
||||
model_class = self.emane.get_model(options.emane)
|
||||
node.model = model_class(self, node.id)
|
||||
if self.state == EventTypes.RUNTIME_STATE:
|
||||
self.emane.add_node(node)
|
||||
# set default wlan config if needed
|
||||
|
|
|
@ -77,6 +77,7 @@ class CoreClient:
|
|||
self.config_services: Dict[str, ConfigService] = {}
|
||||
|
||||
# loaded configuration data
|
||||
self.emane_models: List[str] = []
|
||||
self.servers: Dict[str, CoreServer] = {}
|
||||
self.custom_nodes: Dict[str, NodeDraw] = {}
|
||||
self.custom_observers: Dict[str, Observer] = {}
|
||||
|
@ -392,6 +393,7 @@ class CoreClient:
|
|||
self.client.connect()
|
||||
# get current core configurations services/config services
|
||||
core_config = self.client.get_config()
|
||||
self.emane_models = core_config.emane_models
|
||||
for service in core_config.services:
|
||||
group_services = self.services.setdefault(service.group, set())
|
||||
group_services.add(service.name)
|
||||
|
@ -639,11 +641,11 @@ class CoreClient:
|
|||
image = "ubuntu:latest"
|
||||
emane = None
|
||||
if node_type == NodeType.EMANE:
|
||||
if not self.session.emane_models:
|
||||
if not self.emane_models:
|
||||
dialog = EmaneInstallDialog(self.app)
|
||||
dialog.show()
|
||||
return
|
||||
emane = self.session.emane_models[0]
|
||||
emane = self.emane_models[0]
|
||||
name = f"emane{node_id}"
|
||||
elif node_type == NodeType.WIRELESS_LAN:
|
||||
name = f"wlan{node_id}"
|
||||
|
|
|
@ -115,7 +115,7 @@ class EmaneConfigDialog(Dialog):
|
|||
self.radiovar: tk.IntVar = tk.IntVar()
|
||||
self.radiovar.set(1)
|
||||
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]
|
||||
self.emane_model: tk.StringVar = tk.StringVar(value=model)
|
||||
|
|
|
@ -82,7 +82,7 @@ def create_iface_data(iface_element: etree.Element) -> InterfaceData:
|
|||
|
||||
def create_emane_config(session: "Session") -> etree.Element:
|
||||
emane_configuration = etree.Element("emane_global_configuration")
|
||||
config = session.emane.get_configs()
|
||||
config = session.emane.config
|
||||
emulator_element = etree.SubElement(emane_configuration, "emulator")
|
||||
for emulator_config in session.emane.emane_config.emulator_config:
|
||||
value = config[emulator_config.id]
|
||||
|
@ -379,19 +379,15 @@ class CoreXmlWriter:
|
|||
emane_global_configuration = create_emane_config(self.session)
|
||||
self.scenario.append(emane_global_configuration)
|
||||
emane_configurations = etree.Element("emane_configurations")
|
||||
for node_id in self.session.emane.nodes():
|
||||
all_configs = self.session.emane.get_all_configs(node_id)
|
||||
if not all_configs:
|
||||
continue
|
||||
for node_id, model_configs in self.session.emane.node_configs.items():
|
||||
node_id, iface_id = utils.parse_iface_config_id(node_id)
|
||||
for model_name in all_configs:
|
||||
config = all_configs[model_name]
|
||||
for model_name, config in model_configs.items():
|
||||
logger.debug(
|
||||
"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(
|
||||
node_id, model, config, iface_id
|
||||
node_id, model_class, config, iface_id
|
||||
)
|
||||
emane_configurations.append(emane_configuration)
|
||||
if emane_configurations.getchildren():
|
||||
|
@ -748,7 +744,7 @@ class CoreXmlReader:
|
|||
name = config.get("name")
|
||||
value = config.get("value")
|
||||
configs[name] = value
|
||||
self.session.emane.set_configs(config=configs)
|
||||
self.session.emane.config = configs
|
||||
|
||||
def read_emane_configs(self) -> None:
|
||||
emane_configurations = self.scenario.find("emane_configurations")
|
||||
|
@ -765,9 +761,7 @@ class CoreXmlReader:
|
|||
node = self.session.nodes.get(node_id)
|
||||
if not node:
|
||||
raise CoreXmlError(f"node for emane config doesn't exist: {node_id}")
|
||||
model = self.session.emane.models.get(model_name)
|
||||
if not model:
|
||||
raise CoreXmlError(f"invalid emane model: {model_name}")
|
||||
self.session.emane.get_model(model_name)
|
||||
if iface_id is not None and iface_id not in node.ifaces:
|
||||
raise CoreXmlError(
|
||||
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
|
||||
)
|
||||
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:
|
||||
mobility_configurations = self.scenario.find("mobility_configurations")
|
||||
|
|
|
@ -166,7 +166,7 @@ def build_platform_xml(
|
|||
if not isinstance(data.node, CoreNode) and name in transport_configs:
|
||||
value = control_net.brname
|
||||
else:
|
||||
value = emane_manager.get_config(name)
|
||||
value = emane_manager.config[name]
|
||||
add_param(platform_element, name, value)
|
||||
|
||||
# create nem xml entries for all interfaces
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# required imports
|
||||
from core.api.grpc import client
|
||||
from core.api.grpc.wrappers import NodeType, Position
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
|
||||
# interface helper
|
||||
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
|
||||
|
|
|
@ -6,7 +6,7 @@ with the GUI.
|
|||
import argparse
|
||||
import logging
|
||||
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# required imports
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
|
|
|
@ -123,8 +123,6 @@ service CoreApi {
|
|||
}
|
||||
|
||||
// globals
|
||||
rpc GetEmaneModels (emane.GetEmaneModelsRequest) returns (emane.GetEmaneModelsResponse) {
|
||||
}
|
||||
rpc GetConfig (GetConfigRequest) returns (GetConfigResponse) {
|
||||
}
|
||||
}
|
||||
|
@ -584,17 +582,16 @@ message Session {
|
|||
repeated services.ServiceDefaults default_services = 7;
|
||||
SessionLocation location = 8;
|
||||
repeated Hook hooks = 9;
|
||||
repeated string emane_models = 10;
|
||||
map<string, common.ConfigOption> emane_config = 11;
|
||||
repeated emane.GetEmaneModelConfig emane_model_configs = 12;
|
||||
map<int32, common.MappedConfig> wlan_configs = 13;
|
||||
repeated services.NodeServiceConfig service_configs = 14;
|
||||
repeated configservices.ConfigServiceConfig config_service_configs = 15;
|
||||
map<int32, common.MappedConfig> mobility_configs = 16;
|
||||
map<string, string> metadata = 17;
|
||||
string file = 18;
|
||||
map<string, common.ConfigOption> options = 19;
|
||||
repeated Server servers = 20;
|
||||
map<string, common.ConfigOption> emane_config = 10;
|
||||
repeated emane.GetEmaneModelConfig emane_model_configs = 11;
|
||||
map<int32, common.MappedConfig> wlan_configs = 12;
|
||||
repeated services.NodeServiceConfig service_configs = 13;
|
||||
repeated configservices.ConfigServiceConfig config_service_configs = 14;
|
||||
map<int32, common.MappedConfig> mobility_configs = 15;
|
||||
map<string, string> metadata = 16;
|
||||
string file = 17;
|
||||
map<string, common.ConfigOption> options = 18;
|
||||
repeated Server servers = 19;
|
||||
}
|
||||
|
||||
message SessionSummary {
|
||||
|
|
|
@ -21,14 +21,6 @@ message SetEmaneConfigResponse {
|
|||
bool result = 1;
|
||||
}
|
||||
|
||||
message GetEmaneModelsRequest {
|
||||
int32 session_id = 1;
|
||||
}
|
||||
|
||||
message GetEmaneModelsResponse {
|
||||
repeated string models = 1;
|
||||
}
|
||||
|
||||
message GetEmaneModelConfigRequest {
|
||||
int32 session_id = 1;
|
||||
int32 node_id = 2;
|
||||
|
|
|
@ -9,13 +9,13 @@ from xml.etree import ElementTree
|
|||
import pytest
|
||||
|
||||
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.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.rfpipe import EmaneRfPipeModel
|
||||
from core.emane.tdma import EmaneTdmaModel
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
from core.emulator.session import Session
|
||||
from core.errors import CoreCommandError, CoreError
|
||||
|
@ -100,14 +100,13 @@ class TestEmane:
|
|||
|
||||
# create emane node for networking the core nodes
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options = NodeOptions(emane=model.name)
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
session.emane.set_model(emane_network, model)
|
||||
|
||||
# configure tdma
|
||||
if model == EmaneTdmaModel:
|
||||
session.emane.set_model_config(
|
||||
session.emane.set_config(
|
||||
emane_network.id, EmaneTdmaModel.name, {"schedule": str(_SCHEDULE)}
|
||||
)
|
||||
|
||||
|
@ -142,13 +141,13 @@ class TestEmane:
|
|||
"""
|
||||
# create emane node for networking the core nodes
|
||||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions()
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
options.set_position(80, 50)
|
||||
emane_network = session.add_node(EmaneNet, options=options)
|
||||
config_key = "txpower"
|
||||
config_value = "10"
|
||||
session.emane.set_model(
|
||||
emane_network, EmaneIeee80211abgModel, {config_key: config_value}
|
||||
session.emane.set_config(
|
||||
emane_network.id, EmaneIeee80211abgModel.name, {config_key: config_value}
|
||||
)
|
||||
|
||||
# create nodes
|
||||
|
@ -174,7 +173,7 @@ class TestEmane:
|
|||
# save xml
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
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
|
||||
assert xml_file.isfile()
|
||||
|
@ -190,12 +189,11 @@ class TestEmane:
|
|||
assert not session.get_node(node2_id, CoreNode)
|
||||
|
||||
# load saved xml
|
||||
session.open_xml(file_path, start=True)
|
||||
session.open_xml(Path(file_path), start=True)
|
||||
|
||||
# retrieve configuration we set originally
|
||||
value = str(
|
||||
session.emane.get_config(config_key, emane_id, EmaneIeee80211abgModel.name)
|
||||
)
|
||||
config = session.emane.get_config(emane_id, EmaneIeee80211abgModel.name)
|
||||
value = config[config_key]
|
||||
|
||||
# verify nodes and configuration were restored
|
||||
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(node2.id, emane_node.id, iface2_data)
|
||||
|
||||
# set node specific conifg
|
||||
# set node specific config
|
||||
datarate = "101"
|
||||
session.emane.set_model_config(
|
||||
session.emane.set_config(
|
||||
node1.id, EmaneRfPipeModel.name, {"datarate": datarate}
|
||||
)
|
||||
|
||||
|
@ -233,7 +231,7 @@ class TestEmane:
|
|||
# save xml
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
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
|
||||
assert xml_file.isfile()
|
||||
|
@ -251,7 +249,7 @@ class TestEmane:
|
|||
assert not session.get_node(emane_node.id, EmaneNet)
|
||||
|
||||
# load saved xml
|
||||
session.open_xml(file_path, start=True)
|
||||
session.open_xml(Path(file_path), start=True)
|
||||
|
||||
# verify nodes have been recreated
|
||||
assert session.get_node(node1.id, CoreNode)
|
||||
|
@ -262,7 +260,7 @@ class TestEmane:
|
|||
node = session.nodes[node_id]
|
||||
links += node.links()
|
||||
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
|
||||
|
||||
def test_xml_emane_interface_config(
|
||||
|
@ -286,7 +284,7 @@ class TestEmane:
|
|||
# set node specific conifg
|
||||
datarate = "101"
|
||||
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}
|
||||
)
|
||||
|
||||
|
@ -296,7 +294,7 @@ class TestEmane:
|
|||
# save xml
|
||||
xml_file = tmpdir.join("session.xml")
|
||||
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
|
||||
assert xml_file.isfile()
|
||||
|
@ -314,7 +312,7 @@ class TestEmane:
|
|||
assert not session.get_node(emane_node.id, EmaneNet)
|
||||
|
||||
# load saved xml
|
||||
session.open_xml(file_path, start=True)
|
||||
session.open_xml(Path(file_path), start=True)
|
||||
|
||||
# verify nodes have been recreated
|
||||
assert session.get_node(node1.id, CoreNode)
|
||||
|
@ -325,5 +323,5 @@ class TestEmane:
|
|||
node = session.nodes[node_id]
|
||||
links += node.links()
|
||||
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
|
||||
|
|
|
@ -6,7 +6,7 @@ from core.config import (
|
|||
Configuration,
|
||||
ModelManager,
|
||||
)
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emulator.enumerations import ConfigDataTypes
|
||||
from core.emulator.session import Session
|
||||
from core.location.mobility import BasicRangeModel
|
||||
|
|
|
@ -33,7 +33,7 @@ from core.api.grpc.wrappers import (
|
|||
)
|
||||
from core.api.tlv.dataconversion import ConfigShim
|
||||
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.emulator.data import EventData, IpPrefixes, NodeData, NodeOptions
|
||||
from core.emulator.enumerations import EventTypes, ExceptionLevels
|
||||
|
@ -151,7 +151,7 @@ class TestGrpc:
|
|||
location_alt,
|
||||
)
|
||||
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(
|
||||
wlan_node.id, BasicRangeModel.name
|
||||
)
|
||||
|
@ -543,7 +543,7 @@ class TestGrpc:
|
|||
|
||||
# then
|
||||
assert result is True
|
||||
config = session.emane.get_configs()
|
||||
config = session.emane.config
|
||||
assert len(config) > 1
|
||||
assert config[config_key] == config_value
|
||||
|
||||
|
@ -554,7 +554,7 @@ class TestGrpc:
|
|||
session.set_location(47.57917, -122.13232, 2.00000, 1.0)
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
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_value = "900000"
|
||||
option = ConfigOption(
|
||||
|
@ -574,9 +574,7 @@ class TestGrpc:
|
|||
|
||||
# then
|
||||
assert result is True
|
||||
config = session.emane.get_model_config(
|
||||
emane_network.id, EmaneIeee80211abgModel.name
|
||||
)
|
||||
config = session.emane.get_config(emane_network.id, EmaneIeee80211abgModel.name)
|
||||
assert config[config_key] == config_value
|
||||
|
||||
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)
|
||||
options = NodeOptions(emane=EmaneIeee80211abgModel.name)
|
||||
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
|
||||
with client.context_connect():
|
||||
|
@ -597,18 +595,6 @@ class TestGrpc:
|
|||
# then
|
||||
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):
|
||||
# given
|
||||
client = CoreGrpcClient()
|
||||
|
|
|
@ -22,7 +22,7 @@ from core.api.tlv.enumerations import (
|
|||
NodeTlvs,
|
||||
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.errors import CoreError
|
||||
from core.location.mobility import BasicRangeModel
|
||||
|
@ -939,9 +939,7 @@ class TestGui:
|
|||
|
||||
coretlv.handle_message(message)
|
||||
|
||||
config = coretlv.session.emane.get_model_config(
|
||||
wlan.id, EmaneIeee80211abgModel.name
|
||||
)
|
||||
config = coretlv.session.emane.get_config(wlan.id, EmaneIeee80211abgModel.name)
|
||||
assert config[config_key] == config_value
|
||||
|
||||
def test_config_emane_request(self, coretlv: CoreHandler):
|
||||
|
@ -973,5 +971,5 @@ class TestGui:
|
|||
|
||||
coretlv.handle_message(message)
|
||||
|
||||
config = coretlv.session.emane.get_configs()
|
||||
config = coretlv.session.emane.config
|
||||
assert config[config_key] == config_value
|
||||
|
|
|
@ -300,7 +300,7 @@ will use the defaults. When no configuration is used, the defaults are used.
|
|||
# required imports
|
||||
from core.api.grpc import client
|
||||
from core.api.grpc.core_pb2 import NodeType, Position
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
|
||||
# interface helper
|
||||
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
|
||||
|
|
|
@ -278,7 +278,7 @@ will use the defaults. When no configuration is used, the defaults are used.
|
|||
|
||||
```python
|
||||
# required imports
|
||||
from core.emane.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.models.ieee80211abg import EmaneIeee80211abgModel
|
||||
from core.emane.nodes import EmaneNet
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.data import IpPrefixes, NodeOptions
|
||||
|
|
Loading…
Reference in a new issue