daemon: added grpc wrapped client tests, added new wrapped class ServiceFileConfig to consolidate associated data for its purpose

This commit is contained in:
Blake Harnden 2021-04-01 13:37:19 -07:00
parent 6086d1229b
commit 44f81391c4
5 changed files with 1335 additions and 36 deletions

View file

@ -5,6 +5,7 @@ gRpc client for interfacing with CORE.
import logging
import threading
from contextlib import contextmanager
from pathlib import Path
from queue import Queue
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple
@ -54,7 +55,6 @@ from core.api.grpc.services_pb2 import (
GetServicesRequest,
ServiceActionRequest,
ServiceDefaults,
ServiceFileConfig,
SetNodeServiceFileRequest,
SetNodeServiceRequest,
SetServiceDefaultsRequest,
@ -68,6 +68,7 @@ from core.api.grpc.wlan_pb2 import (
)
from core.api.grpc.wrappers import Hook
from core.emulator.data import IpPrefixes
from core.errors import CoreError
class MoveNodesStreamer:
@ -675,13 +676,17 @@ class CoreGrpcClient:
:return: True for success, False otherwise
:raises grpc.RpcError: when session or node doesn't exist
"""
if position and geo:
raise CoreError("cannot edit position and geo at same time")
position_proto = position.to_proto() if position else None
geo_proto = geo.to_proto() if geo else None
request = core_pb2.EditNodeRequest(
session_id=session_id,
node_id=node_id,
position=position.to_proto(),
position=position_proto,
icon=icon,
source=source,
geo=geo.to_proto(),
geo=geo_proto,
)
response = self.stub.EditNode(request)
return response.result
@ -994,7 +999,7 @@ class CoreGrpcClient:
def get_node_service_configs(
self, session_id: int
) -> List[wrappers.NodeServiceData]:
) -> List[wrappers.NodeServiceConfig]:
"""
Get service data for a node.
@ -1005,8 +1010,8 @@ class CoreGrpcClient:
request = GetNodeServiceConfigsRequest(session_id=session_id)
response = self.stub.GetNodeServiceConfigs(request)
node_services = []
for service_proto in response.configs:
node_service = wrappers.NodeServiceData.from_proto(service_proto)
for config in response.configs:
node_service = wrappers.NodeServiceConfig.from_proto(config)
node_services.append(node_service)
return node_services
@ -1065,22 +1070,17 @@ class CoreGrpcClient:
return response.result
def set_node_service_file(
self, session_id: int, node_id: int, service: str, file_name: str, data: str
self, session_id: int, service_file_config: wrappers.ServiceFileConfig
) -> bool:
"""
Set a service file for a node.
:param session_id: session id
:param node_id: node id
:param service: service name
:param file_name: file name to save
:param data: data to save for file
:param service_file_config: configuration to set
:return: True for success, False otherwise
:raises grpc.RpcError: when session or node doesn't exist
"""
config = ServiceFileConfig(
node_id=node_id, service=service, file=file_name, data=data
)
config = service_file_config.to_proto()
request = SetNodeServiceFileRequest(session_id=session_id, config=config)
response = self.stub.SetNodeServiceFile(request)
return response.result
@ -1263,7 +1263,7 @@ class CoreGrpcClient:
with open(file_path, "w") as xml_file:
xml_file.write(response.data)
def open_xml(self, file_path: str, start: bool = False) -> Tuple[bool, int]:
def open_xml(self, file_path: Path, start: bool = False) -> Tuple[bool, int]:
"""
Load a local scenario XML file to open as a new session.
@ -1271,9 +1271,9 @@ class CoreGrpcClient:
:param start: tuple of result and session id when successful
:return: tuple of result and session id
"""
with open(file_path, "r") as xml_file:
data = xml_file.read()
request = core_pb2.OpenXmlRequest(data=data, start=start, file=file_path)
with file_path.open("r") as f:
data = f.read()
request = core_pb2.OpenXmlRequest(data=data, start=start, file=str(file_path))
response = self.stub.OpenXml(request)
return response.result, response.session_id

View file

@ -233,6 +233,23 @@ class NodeServiceData:
)
@dataclass
class NodeServiceConfig:
node_id: int
service: str
data: NodeServiceData
files: Dict[str, str] = field(default_factory=dict)
@classmethod
def from_proto(cls, proto: services_pb2.NodeServiceConfig) -> "NodeServiceConfig":
return NodeServiceConfig(
node_id=proto.node_id,
service=proto.service,
data=NodeServiceData.from_proto(proto.data),
files=dict(proto.files),
)
@dataclass
class ServiceConfig:
node_id: int
@ -255,6 +272,19 @@ class ServiceConfig:
)
@dataclass
class ServiceFileConfig:
node_id: int
service: str
file: str
data: str = field(repr=False)
def to_proto(self) -> services_pb2.ServiceFileConfig:
return services_pb2.ServiceFileConfig(
node_id=self.node_id, service=self.service, file=self.file, data=self.data
)
@dataclass
class BridgeThroughput:
node_id: int
@ -724,6 +754,9 @@ class Session:
metadata: Dict[str, str]
file: Path
def set_node(self, node: Node) -> None:
self.nodes[node.id] = node
@classmethod
def from_proto(cls, proto: core_pb2.Session) -> "Session":
nodes: Dict[int, Node] = {x.id: Node.from_proto(x) for x in proto.nodes}

