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,
|
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]:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
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
|
: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)
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue