pygui: modified usages of protobufs within coreclient to use module namespace to make more obvious, replaced config services and services with wrappers

This commit is contained in:
Blake Harnden 2020-07-25 20:27:11 -07:00
parent a9a2fb8e46
commit 82a212d1cf
6 changed files with 213 additions and 128 deletions

View file

@ -12,13 +12,15 @@ from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple
import grpc
from core.api.grpc import client, core_pb2
from core.api.grpc.configservices_pb2 import ConfigService, ConfigServiceConfig
from core.api.grpc.core_pb2 import CpuUsageEvent, Event
from core.api.grpc.emane_pb2 import EmaneModelConfig
from core.api.grpc.mobility_pb2 import MobilityConfig
from core.api.grpc.services_pb2 import NodeServiceData, ServiceConfig, ServiceFileConfig
from core.api.grpc.wlan_pb2 import WlanConfig
from core.api.grpc import (
client,
configservices_pb2,
core_pb2,
emane_pb2,
mobility_pb2,
services_pb2,
wlan_pb2,
)
from core.gui import appconfig
from core.gui.appconfig import CoreServer, Observer
from core.gui.dialogs.emaneinstall import EmaneInstallDialog
@ -33,6 +35,7 @@ from core.gui.interface import InterfaceManager
from core.gui.nodeutils import NodeDraw, NodeUtils
from core.gui.wrappers import (
ConfigOption,
ConfigService,
ExceptionEvent,
Hook,
Interface,
@ -42,6 +45,7 @@ from core.gui.wrappers import (
MessageType,
Node,
NodeEvent,
NodeServiceData,
NodeType,
Position,
SessionLocation,
@ -150,7 +154,7 @@ class CoreClient:
for observer in self.app.guiconfig.observers:
self.custom_observers[observer.name] = observer
def handle_events(self, event: Event) -> None:
def handle_events(self, event: core_pb2.Event) -> None:
if event.source == GUI_SOURCE:
return
if event.session_id != self.session_id:
@ -288,7 +292,7 @@ class CoreClient:
logging.debug("handling throughputs event: %s", event)
self.app.after(0, self.app.canvas.set_throughputs, event)
def handle_cpu_event(self, event: CpuUsageEvent) -> None:
def handle_cpu_event(self, event: core_pb2.CpuUsageEvent) -> None:
self.app.after(0, self.app.statusbar.set_cpu, event.usage)
def handle_exception_event(self, event: ExceptionEvent) -> None:
@ -514,7 +518,7 @@ class CoreClient:
# get config service informations
response = self.client.get_config_services()
for service in response.services:
self.config_services[service.name] = service
self.config_services[service.name] = ConfigService.from_proto(service)
group_services = self.config_services_groups.setdefault(
service.group, set()
)
@ -708,7 +712,7 @@ class CoreClient:
logging.debug(
"get node(%s) %s service, response: %s", node_id, service_name, response
)
return response.service
return NodeServiceData.from_proto(response.service)
def set_node_service(
self,
@ -742,7 +746,7 @@ class CoreClient:
response,
)
response = self.client.get_node_service(self.session_id, node_id, service_name)
return response.service
return NodeServiceData.from_proto(response.service)
def get_node_service_file(
self, node_id: int, service_name: str, file_name: str
@ -1000,7 +1004,7 @@ class CoreClient:
self.links[edge.token] = edge
logging.info("Add link between %s and %s", src_node.name, dst_node.name)
def get_wlan_configs_proto(self) -> List[WlanConfig]:
def get_wlan_configs_proto(self) -> List[wlan_pb2.WlanConfig]:
configs = []
for canvas_node in self.canvas_nodes.values():
if canvas_node.core_node.type != NodeType.WIRELESS_LAN:
@ -1009,11 +1013,11 @@ class CoreClient:
continue
config = ConfigOption.to_dict(canvas_node.wlan_config)
node_id = canvas_node.core_node.id
wlan_config = WlanConfig(node_id=node_id, config=config)
wlan_config = wlan_pb2.WlanConfig(node_id=node_id, config=config)
configs.append(wlan_config)
return configs
def get_mobility_configs_proto(self) -> List[MobilityConfig]:
def get_mobility_configs_proto(self) -> List[mobility_pb2.MobilityConfig]:
configs = []
for canvas_node in self.canvas_nodes.values():
if canvas_node.core_node.type != NodeType.WIRELESS_LAN:
@ -1022,11 +1026,13 @@ class CoreClient:
continue
config = ConfigOption.to_dict(canvas_node.mobility_config)
node_id = canvas_node.core_node.id
mobility_config = MobilityConfig(node_id=node_id, config=config)
mobility_config = mobility_pb2.MobilityConfig(
node_id=node_id, config=config
)
configs.append(mobility_config)
return configs
def get_emane_model_configs_proto(self) -> List[EmaneModelConfig]:
def get_emane_model_configs_proto(self) -> List[emane_pb2.EmaneModelConfig]:
configs = []
for canvas_node in self.canvas_nodes.values():
if canvas_node.core_node.type != NodeType.EMANE:
@ -1037,13 +1043,13 @@ class CoreClient:
config = ConfigOption.to_dict(config)
if iface_id is None:
iface_id = -1
config_proto = EmaneModelConfig(
config_proto = emane_pb2.EmaneModelConfig(
node_id=node_id, iface_id=iface_id, model=model, config=config
)
configs.append(config_proto)
return configs
def get_service_configs_proto(self) -> List[ServiceConfig]:
def get_service_configs_proto(self) -> List[services_pb2.ServiceConfig]:
configs = []
for canvas_node in self.canvas_nodes.values():
if not NodeUtils.is_container_node(canvas_node.core_node.type):
@ -1052,7 +1058,7 @@ class CoreClient:
continue
node_id = canvas_node.core_node.id
for name, config in canvas_node.service_configs.items():
config_proto = ServiceConfig(
config_proto = services_pb2.ServiceConfig(
node_id=node_id,
service=name,
directories=config.dirs,
@ -1064,7 +1070,7 @@ class CoreClient:
configs.append(config_proto)
return configs
def get_service_file_configs_proto(self) -> List[ServiceFileConfig]:
def get_service_file_configs_proto(self) -> List[services_pb2.ServiceFileConfig]:
configs = []
for canvas_node in self.canvas_nodes.values():
if not NodeUtils.is_container_node(canvas_node.core_node.type):
@ -1074,13 +1080,15 @@ class CoreClient:
node_id = canvas_node.core_node.id
for service, file_configs in canvas_node.service_file_configs.items():
for file, data in file_configs.items():
config_proto = ServiceFileConfig(
config_proto = services_pb2.ServiceFileConfig(
node_id=node_id, service=service, file=file, data=data
)
configs.append(config_proto)
return configs
def get_config_service_configs_proto(self) -> List[ConfigServiceConfig]:
def get_config_service_configs_proto(
self
) -> List[configservices_pb2.ConfigServiceConfig]:
config_service_protos = []
for canvas_node in self.canvas_nodes.values():
if not NodeUtils.is_container_node(canvas_node.core_node.type):
@ -1090,7 +1098,7 @@ class CoreClient:
node_id = canvas_node.core_node.id
for name, service_config in canvas_node.config_service_configs.items():
config = service_config.get("config", {})
config_proto = ConfigServiceConfig(
config_proto = configservices_pb2.ConfigServiceConfig(
node_id=node_id,
name=name,
templates=service_config["templates"],

View file

@ -8,11 +8,10 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Set
import grpc
from core.api.grpc.services_pb2 import ServiceValidationMode
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import FRAME_PAD, PADX, PADY
from core.gui.widgets import CodeText, ConfigFrame, ListboxScroll
from core.gui.wrappers import ConfigOption
from core.gui.wrappers import ConfigOption, ServiceValidationMode
if TYPE_CHECKING:
from core.gui.app import Application

View file

@ -4,11 +4,10 @@ from typing import TYPE_CHECKING, Dict, Optional
import grpc
from core.api.grpc.mobility_pb2 import MobilityAction
from core.gui.dialogs.dialog import Dialog
from core.gui.images import ImageEnum
from core.gui.themes import PADX, PADY
from core.gui.wrappers import ConfigOption, Node
from core.gui.wrappers import ConfigOption, MobilityAction, Node
if TYPE_CHECKING:
from core.gui.app import Application
@ -150,7 +149,7 @@ class MobilityPlayerDialog(Dialog):
session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.START
session_id, self.node.id, MobilityAction.START.value
)
except grpc.RpcError as e:
self.app.show_grpc_exception("Mobility Error", e)
@ -160,7 +159,7 @@ class MobilityPlayerDialog(Dialog):
session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.PAUSE
session_id, self.node.id, MobilityAction.PAUSE.value
)
except grpc.RpcError as e:
self.app.show_grpc_exception("Mobility Error", e)
@ -170,7 +169,7 @@ class MobilityPlayerDialog(Dialog):
session_id = self.app.core.session_id
try:
self.app.core.client.mobility_action(
session_id, self.node.id, MobilityAction.STOP
session_id, self.node.id, MobilityAction.STOP.value
)
except grpc.RpcError as e:
self.app.show_grpc_exception("Mobility Error", e)

View file

@ -7,12 +7,12 @@ from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
import grpc
from PIL.ImageTk import PhotoImage
from core.api.grpc.services_pb2 import NodeServiceData, ServiceValidationMode
from core.gui.dialogs.copyserviceconfig import CopyServiceConfigDialog
from core.gui.dialogs.dialog import Dialog
from core.gui.images import ImageEnum, Images
from core.gui.themes import FRAME_PAD, PADX, PADY
from core.gui.widgets import CodeText, ListboxScroll
from core.gui.wrappers import NodeServiceData, ServiceValidationMode
if TYPE_CHECKING:
from core.gui.app import Application
@ -72,7 +72,7 @@ class ServiceConfigDialog(Dialog):
self.service_file_data: Optional[CodeText] = None
self.validation_period_entry: Optional[ttk.Entry] = None
self.original_service_files: Dict[str, str] = {}
self.default_config: NodeServiceData = None
self.default_config: Optional[NodeServiceData] = None
self.temp_service_files: Dict[str, str] = {}
self.modified_files: Set[str] = set()
self.has_error: bool = False

View file

@ -6,7 +6,6 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple
import grpc
from PIL.ImageTk import PhotoImage
from core.api.grpc.services_pb2 import NodeServiceData
from core.gui import themes
from core.gui.dialogs.emaneconfig import EmaneConfigDialog
from core.gui.dialogs.mobilityconfig import MobilityConfigDialog
@ -20,7 +19,7 @@ from core.gui.graph.edges import CanvasEdge, CanvasWirelessEdge
from core.gui.graph.tooltip import CanvasTooltip
from core.gui.images import ImageEnum
from core.gui.nodeutils import ANTENNA_SIZE, NodeUtils
from core.gui.wrappers import ConfigOption, Interface, Node, NodeType
from core.gui.wrappers import ConfigOption, Interface, Node, NodeServiceData, NodeType
if TYPE_CHECKING:
from core.gui.app import Application

View file

@ -2,7 +2,25 @@ from dataclasses import dataclass, field
from enum import Enum
from typing import Dict, List
from core.api.grpc import common_pb2, core_pb2
from core.api.grpc import common_pb2, configservices_pb2, core_pb2, services_pb2
class ConfigServiceValidationMode(Enum):
BLOCKING = 0
NON_BLOCKING = 1
TIMER = 2
class ServiceValidationMode(Enum):
BLOCKING = 0
NON_BLOCKING = 1
TIMER = 2
class MobilityAction(Enum):
START = 0
PAUSE = 1
STOP = 2
class ConfigOptionType(Enum):
@ -68,6 +86,68 @@ class MessageType(Enum):
TTY = 64
@dataclass
class ConfigService:
group: str
name: str
executables: List[str]
dependencies: List[str]
directories: List[str]
files: List[str]
startup: List[str]
validate: List[str]
shutdown: List[str]
validation_mode: ConfigServiceValidationMode
validation_timer: int
validation_period: float
@classmethod
def from_proto(cls, proto: configservices_pb2.ConfigService) -> "ConfigService":
return ConfigService(
group=proto.group,
name=proto.name,
executables=proto.executables,
dependencies=proto.dependencies,
directories=proto.directories,
files=proto.files,
startup=proto.startup,
validate=proto.validate,
shutdown=proto.shutdown,
validation_mode=ConfigServiceValidationMode(proto.validation_mode),
validation_timer=proto.validation_timer,
validation_period=proto.validation_period,
)
@dataclass
class NodeServiceData:
executables: List[str]
dependencies: List[str]
dirs: List[str]
configs: List[str]
startup: List[str]
validate: List[str]
validation_mode: ServiceValidationMode
validation_timer: int
shutdown: List[str]
meta: str
@classmethod
def from_proto(cls, proto: services_pb2.NodeServiceData) -> "NodeServiceData":
return NodeServiceData(
executables=proto.executables,
dependencies=proto.dependencies,
dirs=proto.dirs,
configs=proto.configs,
startup=proto.startup,
validate=proto.validate,
validation_mode=proto.validation_mode,
validation_timer=proto.validation_timer,
shutdown=proto.shutdown,
meta=proto.meta,
)
@dataclass
class BridgeThroughput:
node_id: int
@ -119,15 +199,15 @@ class SessionLocation:
scale: float
@classmethod
def from_proto(cls, location: core_pb2.SessionLocation) -> "SessionLocation":
def from_proto(cls, proto: core_pb2.SessionLocation) -> "SessionLocation":
return SessionLocation(
x=location.x,
y=location.y,
z=location.z,
lat=location.lat,
lon=location.lon,
alt=location.alt,
scale=location.scale,
x=proto.x,
y=proto.y,
z=proto.z,
lat=proto.lat,
lon=proto.lon,
alt=proto.alt,
scale=proto.scale,
)
def to_proto(self) -> core_pb2.SessionLocation:
@ -154,16 +234,16 @@ class ExceptionEvent:
@classmethod
def from_proto(
cls, session_id: int, event: core_pb2.ExceptionEvent
cls, session_id: int, proto: core_pb2.ExceptionEvent
) -> "ExceptionEvent":
return ExceptionEvent(
session_id=session_id,
node_id=event.node_id,
level=ExceptionLevel(event.level),
source=event.source,
date=event.date,
text=event.text,
opaque=event.opaque,
node_id=proto.node_id,
level=ExceptionLevel(proto.level),
source=proto.source,
date=proto.date,
text=proto.text,
opaque=proto.opaque,
)
@ -190,14 +270,14 @@ class ConfigOption:
return {k: v.value for k, v in config.items()}
@classmethod
def from_proto(cls, option: common_pb2.ConfigOption) -> "ConfigOption":
def from_proto(cls, proto: common_pb2.ConfigOption) -> "ConfigOption":
return ConfigOption(
label=option.label,
name=option.name,
value=option.value,
type=ConfigOptionType(option.type),
group=option.group,
select=option.select,
label=proto.label,
name=proto.name,
value=proto.value,
type=ConfigOptionType(proto.type),
group=proto.group,
select=proto.select,
)
@ -217,20 +297,20 @@ class Interface:
net2_id: int = None
@classmethod
def from_proto(cls, iface: core_pb2.Interface) -> "Interface":
def from_proto(cls, proto: core_pb2.Interface) -> "Interface":
return Interface(
id=iface.id,
name=iface.name,
mac=iface.mac,
ip4=iface.ip4,
ip4_mask=iface.ip4_mask,
ip6=iface.ip6,
ip6_mask=iface.ip6_mask,
net_id=iface.net_id,
flow_id=iface.flow_id,
mtu=iface.mtu,
node_id=iface.node_id,
net2_id=iface.net2_id,
id=proto.id,
name=proto.name,
mac=proto.mac,
ip4=proto.ip4,
ip4_mask=proto.ip4_mask,
ip6=proto.ip6,
ip6_mask=proto.ip6_mask,
net_id=proto.net_id,
flow_id=proto.flow_id,
mtu=proto.mtu,
node_id=proto.node_id,
net2_id=proto.net2_id,
)
def to_proto(self) -> core_pb2.Interface:
@ -264,18 +344,18 @@ class LinkOptions:
unidirectional: bool = False
@classmethod
def from_proto(cls, options: core_pb2.LinkOptions) -> "LinkOptions":
def from_proto(cls, proto: core_pb2.LinkOptions) -> "LinkOptions":
return LinkOptions(
jitter=options.jitter,
key=options.key,
mburst=options.mburst,
mer=options.mer,
loss=options.loss,
bandwidth=options.bandwidth,
burst=options.burst,
delay=options.delay,
dup=options.dup,
unidirectional=options.unidirectional,
jitter=proto.jitter,
key=proto.key,
mburst=proto.mburst,
mer=proto.mer,
loss=proto.loss,
bandwidth=proto.bandwidth,
burst=proto.burst,
delay=proto.delay,
dup=proto.dup,
unidirectional=proto.unidirectional,
)
def to_proto(self) -> core_pb2.LinkOptions:
@ -306,26 +386,26 @@ class Link:
color: str = None
@classmethod
def from_proto(cls, link: core_pb2.Link) -> "Link":
def from_proto(cls, proto: core_pb2.Link) -> "Link":
iface1 = None
if link.HasField("iface1"):
iface1 = Interface.from_proto(link.iface1)
if proto.HasField("iface1"):
iface1 = Interface.from_proto(proto.iface1)
iface2 = None
if link.HasField("iface2"):
iface2 = Interface.from_proto(link.iface2)
if proto.HasField("iface2"):
iface2 = Interface.from_proto(proto.iface2)
options = None
if link.HasField("options"):
options = LinkOptions.from_proto(link.options)
if proto.HasField("options"):
options = LinkOptions.from_proto(proto.options)
return Link(
type=LinkType(link.type),
node1_id=link.node1_id,
node2_id=link.node2_id,
type=LinkType(proto.type),
node1_id=proto.node1_id,
node2_id=proto.node2_id,
iface1=iface1,
iface2=iface2,
options=options,
network_id=link.network_id,
label=link.label,
color=link.color,
network_id=proto.network_id,
label=proto.label,
color=proto.color,
)
def to_proto(self) -> core_pb2.Link:
@ -360,13 +440,13 @@ class SessionSummary:
dir: str
@classmethod
def from_proto(cls, summary: core_pb2.SessionSummary) -> "SessionSummary":
def from_proto(cls, proto: core_pb2.SessionSummary) -> "SessionSummary":
return SessionSummary(
id=summary.id,
state=SessionState(summary.state),
nodes=summary.nodes,
file=summary.file,
dir=summary.dir,
id=proto.id,
state=SessionState(proto.state),
nodes=proto.nodes,
file=proto.file,
dir=proto.dir,
)
@ -377,8 +457,8 @@ class Hook:
data: str
@classmethod
def from_proto(cls, hook: core_pb2.Hook) -> "Hook":
return Hook(state=SessionState(hook.state), file=hook.file, data=hook.data)
def from_proto(cls, proto: core_pb2.Hook) -> "Hook":
return Hook(state=SessionState(proto.state), file=proto.file, data=proto.data)
def to_proto(self) -> core_pb2.Hook:
return core_pb2.Hook(state=self.state.value, file=self.file, data=self.data)
@ -390,8 +470,8 @@ class Position:
y: float
@classmethod
def from_proto(cls, position: core_pb2.Position) -> "Position":
return Position(x=position.x, y=position.y)
def from_proto(cls, proto: core_pb2.Position) -> "Position":
return Position(x=proto.x, y=proto.y)
def to_proto(self) -> core_pb2.Position:
return core_pb2.Position(x=self.x, y=self.y)
@ -404,8 +484,8 @@ class Geo:
alt: float = None
@classmethod
def from_proto(cls, geo: core_pb2.Geo) -> "Geo":
return Geo(lat=geo.lat, lon=geo.lon, alt=geo.alt)
def from_proto(cls, proto: core_pb2.Geo) -> "Geo":
return Geo(lat=proto.lat, lon=proto.lon, alt=proto.alt)
def to_proto(self) -> core_pb2.Geo:
return core_pb2.Geo(lat=self.lat, lon=self.lon, alt=self.alt)
@ -429,22 +509,22 @@ class Node:
channel: str = None
@classmethod
def from_proto(cls, node: core_pb2.Node) -> "Node":
def from_proto(cls, proto: core_pb2.Node) -> "Node":
return Node(
id=node.id,
name=node.name,
type=NodeType(node.type),
model=node.model,
position=Position.from_proto(node.position),
services=list(node.services),
config_services=list(node.config_services),
emane=node.emane,
icon=node.icon,
image=node.image,
server=node.server,
geo=Geo.from_proto(node.geo),
dir=node.dir,
channel=node.channel,
id=proto.id,
name=proto.name,
type=NodeType(proto.type),
model=proto.model,
position=Position.from_proto(proto.position),
services=list(proto.services),
config_services=list(proto.config_services),
emane=proto.emane,
icon=proto.icon,
image=proto.image,
server=proto.server,
geo=Geo.from_proto(proto.geo),
dir=proto.dir,
channel=proto.channel,
)
def to_proto(self) -> core_pb2.Node:
@ -471,10 +551,10 @@ class LinkEvent:
link: Link
@classmethod
def from_proto(cls, event: core_pb2.LinkEvent) -> "LinkEvent":
def from_proto(cls, proto: core_pb2.LinkEvent) -> "LinkEvent":
return LinkEvent(
message_type=MessageType(event.message_type),
link=Link.from_proto(event.link),
message_type=MessageType(proto.message_type),
link=Link.from_proto(proto.link),
)
@ -484,8 +564,8 @@ class NodeEvent:
node: Node
@classmethod
def from_proto(cls, event: core_pb2.NodeEvent) -> "NodeEvent":
def from_proto(cls, proto: core_pb2.NodeEvent) -> "NodeEvent":
return NodeEvent(
message_type=MessageType(event.message_type),
node=Node.from_proto(event.node),
message_type=MessageType(proto.message_type),
node=Node.from_proto(proto.node),
)