daemon: fixed sdt icons due to legacy gui removal, updated node.type to node.model to avoid variables with the same names with different meanings

This commit is contained in:
Blake Harnden 2022-04-05 13:39:57 -07:00
parent ea751727b4
commit 5ee561b210
15 changed files with 73 additions and 93 deletions

View file

@ -748,9 +748,9 @@ class CoreGrpcClient:
:raises grpc.RpcError: when session doesn't exist :raises grpc.RpcError: when session doesn't exist
""" """
defaults = [] defaults = []
for node_type in service_defaults: for model in service_defaults:
services = service_defaults[node_type] services = service_defaults[model]
default = ServiceDefaults(node_type=node_type, services=services) default = ServiceDefaults(model=model, services=services)
defaults.append(default) defaults.append(default)
request = SetServiceDefaultsRequest(session_id=session_id, defaults=defaults) request = SetServiceDefaultsRequest(session_id=session_id, defaults=defaults)
response = self.stub.SetServiceDefaults(request) response = self.stub.SetServiceDefaults(request)

View file

@ -33,7 +33,7 @@ def handle_node_event(node_data: NodeData) -> core_pb2.Event:
node_proto = core_pb2.Node( node_proto = core_pb2.Node(
id=node.id, id=node.id,
name=node.name, name=node.name,
model=node.type, model=node.model,
icon=node.icon, icon=node.icon,
position=position, position=position,
geo=geo, geo=geo,

View file

@ -286,7 +286,6 @@ def get_node_proto(
lat=node.position.lat, lon=node.position.lon, alt=node.position.alt lat=node.position.lat, lon=node.position.lon, alt=node.position.alt
) )
services = [x.name for x in node.services] services = [x.name for x in node.services]
model = node.type
node_dir = None node_dir = None
config_services = [] config_services = []
if isinstance(node, CoreNodeBase): if isinstance(node, CoreNodeBase):
@ -341,7 +340,7 @@ def get_node_proto(
id=node.id, id=node.id,
name=node.name, name=node.name,
emane=emane_model, emane=emane_model,
model=model, model=node.model,
type=node_type.value, type=node_type.value,
position=position, position=position,
geo=geo, geo=geo,
@ -729,8 +728,8 @@ def get_default_services(session: Session) -> List[ServiceDefaults]:
:return: list of default service sets :return: list of default service sets
""" """
default_services = [] default_services = []
for name, services in session.services.default_services.items(): for model, services in session.services.default_services.items():
default_service = ServiceDefaults(node_type=name, services=services) default_service = ServiceDefaults(model=model, services=services)
default_services.append(default_service) default_services.append(default_service)
return default_services return default_services

View file

@ -920,7 +920,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer):
session.services.default_services.clear() session.services.default_services.clear()
for service_defaults in request.defaults: for service_defaults in request.defaults:
session.services.default_services[ session.services.default_services[
service_defaults.node_type service_defaults.model
] = service_defaults.services ] = service_defaults.services
return SetServiceDefaultsResponse(result=True) return SetServiceDefaultsResponse(result=True)

View file

@ -210,12 +210,12 @@ class Service:
@dataclass @dataclass
class ServiceDefault: class ServiceDefault:
node_type: str model: str
services: List[str] services: List[str]
@classmethod @classmethod
def from_proto(cls, proto: services_pb2.ServiceDefaults) -> "ServiceDefault": def from_proto(cls, proto: services_pb2.ServiceDefaults) -> "ServiceDefault":
return ServiceDefault(node_type=proto.node_type, services=list(proto.services)) return ServiceDefault(model=proto.model, services=list(proto.services))
@dataclass @dataclass
@ -884,9 +884,7 @@ class Session:
def from_proto(cls, proto: core_pb2.Session) -> "Session": def from_proto(cls, proto: core_pb2.Session) -> "Session":
nodes: Dict[int, Node] = {x.id: 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 = { default_services = {x.model: set(x.services) for x in proto.default_services}
x.node_type: set(x.services) for x in proto.default_services
}
hooks = {x.file: Hook.from_proto(x) for x in proto.hooks} hooks = {x.file: Hook.from_proto(x) for x in proto.hooks}
file_path = Path(proto.file) if proto.file else None file_path = Path(proto.file) if proto.file else None
options = ConfigOption.from_dict(proto.options) options = ConfigOption.from_dict(proto.options)
@ -914,9 +912,9 @@ class Session:
options = {k: v.to_proto() for k, v in self.options.items()} options = {k: v.to_proto() for k, v in self.options.items()}
servers = [x.to_proto() for x in self.servers] servers = [x.to_proto() for x in self.servers]
default_services = [] default_services = []
for node_type, services in self.default_services.items(): for model, services in self.default_services.items():
default_service = services_pb2.ServiceDefaults( default_service = services_pb2.ServiceDefaults(
node_type=node_type, services=services model=model, services=services
) )
default_services.append(default_service) default_services.append(default_service)
file = str(self.file) if self.file else None file = str(self.file) if self.file else None

View file

@ -536,15 +536,15 @@ class Session:
# add services to needed nodes # add services to needed nodes
if isinstance(node, (CoreNode, PhysicalNode)): if isinstance(node, (CoreNode, PhysicalNode)):
node.type = options.model node.model = options.model
if options.legacy or options.services: if options.legacy or options.services:
logger.debug("set node type: %s", node.type) logger.debug("set node type: %s", node.model)
self.services.add_services(node, node.type, options.services) self.services.add_services(node, node.model, options.services)
# add config services # add config services
config_services = options.config_services config_services = options.config_services
if not options.legacy and not config_services and not node.services: if not options.legacy and not config_services and not node.services:
config_services = self.services.default_services.get(node.type, []) config_services = self.services.default_services.get(node.model, [])
logger.info("setting node config services: %s", config_services) logger.info("setting node config services: %s", config_services)
for name in config_services: for name in config_services:
service_class = self.service_manager.get_service(name) service_class = self.service_manager.get_service(name)

View file

@ -62,11 +62,9 @@ class NodeBase(abc.ABC):
if _id is None: if _id is None:
_id = session.next_node_id() _id = session.next_node_id()
self.id: int = _id self.id: int = _id
if name is None: self.name: str = name or f"o{self.id}"
name = f"o{self.id}"
self.name: str = name
self.server: "DistributedServer" = server self.server: "DistributedServer" = server
self.type: Optional[str] = None self.model: Optional[str] = None
self.services: CoreServices = [] self.services: CoreServices = []
self.ifaces: Dict[int, CoreInterface] = {} self.ifaces: Dict[int, CoreInterface] = {}
self.iface_id: int = 0 self.iface_id: int = 0

View file

@ -663,7 +663,6 @@ class SwitchNode(CoreNetwork):
apitype: NodeTypes = NodeTypes.SWITCH apitype: NodeTypes = NodeTypes.SWITCH
policy: NetworkPolicy = NetworkPolicy.ACCEPT policy: NetworkPolicy = NetworkPolicy.ACCEPT
type: str = "lanswitch"
class HubNode(CoreNetwork): class HubNode(CoreNetwork):
@ -674,7 +673,6 @@ class HubNode(CoreNetwork):
apitype: NodeTypes = NodeTypes.HUB apitype: NodeTypes = NodeTypes.HUB
policy: NetworkPolicy = NetworkPolicy.ACCEPT policy: NetworkPolicy = NetworkPolicy.ACCEPT
type: str = "hub"
def startup(self) -> None: def startup(self) -> None:
""" """
@ -694,7 +692,6 @@ class WlanNode(CoreNetwork):
apitype: NodeTypes = NodeTypes.WIRELESS_LAN apitype: NodeTypes = NodeTypes.WIRELESS_LAN
linktype: LinkTypes = LinkTypes.WIRED linktype: LinkTypes = LinkTypes.WIRED
policy: NetworkPolicy = NetworkPolicy.DROP policy: NetworkPolicy = NetworkPolicy.DROP
type: str = "wlan"
def __init__( def __init__(
self, self,
@ -794,4 +791,3 @@ class TunnelNode(GreTapBridge):
apitype: NodeTypes = NodeTypes.TUNNEL apitype: NodeTypes = NodeTypes.TUNNEL
policy: NetworkPolicy = NetworkPolicy.ACCEPT policy: NetworkPolicy = NetworkPolicy.ACCEPT
type: str = "tunnel"

View file

@ -29,7 +29,6 @@ class Rj45Node(CoreNodeBase):
""" """
apitype: NodeTypes = NodeTypes.RJ45 apitype: NodeTypes = NodeTypes.RJ45
type: str = "rj45"
def __init__( def __init__(
self, self,

View file

@ -4,16 +4,18 @@ sdt.py: Scripted Display Tool (SDT3D) helper
import logging import logging
import socket import socket
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple from pathlib import Path
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, Type
from urllib.parse import urlparse from urllib.parse import urlparse
from core.constants import CORE_CONF_DIR, CORE_DATA_DIR from core.constants import CORE_CONF_DIR
from core.emane.nodes import EmaneNet from core.emane.nodes import EmaneNet
from core.emulator.data import LinkData, NodeData from core.emulator.data import LinkData, NodeData
from core.emulator.enumerations import EventTypes, MessageFlags from core.emulator.enumerations import EventTypes, MessageFlags
from core.errors import CoreError from core.errors import CoreError
from core.nodes.base import NodeBase from core.nodes.base import CoreNode, NodeBase
from core.nodes.network import WlanNode from core.nodes.network import HubNode, SwitchNode, TunnelNode, WlanNode
from core.nodes.physical import Rj45Node
from core.nodes.wireless import WirelessNode from core.nodes.wireless import WirelessNode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -21,12 +23,22 @@ logger = logging.getLogger(__name__)
if TYPE_CHECKING: if TYPE_CHECKING:
from core.emulator.session import Session from core.emulator.session import Session
LOCAL_ICONS_PATH: Path = Path(__file__).parent.parent / "gui" / "data" / "icons"
CORE_LAYER: str = "CORE" CORE_LAYER: str = "CORE"
NODE_LAYER: str = "CORE::Nodes" NODE_LAYER: str = "CORE::Nodes"
LINK_LAYER: str = "CORE::Links" LINK_LAYER: str = "CORE::Links"
WIRED_LINK_LAYER: str = f"{LINK_LAYER}::wired" WIRED_LINK_LAYER: str = f"{LINK_LAYER}::wired"
CORE_LAYERS: List[str] = [CORE_LAYER, LINK_LAYER, NODE_LAYER, WIRED_LINK_LAYER] CORE_LAYERS: List[str] = [CORE_LAYER, LINK_LAYER, NODE_LAYER, WIRED_LINK_LAYER]
DEFAULT_LINK_COLOR: str = "red" DEFAULT_LINK_COLOR: str = "red"
NODE_TYPES: Dict[Type[NodeBase], str] = {
HubNode: "hub",
SwitchNode: "lanswitch",
TunnelNode: "tunnel",
WlanNode: "wlan",
EmaneNet: "emane",
WirelessNode: "wireless",
Rj45Node: "rj45",
}
def is_wireless(node: NodeBase) -> bool: def is_wireless(node: NodeBase) -> bool:
@ -52,16 +64,18 @@ class Sdt:
DEFAULT_ALT: int = 2500 DEFAULT_ALT: int = 2500
# TODO: read in user"s nodes.conf here; below are default node types from the GUI # TODO: read in user"s nodes.conf here; below are default node types from the GUI
DEFAULT_SPRITES: Dict[str, str] = [ DEFAULT_SPRITES: Dict[str, str] = [
("router", "router.gif"), ("router", "router.png"),
("host", "host.gif"), ("host", "host.png"),
("PC", "pc.gif"), ("PC", "pc.png"),
("mdr", "mdr.gif"), ("mdr", "mdr.png"),
("prouter", "router_green.gif"), ("prouter", "prouter.png"),
("hub", "hub.gif"), ("hub", "hub.png"),
("lanswitch", "lanswitch.gif"), ("lanswitch", "lanswitch.png"),
("wlan", "wlan.gif"), ("wlan", "wlan.png"),
("rj45", "rj45.gif"), ("emane", "emane.png"),
("tunnel", "tunnel.gif"), ("wireless", "wireless.png"),
("rj45", "rj45.png"),
("tunnel", "tunnel.png"),
] ]
def __init__(self, session: "Session") -> None: def __init__(self, session: "Session") -> None:
@ -144,7 +158,7 @@ class Sdt:
:return: initialize command status :return: initialize command status
""" """
if not self.cmd(f'path "{CORE_DATA_DIR}/icons/normal"'): if not self.cmd(f'path "{LOCAL_ICONS_PATH.absolute()}"'):
return False return False
# send node type to icon mappings # send node type to icon mappings
for node_type, icon in self.DEFAULT_SPRITES: for node_type, icon in self.DEFAULT_SPRITES:
@ -166,7 +180,6 @@ class Sdt:
logger.error("error closing socket") logger.error("error closing socket")
finally: finally:
self.sock = None self.sock = None
self.connected = False self.connected = False
def shutdown(self) -> None: def shutdown(self) -> None:
@ -194,7 +207,6 @@ class Sdt:
""" """
if self.sock is None: if self.sock is None:
return False return False
try: try:
cmd = f"{cmdstr}\n".encode() cmd = f"{cmdstr}\n".encode()
logger.debug("sdt cmd: %s", cmd) logger.debug("sdt cmd: %s", cmd)
@ -259,13 +271,14 @@ class Sdt:
pos = self.get_node_position(node) pos = self.get_node_position(node)
if not pos: if not pos:
return return
node_type = node.type if isinstance(node, CoreNode):
if node_type is None: node_type = node.model
node_type = type(node).type else:
node_type = NODE_TYPES.get(type(node), "PC")
icon = node.icon icon = node.icon
if icon: if icon:
node_type = node.name node_type = node.name
icon = icon.replace("$CORE_DATA_DIR", str(CORE_DATA_DIR)) icon = icon.replace("$CORE_DATA_DIR", str(LOCAL_ICONS_PATH.absolute()))
icon = icon.replace("$CORE_CONF_DIR", str(CORE_CONF_DIR)) icon = icon.replace("$CORE_CONF_DIR", str(CORE_CONF_DIR))
self.cmd(f"sprite {node_type} image {icon}") self.cmd(f"sprite {node_type} image {icon}")
self.cmd( self.cmd(

View file

@ -234,26 +234,6 @@ class CoreServices:
""" """
self.custom_services.clear() self.custom_services.clear()
def get_default_services(self, node_type: str) -> List[Type["CoreService"]]:
"""
Get the list of default services that should be enabled for a
node for the given node type.
:param node_type: node type to get default services for
:return: default services
"""
logger.debug("getting default services for type: %s", node_type)
results = []
defaults = self.default_services.get(node_type, [])
for name in defaults:
logger.debug("checking for service with service manager: %s", name)
service = ServiceManager.get(name)
if not service:
logger.warning("default service %s is unknown", name)
else:
results.append(service)
return results
def get_service( def get_service(
self, node_id: int, service_name: str, default_service: bool = False self, node_id: int, service_name: str, default_service: bool = False
) -> "CoreService": ) -> "CoreService":
@ -293,21 +273,21 @@ class CoreServices:
node_services[service.name] = service node_services[service.name] = service
def add_services( def add_services(
self, node: CoreNode, node_type: str, services: List[str] = None self, node: CoreNode, model: str, services: List[str] = None
) -> None: ) -> None:
""" """
Add services to a node. Add services to a node.
:param node: node to add services to :param node: node to add services to
:param node_type: node type to add services to :param model: node model type to add services for
:param services: names of services to add to node :param services: names of services to add to node
:return: nothing :return: nothing
""" """
if not services: if not services:
logger.info( logger.info(
"using default services for node(%s) type(%s)", node.name, node_type "using default services for node(%s) type(%s)", node.name, model
) )
services = self.default_services.get(node_type, []) services = self.default_services.get(model, [])
logger.info("setting services for node(%s): %s", node.name, services) logger.info("setting services for node(%s): %s", node.name, services)
for service_name in services: for service_name in services:
service = self.get_service(node.id, service_name, default_service=True) service = self.get_service(node.id, service_name, default_service=True)

View file

@ -211,7 +211,7 @@ class ServiceElement:
class DeviceElement(NodeElement): class DeviceElement(NodeElement):
def __init__(self, session: "Session", node: NodeBase) -> None: def __init__(self, session: "Session", node: NodeBase) -> None:
super().__init__(session, node, "device") super().__init__(session, node, "device")
add_attribute(self.element, "type", node.type) add_attribute(self.element, "type", node.model)
self.add_class() self.add_class()
self.add_services() self.add_services()
@ -434,15 +434,14 @@ class CoreXmlWriter:
self.scenario.append(service_configurations) self.scenario.append(service_configurations)
def write_default_services(self) -> None: def write_default_services(self) -> None:
node_types = etree.Element("default_services") models = etree.Element("default_services")
for node_type in self.session.services.default_services: for model in self.session.services.default_services:
services = self.session.services.default_services[node_type] services = self.session.services.default_services[model]
node_type = etree.SubElement(node_types, "node", type=node_type) model = etree.SubElement(models, "node", type=model)
for service in services: for service in services:
etree.SubElement(node_type, "service", name=service) etree.SubElement(model, "service", name=service)
if models.getchildren():
if node_types.getchildren(): self.scenario.append(models)
self.scenario.append(node_types)
def write_nodes(self) -> None: def write_nodes(self) -> None:
for node_id in self.session.nodes: for node_id in self.session.nodes:
@ -586,14 +585,12 @@ class CoreXmlReader:
return return
for node in default_services.iterchildren(): for node in default_services.iterchildren():
node_type = node.get("type") model = node.get("type")
services = [] services = []
for service in node.iterchildren(): for service in node.iterchildren():
services.append(service.get("name")) services.append(service.get("name"))
logger.info( logger.info("reading default services for nodes(%s): %s", model, services)
"reading default services for nodes(%s): %s", node_type, services self.session.services.default_services[model] = services
)
self.session.services.default_services[node_type] = services
def read_session_metadata(self) -> None: def read_session_metadata(self) -> None:
session_metadata = self.scenario.find("session_metadata") session_metadata = self.scenario.find("session_metadata")

View file

@ -37,7 +37,7 @@ message ServiceAction {
} }
message ServiceDefaults { message ServiceDefaults {
string node_type = 1; string model = 1;
repeated string services = 2; repeated string services = 2;
} }

View file

@ -641,16 +641,16 @@ class TestGrpc:
# given # given
client = CoreGrpcClient() client = CoreGrpcClient()
session = grpc_server.coreemu.create_session() session = grpc_server.coreemu.create_session()
node_type = "test" model = "test"
services = ["SSH"] services = ["SSH"]
# then # then
with client.context_connect(): with client.context_connect():
result = client.set_service_defaults(session.id, {node_type: services}) result = client.set_service_defaults(session.id, {model: services})
# then # then
assert result is True assert result is True
assert session.services.default_services[node_type] == services assert session.services.default_services[model] == services
def test_get_node_service(self, grpc_server: CoreGrpcServer): def test_get_node_service(self, grpc_server: CoreGrpcServer):
# given # given

View file

@ -53,7 +53,7 @@ class TestServices:
total_service = len(node.services) total_service = len(node.services)
# when # when
session.services.add_services(node, node.type, [SERVICE_ONE, SERVICE_TWO]) session.services.add_services(node, node.model, [SERVICE_ONE, SERVICE_TWO])
# then # then
assert node.services assert node.services