grpc: update GetSession to return all session related information, rather than needing 8 different calls, pygui: updated session protobuf wrapper to handle all new data

This commit is contained in:
Blake Harnden 2020-07-27 18:19:51 -07:00
parent 160498336c
commit 3bdd6292cd
8 changed files with 260 additions and 115 deletions

View file

@ -8,13 +8,22 @@ from grpc import ServicerContext
from core import utils from core import utils
from core.api.grpc import common_pb2, core_pb2 from core.api.grpc import common_pb2, core_pb2
from core.api.grpc.services_pb2 import NodeServiceData, ServiceConfig from core.api.grpc.common_pb2 import MappedConfig
from core.api.grpc.configservices_pb2 import ConfigServiceConfig
from core.api.grpc.emane_pb2 import EmaneModelConfig
from core.api.grpc.services_pb2 import (
NodeServiceConfig,
NodeServiceData,
ServiceConfig,
ServiceDefaults,
)
from core.config import ConfigurableOptions from core.config import ConfigurableOptions
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions from core.emulator.data import InterfaceData, LinkData, LinkOptions, NodeOptions
from core.emulator.enumerations import LinkTypes, NodeTypes from core.emulator.enumerations import LinkTypes, NodeTypes
from core.emulator.session import Session from core.emulator.session import Session
from core.nodes.base import CoreNode, NodeBase from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase
from core.nodes.interface import CoreInterface from core.nodes.interface import CoreInterface
from core.services.coreservices import CoreService from core.services.coreservices import CoreService
@ -536,3 +545,119 @@ def get_nem_id(
message = f"{node.name} interface {iface_id} nem id does not exist" message = f"{node.name} interface {iface_id} nem id does not exist"
context.abort(grpc.StatusCode.INVALID_ARGUMENT, message) context.abort(grpc.StatusCode.INVALID_ARGUMENT, message)
return nem_id return nem_id
def get_emane_model_configs(session: Session) -> List[EmaneModelConfig]:
configs = []
for _id in session.emane.node_configurations:
if _id == -1:
continue
model_configs = session.emane.node_configurations[_id]
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)
node_id, iface_id = parse_emane_model_id(_id)
model_config = EmaneModelConfig(
node_id=node_id, model=model_name, iface_id=iface_id, config=config
)
configs.append(model_config)
return configs
def get_wlan_configs(session: Session) -> Dict[int, MappedConfig]:
configs = {}
for node_id in session.mobility.node_configurations:
model_config = session.mobility.node_configurations[node_id]
if node_id == -1:
continue
for model_name in model_config:
if model_name != BasicRangeModel.name:
continue
current_config = session.mobility.get_model_config(node_id, model_name)
config = get_config_options(current_config, BasicRangeModel)
mapped_config = MappedConfig(config=config)
configs[node_id] = mapped_config
return configs
def get_mobility_configs(session: Session) -> Dict[int, MappedConfig]:
configs = {}
for node_id in session.mobility.node_configurations:
model_config = session.mobility.node_configurations[node_id]
if node_id == -1:
continue
for model_name in model_config:
if model_name != Ns2ScriptedMobility.name:
continue
current_config = session.mobility.get_model_config(node_id, model_name)
config = get_config_options(current_config, Ns2ScriptedMobility)
mapped_config = MappedConfig(config=config)
configs[node_id] = mapped_config
return configs
def get_hooks(session: Session) -> List[core_pb2.Hook]:
hooks = []
for state in session.hooks:
state_hooks = session.hooks[state]
for file_name, file_data in state_hooks:
hook = core_pb2.Hook(state=state.value, file=file_name, data=file_data)
hooks.append(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():
default_service = ServiceDefaults(node_type=name, services=services)
default_services.append(default_service)
return default_services
def get_node_service_configs(session: Session) -> List[NodeServiceConfig]:
configs = []
for node_id, service_configs in session.services.custom_services.items():
for name in service_configs:
service = session.services.get_service(node_id, name)
service_proto = get_service_configuration(service)
config = NodeServiceConfig(
node_id=node_id,
service=name,
data=service_proto,
files=service.config_data,
)
configs.append(config)
return configs
def get_node_config_service_configs(session: Session) -> List[ConfigServiceConfig]:
configs = []
for node in session.nodes.values():
if not isinstance(node, CoreNodeBase):
continue
for name, service in node.config_services.items():
if not service.custom_templates and not service.custom_config:
continue
config_proto = ConfigServiceConfig(
node_id=node.id,
name=name,
templates=service.custom_templates,
config=service.custom_config,
)
configs.append(config_proto)
return configs
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)