View file

@ -6,6 +6,7 @@ import json
import logging
import os
import tkinter as tk
from pathlib import Path
from tkinter import messagebox
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple
@ -28,6 +29,7 @@ from core.api.grpc.wrappers import (
NodeType,
Position,
ServiceConfig,
ServiceFileConfig,
Session,
SessionLocation,
SessionState,
@ -551,7 +553,7 @@ class CoreClient:
except grpc.RpcError as e:
self.app.show_grpc_exception("Save XML Error", e)
def open_xml(self, file_path: str) -> None:
def open_xml(self, file_path: Path) -> None:
"""
Open core xml
"""
@ -599,17 +601,9 @@ class CoreClient:
def set_node_service_file(
self, node_id: int, service_name: str, file_name: str, data: str
) -> None:
result = self.client.set_node_service_file(
self.session.id, node_id, service_name, file_name, data
)
logging.info(
"set node(%s) service file, service: %s, file: %s, data: %s, result: %s",
node_id,
service_name,
file_name,
data,
result,
)
config = ServiceFileConfig(node_id, service_name, file_name, data)
result = self.client.set_node_service_file(self.session.id, config)
logging.info("set service file config %s: %s", config, result)
def create_nodes_and_links(self) -> None:
"""
@ -639,10 +633,8 @@ class CoreClient:
self.client.set_mobility_config(self.session.id, node_id, config)
for config in self.get_service_configs():
self.client.set_node_service(self.session.id, config)
for node_id, service, file, data in self.get_service_file_configs():
self.client.set_node_service_file(
self.session.id, node_id, service, file, data
)
for config in self.get_service_file_configs():
self.client.set_node_service_file(self.session.id, config)
for hook in self.session.hooks.values():
self.client.add_hook(self.session.id, hook)
for config in self.get_emane_model_configs():
@ -806,7 +798,7 @@ class CoreClient:
configs.append(config)
return configs
def get_service_file_configs(self) -> List[Tuple[int, str, str, str]]:
def get_service_file_configs(self) -> List[ServiceFileConfig]:
configs = []
for node in self.session.nodes.values():
if not nutils.is_container(node):
@ -815,7 +807,8 @@ class CoreClient:
continue
for service, file_configs in node.service_file_configs.items():
for file, data in file_configs.items():
configs.append((node.id, service, file, data))
config = ServiceFileConfig(node.id, service, file, data)
configs.append(config)
return configs
def get_config_service_configs_proto(

View file

@ -312,6 +312,7 @@ class Menubar(tk.Menu):
filetypes=(("XML Files", "*.xml"), ("All Files", "*")),
)
if file_path:
file_path = Path(file_path)
self.open_xml_task(file_path)
def open_xml_task(self, file_path: Path) -> None:

1272
daemon/tests/test_grpcw.py Normal file

File diff suppressed because it is too large Load diff