View file

@ -19,7 +19,6 @@ from core.api.grpc import (
core_pb2_grpc, core_pb2_grpc,
grpcutils, grpcutils,
) )
from core.api.grpc.common_pb2 import MappedConfig
from core.api.grpc.configservices_pb2 import ( from core.api.grpc.configservices_pb2 import (
ConfigService, ConfigService,
GetConfigServiceDefaultsRequest, GetConfigServiceDefaultsRequest,
@ -89,7 +88,6 @@ from core.api.grpc.services_pb2 import (
ServiceAction, ServiceAction,
ServiceActionRequest, ServiceActionRequest,
ServiceActionResponse, ServiceActionResponse,
ServiceDefaults,
SetNodeServiceFileRequest, SetNodeServiceFileRequest,
SetNodeServiceFileResponse, SetNodeServiceFileResponse,
SetNodeServiceRequest, SetNodeServiceRequest,
@ -118,7 +116,7 @@ from core.emulator.enumerations import (
from core.emulator.session import NT, Session from core.emulator.session import NT, Session
from core.errors import CoreCommandError, CoreError from core.errors import CoreCommandError, CoreError
from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility
from core.nodes.base import CoreNode, CoreNodeBase, NodeBase from core.nodes.base import CoreNode, NodeBase
from core.nodes.network import PtpNet, WlanNode from core.nodes.network import PtpNet, WlanNode
from core.services.coreservices import ServiceManager from core.services.coreservices import ServiceManager
@ -558,7 +556,6 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get session: %s", request) logging.debug("get session: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
links = [] links = []
nodes = [] nodes = []
for _id in session.nodes: for _id in session.nodes:
@ -568,9 +565,37 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
nodes.append(node_proto) nodes.append(node_proto)
node_links = get_links(node) node_links = get_links(node)
links.extend(node_links) 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_proto = core_pb2.Session( session_proto = core_pb2.Session(
state=session.state.value, nodes=nodes, links=links, dir=session.session_dir state=session.state.value,
nodes=nodes,
links=links,
dir=session.session_dir,
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,
) )
return core_pb2.GetSessionResponse(session=session_proto) return core_pb2.GetSessionResponse(session=session_proto)
@ -1012,12 +1037,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get hooks: %s", request) logging.debug("get hooks: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
hooks = [] hooks = grpcutils.get_hooks(session)
for state in session.hooks:
state_hooks = session.hooks[state]
for file_name, file_data in state_hooks:
hook = core_pb2.Hook(state=state.value, file=file_name, data=file_data)
hooks.append(hook)
return core_pb2.GetHooksResponse(hooks=hooks) return core_pb2.GetHooksResponse(hooks=hooks)
def AddHook( def AddHook(
@ -1050,19 +1070,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get mobility configs: %s", request) logging.debug("get mobility configs: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
response = GetMobilityConfigsResponse() configs = grpcutils.get_mobility_configs(session)
for node_id in session.mobility.node_configurations: return GetMobilityConfigsResponse(configs=configs)
model_config = session.mobility.node_configurations[node_id]
if node_id == -1:
continue
for model_name in model_config:
if model_name != Ns2ScriptedMobility.name:
continue
current_config = session.mobility.get_model_config(node_id, model_name)
config = get_config_options(current_config, Ns2ScriptedMobility)
mapped_config = MappedConfig(config=config)
response.configs[node_id].CopyFrom(mapped_config)
return response
def GetMobilityConfig( def GetMobilityConfig(
self, request: GetMobilityConfigRequest, context: ServicerContext self, request: GetMobilityConfigRequest, context: ServicerContext
@ -1157,12 +1166,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get service defaults: %s", request) logging.debug("get service defaults: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
all_service_defaults = [] defaults = grpcutils.get_default_services(session)
for node_type in session.services.default_services: return GetServiceDefaultsResponse(defaults=defaults)
services = session.services.default_services[node_type]
service_defaults = ServiceDefaults(node_type=node_type, services=services)
all_service_defaults.append(service_defaults)
return GetServiceDefaultsResponse(defaults=all_service_defaults)
def SetServiceDefaults( def SetServiceDefaults(
self, request: SetServiceDefaultsRequest, context: ServicerContext self, request: SetServiceDefaultsRequest, context: ServicerContext
@ -1196,18 +1201,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get node service configs: %s", request) logging.debug("get node service configs: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
configs = [] configs = grpcutils.get_node_service_configs(session)
for node_id, service_configs in session.services.custom_services.items():
for name in service_configs:
service = session.services.get_service(node_id, name)
service_proto = grpcutils.get_service_configuration(service)
config = GetNodeServiceConfigsResponse.ServiceConfig(
node_id=node_id,
service=name,
data=service_proto,
files=service.config_data,
)
configs.append(config)
return GetNodeServiceConfigsResponse(configs=configs) return GetNodeServiceConfigsResponse(configs=configs)
def GetNodeService( def GetNodeService(
@ -1337,19 +1331,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get wlan configs: %s", request) logging.debug("get wlan configs: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
response = GetWlanConfigsResponse() configs = grpcutils.get_wlan_configs(session)
for node_id in session.mobility.node_configurations: return GetWlanConfigsResponse(configs=configs)
model_config = session.mobility.node_configurations[node_id]
if node_id == -1:
continue
for model_name in model_config:
if model_name != BasicRangeModel.name:
continue
current_config = session.mobility.get_model_config(node_id, model_name)
config = get_config_options(current_config, BasicRangeModel)
mapped_config = MappedConfig(config=config)
response.configs[node_id].CopyFrom(mapped_config)
return response
def GetWlanConfig( def GetWlanConfig(
self, request: GetWlanConfigRequest, context: ServicerContext self, request: GetWlanConfigRequest, context: ServicerContext
@ -1401,8 +1384,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get emane config: %s", request) logging.debug("get emane config: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
current_config = session.emane.get_configs() config = grpcutils.get_emane_config(session)
config = get_config_options(current_config, session.emane.emane_config)
return GetEmaneConfigResponse(config=config) return GetEmaneConfigResponse(config=config)
def SetEmaneConfig( def SetEmaneConfig(
@ -1433,11 +1415,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get emane models: %s", request) logging.debug("get emane models: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
models = [] models = grpcutils.get_emane_models(session)
for model in session.emane.models.keys():
if len(model.split("_")) != 2:
continue
models.append(model)
return GetEmaneModelsResponse(models=models) return GetEmaneModelsResponse(models=models)
def GetEmaneModelConfig( def GetEmaneModelConfig(
@ -1491,22 +1469,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
""" """
logging.debug("get emane model configs: %s", request) logging.debug("get emane model configs: %s", request)
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
configs = grpcutils.get_emane_model_configs(session)
configs = []
for _id in session.emane.node_configurations:
if _id == -1:
continue
model_configs = session.emane.node_configurations[_id]
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)
node_id, iface_id = grpcutils.parse_emane_model_id(_id)
model_config = GetEmaneModelConfigsResponse.ModelConfig(
node_id=node_id, model=model_name, iface_id=iface_id, config=config
)
configs.append(model_config)
return GetEmaneModelConfigsResponse(configs=configs) return GetEmaneModelConfigsResponse(configs=configs)
def SaveXml( def SaveXml(
@ -1713,21 +1676,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
:return: get node config service configs response :return: get node config service configs response
""" """
session = self.get_session(request.session_id, context) session = self.get_session(request.session_id, context)
configs = [] configs = grpcutils.get_node_config_service_configs(session)
for node in session.nodes.values():
if not isinstance(node, CoreNodeBase):
continue
for name, service in node.config_services.items():
if not service.custom_templates and not service.custom_config:
continue
config_proto = configservices_pb2.ConfigServiceConfig(
node_id=node.id,
name=name,
templates=service.custom_templates,
config=service.custom_config,
)
configs.append(config_proto)
return GetNodeConfigServiceConfigsResponse(configs=configs) return GetNodeConfigServiceConfigsResponse(configs=configs)
def GetNodeConfigServices( def GetNodeConfigServices(

View file

@ -119,7 +119,7 @@ class Session:
# states and hooks handlers # states and hooks handlers
self.state: EventTypes = EventTypes.DEFINITION_STATE self.state: EventTypes = EventTypes.DEFINITION_STATE
self.state_time: float = time.monotonic() self.state_time: float = time.monotonic()
self.hooks: Dict[EventTypes, Tuple[str, str]] = {} self.hooks: Dict[EventTypes, List[Tuple[str, str]]] = {}
self.state_hooks: Dict[EventTypes, List[Callable[[EventTypes], None]]] = {} self.state_hooks: Dict[EventTypes, List[Callable[[EventTypes], None]]] = {}
self.add_state_hook( self.add_state_hook(
state=EventTypes.RUNTIME_STATE, hook=self.runtime_state_hook state=EventTypes.RUNTIME_STATE, hook=self.runtime_state_hook

View file

@ -330,7 +330,7 @@ class CanvasGraph(tk.Canvas):
Draw existing session. Draw existing session.
""" """
# draw existing nodes # draw existing nodes
for core_node in session.nodes: for core_node in session.nodes.values():
logging.debug("drawing node: %s", core_node) logging.debug("drawing node: %s", core_node)
# peer to peer node is not drawn on the GUI # peer to peer node is not drawn on the GUI
if NodeUtils.is_ignore_node(core_node.type): if NodeUtils.is_ignore_node(core_node.type):

View file

@ -1,6 +1,6 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Dict, List from typing import Dict, List, Optional, Tuple
from core.api.grpc import common_pb2, configservices_pb2, core_pb2, services_pb2 from core.api.grpc import common_pb2, configservices_pb2, core_pb2, services_pb2
@ -119,6 +119,12 @@ class ConfigService:
) )
@dataclass
class ConfigServiceData:
templates: Dict[str, str]
config: Dict[str, str]
@dataclass @dataclass
class NodeServiceData: class NodeServiceData:
executables: List[str] executables: List[str]
@ -508,6 +514,22 @@ class Node:
dir: str = None dir: str = None
channel: str = None channel: str = None
# configurations
emane_model_configs: Dict[
Tuple[str, Optional[int]], Dict[str, ConfigOption]
] = field(default_factory=dict, repr=False)
wlan_config: Dict[str, ConfigOption] = field(default_factory=dict, repr=False)
mobility_config: Dict[str, ConfigOption] = field(default_factory=dict, repr=False)
service_configs: Dict[str, NodeServiceData] = field(
default_factory=dict, repr=False
)
service_file_configs: Dict[str, Dict[str, str]] = field(
default_factory=dict, repr=False
)
config_service_configs: Dict[str, ConfigServiceData] = field(
default_factory=dict, repr=False
)
@classmethod @classmethod
def from_proto(cls, proto: core_pb2.Node) -> "Node": def from_proto(cls, proto: core_pb2.Node) -> "Node":
return Node( return Node(
@ -549,20 +571,62 @@ class Node:
class Session: class Session:
id: int id: int
state: SessionState state: SessionState
nodes: List[Node] nodes: Dict[int, Node]
links: List[Link] links: List[Link]
dir: str dir: str
user: str
default_services: Dict[str, List[str]]
location: SessionLocation
hooks: List[Hook]
emane_models: List[str]
emane_config: Dict[str, ConfigOption]
metadata: Dict[str, str]
@classmethod @classmethod
def from_proto(cls, proto: core_pb2.Session) -> "Session": def from_proto(cls, proto: core_pb2.Session) -> "Session":
nodes = [Node.from_proto(x) for x in proto.nodes] nodes: Dict[int, Node] = {x.id: Node.from_proto(x) for x in proto.nodes}
links = [Link.from_proto(x) for x in proto.links] links = [Link.from_proto(x) for x in proto.links]
default_services = {x.node_type: x.services for x in proto.default_services}
hooks = [Hook.from_proto(x) for x in proto.hooks]
# update nodes with their current configurations
for model in proto.emane_model_configs:
iface_id = None
if model.iface_id != -1:
iface_id = model.iface_id
node = nodes[model.node_id]
key = (model.model, iface_id)
node.emane_model_configs[key] = ConfigOption.from_dict(model.config)
for node_id, mapped_config in proto.wlan_configs.items():
node = nodes[node_id]
node.wlan_config = ConfigOption.from_dict(mapped_config.config)
for config in proto.service_configs:
service = config.service
node = nodes[config.node_id]
node.service_configs[service] = NodeServiceData.from_proto(config.data)
for file, data in config.files.items():
files = node.service_file_configs.setdefault(service, {})
files[file] = data
for config in proto.config_service_configs:
node = nodes[config.node_id]
node.config_service_configs[config.name] = ConfigServiceData(
templates=dict(config.templates), config=dict(config.config)
)
for node_id, mapped_config in proto.mobility_configs.items():
node = nodes[node_id]
node.mobility_config = ConfigOption.from_dict(mapped_config.config)
return Session( return Session(
id=proto.id, id=proto.id,
state=SessionState(proto.state), state=SessionState(proto.state),
nodes=nodes, nodes=nodes,
links=links, links=links,
dir=proto.dir, dir=proto.dir,
user=proto.user,
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),
) )

View file

@ -714,6 +714,18 @@ message Session {
repeated Node nodes = 3; repeated Node nodes = 3;
repeated Link links = 4; repeated Link links = 4;
string dir = 5; string dir = 5;
string user = 6;
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.EmaneModelConfig 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;
} }
message SessionSummary { message SessionSummary {

View file

@ -54,13 +54,7 @@ message GetEmaneModelConfigsRequest {
} }
message GetEmaneModelConfigsResponse { message GetEmaneModelConfigsResponse {
message ModelConfig { repeated EmaneModelConfig configs = 1;
int32 node_id = 1;
string model = 2;
int32 iface_id = 3;
map<string, common.ConfigOption> config = 4;
}
repeated ModelConfig configs = 1;
} }
message GetEmaneEventChannelRequest { message GetEmaneEventChannelRequest {

View file

@ -59,6 +59,13 @@ message NodeServiceData {
string meta = 10; string meta = 10;
} }
message NodeServiceConfig {
int32 node_id = 1;
string service = 2;
NodeServiceData data = 3;
map<string, string> files = 4;
}
message GetServicesRequest { message GetServicesRequest {
} }
@ -89,13 +96,7 @@ message GetNodeServiceConfigsRequest {
} }
message GetNodeServiceConfigsResponse { message GetNodeServiceConfigsResponse {
message ServiceConfig { repeated NodeServiceConfig configs = 1;
int32 node_id = 1;
string service = 2;
NodeServiceData data = 3;
map<string, string> files = 4;
}
repeated ServiceConfig configs = 1;
} }
message GetNodeServiceRequest { message GetNodeServiceRequest {