diff --git a/daemon/core/api/grpc/events.py b/daemon/core/api/grpc/events.py index 172cec82..0bab096b 100644 --- a/daemon/core/api/grpc/events.py +++ b/daemon/core/api/grpc/events.py @@ -80,14 +80,14 @@ def handle_link_event(event: LinkData) -> core_pb2.LinkEvent: unidirectional=event.unidirectional, ) link = core_pb2.Link( - type=event.link_type, + type=event.link_type.value, node_one_id=event.node1_id, node_two_id=event.node2_id, interface_one=interface_one, interface_two=interface_two, options=options, ) - return core_pb2.LinkEvent(message_type=event.message_type, link=link) + return core_pb2.LinkEvent(message_type=event.message_type.value, link=link) def handle_session_event(event: EventData) -> core_pb2.SessionEvent: @@ -102,7 +102,7 @@ def handle_session_event(event: EventData) -> core_pb2.SessionEvent: event_time = float(event_time) return core_pb2.SessionEvent( node_id=event.node, - event=event.event_type, + event=event.event_type.value, name=event.name, data=event.data, time=event_time, @@ -158,7 +158,7 @@ def handle_file_event(event: FileData) -> core_pb2.FileEvent: :return: file event """ return core_pb2.FileEvent( - message_type=event.message_type, + message_type=event.message_type.value, node_id=event.node, name=event.name, mode=event.mode, diff --git a/daemon/core/api/grpc/grpcutils.py b/daemon/core/api/grpc/grpcutils.py index 4ee492b9..77813b34 100644 --- a/daemon/core/api/grpc/grpcutils.py +++ b/daemon/core/api/grpc/grpcutils.py @@ -26,11 +26,7 @@ def add_node_data(node_proto: core_pb2.Node) -> Tuple[NodeTypes, int, NodeOption :return: node type, id, and options """ _id = node_proto.id - _type = node_proto.type - if _type is None: - _type = NodeTypes.DEFAULT.value - _type = NodeTypes(_type) - + _type = NodeTypes(node_proto.type) options = NodeOptions(name=node_proto.name, model=node_proto.model) options.icon = node_proto.icon options.opaque = node_proto.opaque @@ -233,7 +229,7 @@ def get_links(session: Session, node: NodeBase): :return: [core.api.grpc.core_pb2.Link] """ links = [] - for link_data in node.all_link_data(0): + for link_data in node.all_link_data(): link = convert_link(session, link_data) links.append(link) return links @@ -325,7 +321,7 @@ def convert_link(session: Session, link_data: LinkData) -> core_pb2.Link: ) return core_pb2.Link( - type=link_data.link_type, + type=link_data.link_type.value, node_one_id=link_data.node1_id, node_two_id=link_data.node2_id, interface_one=interface_one, diff --git a/daemon/core/api/grpc/server.py b/daemon/core/api/grpc/server.py index 69fc0c48..cabc0f1c 100644 --- a/daemon/core/api/grpc/server.py +++ b/daemon/core/api/grpc/server.py @@ -173,7 +173,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): # add all hooks for hook in request.hooks: - session.add_hook(hook.state, hook.file, None, hook.data) + state = EventTypes(hook.state) + session.add_hook(state, hook.file, None, hook.data) # create nodes _, exceptions = grpcutils.create_nodes(session, request.nodes) @@ -279,7 +280,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): session.location.setrefgeo(47.57917, -122.13232, 2.0) session.location.refscale = 150000.0 return core_pb2.CreateSessionResponse( - session_id=session.id, state=session.state + session_id=session.id, state=session.state.value ) def DeleteSession( @@ -312,7 +313,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): session = self.coreemu.sessions[session_id] session_summary = core_pb2.SessionSummary( id=session_id, - state=session.state, + state=session.state.value, nodes=session.get_node_count(), file=session.file_name, ) @@ -521,7 +522,9 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): node_links = get_links(session, node) links.extend(node_links) - session_proto = core_pb2.Session(state=session.state, nodes=nodes, links=links) + session_proto = core_pb2.Session( + state=session.state.value, nodes=nodes, links=links + ) return core_pb2.GetSessionResponse(session=session_proto) def AddSessionServer( @@ -718,7 +721,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): if request.source: source = request.source if not has_geo: - node_data = node.data(0, source=source) + node_data = node.data(source=source) session.broadcast_node(node_data) except CoreError: result = False @@ -895,7 +898,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): for state in session._hooks: state_hooks = session._hooks[state] for file_name, file_data in state_hooks: - hook = core_pb2.Hook(state=state, file=file_name, data=file_data) + hook = core_pb2.Hook(state=state.value, file=file_name, data=file_data) hooks.append(hook) return core_pb2.GetHooksResponse(hooks=hooks) @@ -912,7 +915,8 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): logging.debug("add hook: %s", request) session = self.get_session(request.session_id, context) hook = request.hook - session.add_hook(hook.state, hook.file, None, hook.data) + state = EventTypes(hook.state) + session.add_hook(state, hook.file, None, hook.data) return core_pb2.AddHookResponse(result=True) def GetMobilityConfigs( @@ -1266,7 +1270,7 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): session.mobility.set_model_config( wlan_config.node_id, BasicRangeModel.name, wlan_config.config ) - if session.state == EventTypes.RUNTIME_STATE.value: + if session.state == EventTypes.RUNTIME_STATE: node = self.get_node(session, wlan_config.node_id, context) node.updatemodel(wlan_config.config) return core_pb2.SetWlanConfigResponse(result=True) @@ -1491,12 +1495,12 @@ class CoreGrpcServer(core_pb2_grpc.CoreApiServicer): if emane_one.id == emane_two.id: if request.linked: - flag = MessageFlags.ADD.value + flag = MessageFlags.ADD else: - flag = MessageFlags.DELETE.value + flag = MessageFlags.DELETE link = LinkData( message_type=flag, - link_type=LinkTypes.WIRELESS.value, + link_type=LinkTypes.WIRELESS, node1_id=node_one.id, node2_id=node_two.id, network_id=emane_one.id, diff --git a/daemon/core/api/tlv/coreapi.py b/daemon/core/api/tlv/coreapi.py index b72c186b..b8021b9f 100644 --- a/daemon/core/api/tlv/coreapi.py +++ b/daemon/core/api/tlv/coreapi.py @@ -13,7 +13,7 @@ from enum import Enum import netaddr from core.api.tlv import structutils -from core.emulator.enumerations import ( +from core.api.tlv.enumerations import ( ConfigTlvs, EventTlvs, ExceptionTlvs, @@ -21,12 +21,11 @@ from core.emulator.enumerations import ( FileTlvs, InterfaceTlvs, LinkTlvs, - MessageFlags, MessageTypes, NodeTlvs, - RegisterTlvs, SessionTlvs, ) +from core.emulator.enumerations import MessageFlags, RegisterTlvs class CoreTlvData: diff --git a/daemon/core/api/tlv/corehandlers.py b/daemon/core/api/tlv/corehandlers.py index 1f3b24e9..da2d730d 100644 --- a/daemon/core/api/tlv/corehandlers.py +++ b/daemon/core/api/tlv/corehandlers.py @@ -15,26 +15,28 @@ from queue import Empty, Queue from core import utils from core.api.tlv import coreapi, dataconversion, structutils -from core.config import ConfigShim -from core.emulator.data import ConfigData, EventData, ExceptionData, FileData -from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions -from core.emulator.enumerations import ( - ConfigDataTypes, +from core.api.tlv.dataconversion import ConfigShim +from core.api.tlv.enumerations import ( ConfigFlags, ConfigTlvs, EventTlvs, - EventTypes, ExceptionTlvs, ExecuteTlvs, FileTlvs, LinkTlvs, - LinkTypes, - MessageFlags, MessageTypes, NodeTlvs, + SessionTlvs, +) +from core.emulator.data import ConfigData, EventData, ExceptionData, FileData +from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions +from core.emulator.enumerations import ( + ConfigDataTypes, + EventTypes, + LinkTypes, + MessageFlags, NodeTypes, RegisterTlvs, - SessionTlvs, ) from core.errors import CoreCommandError, CoreError from core.location.mobility import BasicRangeModel @@ -228,7 +230,7 @@ class CoreHandler(socketserver.BaseRequestHandler): coreapi.CoreEventTlv, [ (EventTlvs.NODE, event_data.node), - (EventTlvs.TYPE, event_data.event_type), + (EventTlvs.TYPE, event_data.event_type.value), (EventTlvs.NAME, event_data.name), (EventTlvs.DATA, event_data.data), (EventTlvs.TIME, event_data.time), @@ -265,7 +267,7 @@ class CoreHandler(socketserver.BaseRequestHandler): (FileTlvs.COMPRESSED_DATA, file_data.compressed_data), ], ) - message = coreapi.CoreFileMessage.pack(file_data.message_type, tlv_data) + message = coreapi.CoreFileMessage.pack(file_data.message_type.value, tlv_data) try: self.sendall(message) @@ -356,7 +358,7 @@ class CoreHandler(socketserver.BaseRequestHandler): (LinkTlvs.BURST, link_data.burst), (LinkTlvs.SESSION, link_data.session), (LinkTlvs.MBURST, link_data.mburst), - (LinkTlvs.TYPE, link_data.link_type), + (LinkTlvs.TYPE, link_data.link_type.value), (LinkTlvs.GUI_ATTRIBUTES, link_data.gui_attributes), (LinkTlvs.UNIDIRECTIONAL, link_data.unidirectional), (LinkTlvs.EMULATION_ID, link_data.emulation_id), @@ -380,7 +382,7 @@ class CoreHandler(socketserver.BaseRequestHandler): ], ) - message = coreapi.CoreLinkMessage.pack(link_data.message_type, tlv_data) + message = coreapi.CoreLinkMessage.pack(link_data.message_type.value, tlv_data) try: self.sendall(message) @@ -396,7 +398,6 @@ class CoreHandler(socketserver.BaseRequestHandler): logging.info( "GUI has connected to session %d at %s", self.session.id, time.ctime() ) - tlv_data = b"" tlv_data += coreapi.CoreRegisterTlv.pack( RegisterTlvs.EXECUTE_SERVER.value, "core-daemon" @@ -406,29 +407,29 @@ class CoreHandler(socketserver.BaseRequestHandler): ) tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.UTILITY.value, "broker") tlv_data += coreapi.CoreRegisterTlv.pack( - self.session.location.config_type, self.session.location.name + self.session.location.config_type.value, self.session.location.name ) tlv_data += coreapi.CoreRegisterTlv.pack( - self.session.mobility.config_type, self.session.mobility.name + self.session.mobility.config_type.value, self.session.mobility.name ) for model_name in self.session.mobility.models: model_class = self.session.mobility.models[model_name] tlv_data += coreapi.CoreRegisterTlv.pack( - model_class.config_type, model_class.name + model_class.config_type.value, model_class.name ) tlv_data += coreapi.CoreRegisterTlv.pack( - self.session.services.config_type, self.session.services.name + self.session.services.config_type.value, self.session.services.name ) tlv_data += coreapi.CoreRegisterTlv.pack( - self.session.emane.config_type, self.session.emane.name + self.session.emane.config_type.value, self.session.emane.name ) for model_name in self.session.emane.models: model_class = self.session.emane.models[model_name] tlv_data += coreapi.CoreRegisterTlv.pack( - model_class.config_type, model_class.name + model_class.config_type.value, model_class.name ) tlv_data += coreapi.CoreRegisterTlv.pack( - self.session.options.config_type, self.session.options.name + self.session.options.config_type.value, self.session.options.name ) tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.UTILITY.value, "metadata") @@ -723,7 +724,7 @@ class CoreHandler(socketserver.BaseRequestHandler): if message.flags & MessageFlags.STRING.value: self.node_status_request[node.id] = True - if self.session.state == EventTypes.RUNTIME_STATE.value: + if self.session.state == EventTypes.RUNTIME_STATE: self.send_node_emulation_id(node.id) elif message.flags & MessageFlags.DELETE.value: with self._shutdown_lock: @@ -966,7 +967,7 @@ class CoreHandler(socketserver.BaseRequestHandler): retries = 10 # wait for session to enter RUNTIME state, to prevent GUI from # connecting while nodes are still being instantiated - while session.state != EventTypes.RUNTIME_STATE.value: + while session.state != EventTypes.RUNTIME_STATE: logging.debug( "waiting for session %d to enter RUNTIME state", sid ) @@ -1375,7 +1376,7 @@ class CoreHandler(socketserver.BaseRequestHandler): parsed_config = ConfigShim.str_to_dict(values_str) self.session.mobility.set_model_config(node_id, object_name, parsed_config) - if self.session.state == EventTypes.RUNTIME_STATE.value and parsed_config: + if self.session.state == EventTypes.RUNTIME_STATE and parsed_config: try: node = self.session.get_node(node_id) if object_name == BasicRangeModel.name: @@ -1502,6 +1503,7 @@ class CoreHandler(socketserver.BaseRequestHandler): logging.error("error setting hook having state '%s'", state) return () state = int(state) + state = EventTypes(state) self.session.add_hook(state, file_name, source_name, data) return () @@ -1538,9 +1540,11 @@ class CoreHandler(socketserver.BaseRequestHandler): :return: reply messages :raises core.CoreError: when event type <= SHUTDOWN_STATE and not a known node id """ + event_type_value = message.get_tlv(EventTlvs.TYPE.value) + event_type = EventTypes(event_type_value) event_data = EventData( node=message.get_tlv(EventTlvs.NODE.value), - event_type=message.get_tlv(EventTlvs.TYPE.value), + event_type=event_type, name=message.get_tlv(EventTlvs.NAME.value), data=message.get_tlv(EventTlvs.DATA.value), time=message.get_tlv(EventTlvs.TIME.value), @@ -1549,7 +1553,6 @@ class CoreHandler(socketserver.BaseRequestHandler): if event_data.event_type is None: raise NotImplementedError("Event message missing event type") - event_type = EventTypes(event_data.event_type) node_id = event_data.node logging.debug("handling event %s at %s", event_type.name, time.ctime()) @@ -1667,25 +1670,19 @@ class CoreHandler(socketserver.BaseRequestHandler): unknown.append(service_name) continue - if ( - event_type == EventTypes.STOP.value - or event_type == EventTypes.RESTART.value - ): + if event_type in [EventTypes.STOP, EventTypes.RESTART]: status = self.session.services.stop_service(node, service) if status: fail += f"Stop {service.name}," - if ( - event_type == EventTypes.START.value - or event_type == EventTypes.RESTART.value - ): + if event_type in [EventTypes.START, EventTypes.RESTART]: status = self.session.services.startup_service(node, service) if status: fail += f"Start ({service.name})," - if event_type == EventTypes.PAUSE.value: + if event_type == EventTypes.PAUSE: status = self.session.services.validate_service(node, service) if status: fail += f"{service.name}," - if event_type == EventTypes.RECONFIGURE.value: + if event_type == EventTypes.RECONFIGURE: self.session.services.service_reconfigure(node, service) fail_data = "" @@ -1845,11 +1842,11 @@ class CoreHandler(socketserver.BaseRequestHandler): with self.session._nodes_lock: for node_id in self.session.nodes: node = self.session.nodes[node_id] - node_data = node.data(message_type=MessageFlags.ADD.value) + node_data = node.data(message_type=MessageFlags.ADD) if node_data: nodes_data.append(node_data) - node_links = node.all_link_data(flags=MessageFlags.ADD.value) + node_links = node.all_link_data(flags=MessageFlags.ADD) for link_data in node_links: links_data.append(link_data) @@ -1917,7 +1914,7 @@ class CoreHandler(socketserver.BaseRequestHandler): for file_name, config_data in self.session.services.all_files(service): file_data = FileData( - message_type=MessageFlags.ADD.value, + message_type=MessageFlags.ADD, node=node_id, name=str(file_name), type=opaque, @@ -1931,7 +1928,7 @@ class CoreHandler(socketserver.BaseRequestHandler): for state in sorted(self.session._hooks.keys()): for file_name, config_data in self.session._hooks[state]: file_data = FileData( - message_type=MessageFlags.ADD.value, + message_type=MessageFlags.ADD, name=str(file_name), type=f"hook:{state}", data=str(config_data), @@ -2052,7 +2049,7 @@ class CoreUdpHandler(CoreHandler): current_session = self.server.mainserver.coreemu.sessions[session_id] current_node_count = current_session.get_node_count() if ( - current_session.state == EventTypes.RUNTIME_STATE.value + current_session.state == EventTypes.RUNTIME_STATE and current_node_count > node_count ): node_count = current_node_count diff --git a/daemon/core/api/tlv/dataconversion.py b/daemon/core/api/tlv/dataconversion.py index 8d47613d..21730afb 100644 --- a/daemon/core/api/tlv/dataconversion.py +++ b/daemon/core/api/tlv/dataconversion.py @@ -1,9 +1,14 @@ """ Converts CORE data objects into legacy API messages. """ +import logging +from collections import OrderedDict +from typing import Dict, List from core.api.tlv import coreapi, structutils -from core.emulator.enumerations import ConfigTlvs, NodeTlvs +from core.api.tlv.enumerations import ConfigTlvs, NodeTlvs +from core.config import ConfigGroup, ConfigurableOptions +from core.emulator.data import ConfigData def convert_node(node_data): @@ -17,7 +22,7 @@ def convert_node(node_data): coreapi.CoreNodeTlv, [ (NodeTlvs.NUMBER, node_data.id), - (NodeTlvs.TYPE, node_data.node_type), + (NodeTlvs.TYPE, node_data.node_type.value), (NodeTlvs.NAME, node_data.name), (NodeTlvs.IP_ADDRESS, node_data.ip_address), (NodeTlvs.MAC_ADDRESS, node_data.mac_address), @@ -38,7 +43,7 @@ def convert_node(node_data): (NodeTlvs.OPAQUE, node_data.opaque), ], ) - return coreapi.CoreNodeMessage.pack(node_data.message_type, tlv_data) + return coreapi.CoreNodeMessage.pack(node_data.message_type.value, tlv_data) def convert_config(config_data): @@ -67,3 +72,102 @@ def convert_config(config_data): ], ) return coreapi.CoreConfMessage.pack(config_data.message_type, tlv_data) + + +class ConfigShim: + """ + Provides helper methods for converting newer configuration values into TLV + compatible formats. + """ + + @classmethod + def str_to_dict(cls, key_values: str) -> Dict[str, str]: + """ + Converts a TLV key/value string into an ordered mapping. + + :param key_values: + :return: ordered mapping of key/value pairs + """ + key_values = key_values.split("|") + values = OrderedDict() + for key_value in key_values: + key, value = key_value.split("=", 1) + values[key] = value + return values + + @classmethod + def groups_to_str(cls, config_groups: List[ConfigGroup]) -> str: + """ + Converts configuration groups to a TLV formatted string. + + :param config_groups: configuration groups to format + :return: TLV configuration group string + """ + group_strings = [] + for config_group in config_groups: + group_string = ( + f"{config_group.name}:{config_group.start}-{config_group.stop}" + ) + group_strings.append(group_string) + return "|".join(group_strings) + + @classmethod + def config_data( + cls, + flags: int, + node_id: int, + type_flags: int, + configurable_options: ConfigurableOptions, + config: Dict[str, str], + ) -> ConfigData: + """ + Convert this class to a Config API message. Some TLVs are defined + by the class, but node number, conf type flags, and values must + be passed in. + + :param flags: message flags + :param node_id: node id + :param type_flags: type flags + :param configurable_options: options to create config data for + :param config: configuration values for options + :return: configuration data object + """ + key_values = None + captions = None + data_types = [] + possible_values = [] + logging.debug("configurable: %s", configurable_options) + logging.debug("configuration options: %s", configurable_options.configurations) + logging.debug("configuration data: %s", config) + for configuration in configurable_options.configurations(): + if not captions: + captions = configuration.label + else: + captions += f"|{configuration.label}" + + data_types.append(configuration.type.value) + + options = ",".join(configuration.options) + possible_values.append(options) + + _id = configuration.id + config_value = config.get(_id, configuration.default) + key_value = f"{_id}={config_value}" + if not key_values: + key_values = key_value + else: + key_values += f"|{key_value}" + + groups_str = cls.groups_to_str(configurable_options.config_groups()) + return ConfigData( + message_type=flags, + node=node_id, + object=configurable_options.name, + type=type_flags, + data_types=tuple(data_types), + data_values=key_values, + captions=captions, + possible_values="|".join(possible_values), + bitmap=configurable_options.bitmap, + groups=groups_str, + ) diff --git a/daemon/core/api/tlv/enumerations.py b/daemon/core/api/tlv/enumerations.py new file mode 100644 index 00000000..ed06bbe7 --- /dev/null +++ b/daemon/core/api/tlv/enumerations.py @@ -0,0 +1,212 @@ +""" +Enumerations specific to the CORE TLV API. +""" +from enum import Enum + +CORE_API_PORT = 4038 + + +class MessageTypes(Enum): + """ + CORE message types. + """ + + NODE = 0x01 + LINK = 0x02 + EXECUTE = 0x03 + REGISTER = 0x04 + CONFIG = 0x05 + FILE = 0x06 + INTERFACE = 0x07 + EVENT = 0x08 + SESSION = 0x09 + EXCEPTION = 0x0A + + +class NodeTlvs(Enum): + """ + Node type, length, value enumerations. + """ + + NUMBER = 0x01 + TYPE = 0x02 + NAME = 0x03 + IP_ADDRESS = 0x04 + MAC_ADDRESS = 0x05 + IP6_ADDRESS = 0x06 + MODEL = 0x07 + EMULATION_SERVER = 0x08 + SESSION = 0x0A + X_POSITION = 0x20 + Y_POSITION = 0x21 + CANVAS = 0x22 + EMULATION_ID = 0x23 + NETWORK_ID = 0x24 + SERVICES = 0x25 + LATITUDE = 0x30 + LONGITUDE = 0x31 + ALTITUDE = 0x32 + ICON = 0x42 + OPAQUE = 0x50 + + +class LinkTlvs(Enum): + """ + Link type, length, value enumerations. + """ + + N1_NUMBER = 0x01 + N2_NUMBER = 0x02 + DELAY = 0x03 + BANDWIDTH = 0x04 + PER = 0x05 + DUP = 0x06 + JITTER = 0x07 + MER = 0x08 + BURST = 0x09 + SESSION = 0x0A + MBURST = 0x10 + TYPE = 0x20 + GUI_ATTRIBUTES = 0x21 + UNIDIRECTIONAL = 0x22 + EMULATION_ID = 0x23 + NETWORK_ID = 0x24 + KEY = 0x25 + INTERFACE1_NUMBER = 0x30 + INTERFACE1_IP4 = 0x31 + INTERFACE1_IP4_MASK = 0x32 + INTERFACE1_MAC = 0x33 + INTERFACE1_IP6 = 0x34 + INTERFACE1_IP6_MASK = 0x35 + INTERFACE2_NUMBER = 0x36 + INTERFACE2_IP4 = 0x37 + INTERFACE2_IP4_MASK = 0x38 + INTERFACE2_MAC = 0x39 + INTERFACE2_IP6 = 0x40 + INTERFACE2_IP6_MASK = 0x41 + INTERFACE1_NAME = 0x42 + INTERFACE2_NAME = 0x43 + OPAQUE = 0x50 + + +class ExecuteTlvs(Enum): + """ + Execute type, length, value enumerations. + """ + + NODE = 0x01 + NUMBER = 0x02 + TIME = 0x03 + COMMAND = 0x04 + RESULT = 0x05 + STATUS = 0x06 + SESSION = 0x0A + + +class ConfigTlvs(Enum): + """ + Configuration type, length, value enumerations. + """ + + NODE = 0x01 + OBJECT = 0x02 + TYPE = 0x03 + DATA_TYPES = 0x04 + VALUES = 0x05 + CAPTIONS = 0x06 + BITMAP = 0x07 + POSSIBLE_VALUES = 0x08 + GROUPS = 0x09 + SESSION = 0x0A + INTERFACE_NUMBER = 0x0B + NETWORK_ID = 0x24 + OPAQUE = 0x50 + + +class ConfigFlags(Enum): + """ + Configuration flags. + """ + + NONE = 0x00 + REQUEST = 0x01 + UPDATE = 0x02 + RESET = 0x03 + + +class FileTlvs(Enum): + """ + File type, length, value enumerations. + """ + + NODE = 0x01 + NAME = 0x02 + MODE = 0x03 + NUMBER = 0x04 + TYPE = 0x05 + SOURCE_NAME = 0x06 + SESSION = 0x0A + DATA = 0x10 + COMPRESSED_DATA = 0x11 + + +class InterfaceTlvs(Enum): + """ + Interface type, length, value enumerations. + """ + + NODE = 0x01 + NUMBER = 0x02 + NAME = 0x03 + IP_ADDRESS = 0x04 + MASK = 0x05 + MAC_ADDRESS = 0x06 + IP6_ADDRESS = 0x07 + IP6_MASK = 0x08 + TYPE = 0x09 + SESSION = 0x0A + STATE = 0x0B + EMULATION_ID = 0x23 + NETWORK_ID = 0x24 + + +class EventTlvs(Enum): + """ + Event type, length, value enumerations. + """ + + NODE = 0x01 + TYPE = 0x02 + NAME = 0x03 + DATA = 0x04 + TIME = 0x05 + SESSION = 0x0A + + +class SessionTlvs(Enum): + """ + Session type, length, value enumerations. + """ + + NUMBER = 0x01 + NAME = 0x02 + FILE = 0x03 + NODE_COUNT = 0x04 + DATE = 0x05 + THUMB = 0x06 + USER = 0x07 + OPAQUE = 0x0A + + +class ExceptionTlvs(Enum): + """ + Exception type, length, value enumerations. + """ + + NODE = 0x01 + SESSION = 0x02 + LEVEL = 0x03 + SOURCE = 0x04 + DATE = 0x05 + TEXT = 0x06 + OPAQUE = 0x0A diff --git a/daemon/core/config.py b/daemon/core/config.py index b7c20362..1f5bc3c0 100644 --- a/daemon/core/config.py +++ b/daemon/core/config.py @@ -7,7 +7,6 @@ from collections import OrderedDict from typing import TYPE_CHECKING, Dict, List, Tuple, Type, Union from core.emane.nodes import EmaneNet -from core.emulator.data import ConfigData from core.emulator.enumerations import ConfigDataTypes from core.nodes.network import WlanNode @@ -110,104 +109,6 @@ class ConfigurableOptions: ) -class ConfigShim: - """ - Provides helper methods for converting newer configuration values into TLV compatible formats. - """ - - @classmethod - def str_to_dict(cls, key_values: str) -> Dict[str, str]: - """ - Converts a TLV key/value string into an ordered mapping. - - :param key_values: - :return: ordered mapping of key/value pairs - """ - key_values = key_values.split("|") - values = OrderedDict() - for key_value in key_values: - key, value = key_value.split("=", 1) - values[key] = value - return values - - @classmethod - def groups_to_str(cls, config_groups: List[ConfigGroup]) -> str: - """ - Converts configuration groups to a TLV formatted string. - - :param config_groups: configuration groups to format - :return: TLV configuration group string - """ - group_strings = [] - for config_group in config_groups: - group_string = ( - f"{config_group.name}:{config_group.start}-{config_group.stop}" - ) - group_strings.append(group_string) - return "|".join(group_strings) - - @classmethod - def config_data( - cls, - flags: int, - node_id: int, - type_flags: int, - configurable_options: ConfigurableOptions, - config: Dict[str, str], - ) -> ConfigData: - """ - Convert this class to a Config API message. Some TLVs are defined - by the class, but node number, conf type flags, and values must - be passed in. - - :param flags: message flags - :param node_id: node id - :param type_flags: type flags - :param configurable_options: options to create config data for - :param config: configuration values for options - :return: configuration data object - """ - key_values = None - captions = None - data_types = [] - possible_values = [] - logging.debug("configurable: %s", configurable_options) - logging.debug("configuration options: %s", configurable_options.configurations) - logging.debug("configuration data: %s", config) - for configuration in configurable_options.configurations(): - if not captions: - captions = configuration.label - else: - captions += f"|{configuration.label}" - - data_types.append(configuration.type.value) - - options = ",".join(configuration.options) - possible_values.append(options) - - _id = configuration.id - config_value = config.get(_id, configuration.default) - key_value = f"{_id}={config_value}" - if not key_values: - key_values = key_value - else: - key_values += f"|{key_value}" - - groups_str = cls.groups_to_str(configurable_options.config_groups()) - return ConfigData( - message_type=flags, - node=node_id, - object=configurable_options.name, - type=type_flags, - data_types=tuple(data_types), - data_values=key_values, - captions=captions, - possible_values="|".join(possible_values), - bitmap=configurable_options.bitmap, - groups=groups_str, - ) - - class ConfigurableManager: """ Provides convenience methods for storing and retrieving configuration options for diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index ea4a019d..37185c93 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -60,7 +60,7 @@ class EmaneManager(ModelManager): """ name = "emane" - config_type = RegisterTlvs.EMULATION_SERVER.value + config_type = RegisterTlvs.EMULATION_SERVER SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2) EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG" DEFAULT_LOG_LEVEL = 3 @@ -806,7 +806,7 @@ class EmaneManager(ModelManager): # don"t use node.setposition(x,y,z) which generates an event node.position.set(x, y, z) node.position.set_geo(lon, lat, alt) - node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt) + node_data = node.data(lat=lat, lon=lon, alt=alt) self.session.broadcast_node(node_data) return True diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index b44d16b6..d8984f7c 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -33,8 +33,8 @@ class EmaneNet(CoreNetworkBase): Emane controller object that exists in a session. """ - apitype = NodeTypes.EMANE.value - linktype = LinkTypes.WIRED.value + apitype = NodeTypes.EMANE + linktype = LinkTypes.WIRED type = "wlan" is_emane = True @@ -103,12 +103,12 @@ class EmaneNet(CoreNetworkBase): set the EmaneModel associated with this node """ logging.info("adding model: %s", model.name) - if model.config_type == RegisterTlvs.WIRELESS.value: + if model.config_type == RegisterTlvs.WIRELESS: # EmaneModel really uses values from ConfigurableManager # when buildnemxml() is called, not during init() self.model = model(session=self.session, _id=self.id) self.model.update_config(config) - elif model.config_type == RegisterTlvs.MOBILITY.value: + elif model.config_type == RegisterTlvs.MOBILITY: self.mobility = model(session=self.session, _id=self.id) self.mobility.update_config(config) diff --git a/daemon/core/emulator/enumerations.py b/daemon/core/emulator/enumerations.py index f426774e..2c6e14db 100644 --- a/daemon/core/emulator/enumerations.py +++ b/daemon/core/emulator/enumerations.py @@ -1,35 +1,16 @@ """ -Contains all legacy enumerations for interacting with legacy CORE code. +Common enumerations used within CORE. """ from enum import Enum -CORE_API_VERSION = "1.23" -CORE_API_PORT = 4038 - - -class MessageTypes(Enum): - """ - CORE message types. - """ - - NODE = 0x01 - LINK = 0x02 - EXECUTE = 0x03 - REGISTER = 0x04 - CONFIG = 0x05 - FILE = 0x06 - INTERFACE = 0x07 - EVENT = 0x08 - SESSION = 0x09 - EXCEPTION = 0x0A - class MessageFlags(Enum): """ CORE message flags. """ + NONE = 0x00 ADD = 0x01 DELETE = 0x02 CRI = 0x04 @@ -39,33 +20,6 @@ class MessageFlags(Enum): TTY = 0x40 -class NodeTlvs(Enum): - """ - Node type, length, value enumerations. - """ - - NUMBER = 0x01 - TYPE = 0x02 - NAME = 0x03 - IP_ADDRESS = 0x04 - MAC_ADDRESS = 0x05 - IP6_ADDRESS = 0x06 - MODEL = 0x07 - EMULATION_SERVER = 0x08 - SESSION = 0x0A - X_POSITION = 0x20 - Y_POSITION = 0x21 - CANVAS = 0x22 - EMULATION_ID = 0x23 - NETWORK_ID = 0x24 - SERVICES = 0x25 - LATITUDE = 0x30 - LONGITUDE = 0x31 - ALTITUDE = 0x32 - ICON = 0x42 - OPAQUE = 0x50 - - class NodeTypes(Enum): """ Node types. @@ -86,56 +40,6 @@ class NodeTypes(Enum): LXC = 16 -class Rj45Models(Enum): - """ - RJ45 model types. - """ - - LINKED = 0 - WIRELESS = 1 - INSTALLED = 2 - - -# Link Message TLV Types -class LinkTlvs(Enum): - """ - Link type, length, value enumerations. - """ - - N1_NUMBER = 0x01 - N2_NUMBER = 0x02 - DELAY = 0x03 - BANDWIDTH = 0x04 - PER = 0x05 - DUP = 0x06 - JITTER = 0x07 - MER = 0x08 - BURST = 0x09 - SESSION = 0x0A - MBURST = 0x10 - TYPE = 0x20 - GUI_ATTRIBUTES = 0x21 - UNIDIRECTIONAL = 0x22 - EMULATION_ID = 0x23 - NETWORK_ID = 0x24 - KEY = 0x25 - INTERFACE1_NUMBER = 0x30 - INTERFACE1_IP4 = 0x31 - INTERFACE1_IP4_MASK = 0x32 - INTERFACE1_MAC = 0x33 - INTERFACE1_IP6 = 0x34 - INTERFACE1_IP6_MASK = 0x35 - INTERFACE2_NUMBER = 0x36 - INTERFACE2_IP4 = 0x37 - INTERFACE2_IP4_MASK = 0x38 - INTERFACE2_MAC = 0x39 - INTERFACE2_IP6 = 0x40 - INTERFACE2_IP6_MASK = 0x41 - INTERFACE1_NAME = 0x42 - INTERFACE2_NAME = 0x43 - OPAQUE = 0x50 - - class LinkTypes(Enum): """ Link types. @@ -145,20 +49,6 @@ class LinkTypes(Enum): WIRED = 1 -class ExecuteTlvs(Enum): - """ - Execute type, length, value enumerations. - """ - - NODE = 0x01 - NUMBER = 0x02 - TIME = 0x03 - COMMAND = 0x04 - RESULT = 0x05 - STATUS = 0x06 - SESSION = 0x0A - - class RegisterTlvs(Enum): """ Register type, length, value enumerations. @@ -173,37 +63,6 @@ class RegisterTlvs(Enum): SESSION = 0x0A -class ConfigTlvs(Enum): - """ - Configuration type, length, value enumerations. - """ - - NODE = 0x01 - OBJECT = 0x02 - TYPE = 0x03 - DATA_TYPES = 0x04 - VALUES = 0x05 - CAPTIONS = 0x06 - BITMAP = 0x07 - POSSIBLE_VALUES = 0x08 - GROUPS = 0x09 - SESSION = 0x0A - INTERFACE_NUMBER = 0x0B - NETWORK_ID = 0x24 - OPAQUE = 0x50 - - -class ConfigFlags(Enum): - """ - Configuration flags. - """ - - NONE = 0x00 - REQUEST = 0x01 - UPDATE = 0x02 - RESET = 0x03 - - class ConfigDataTypes(Enum): """ Configuration data types. @@ -222,55 +81,6 @@ class ConfigDataTypes(Enum): BOOL = 0x0B -class FileTlvs(Enum): - """ - File type, length, value enumerations. - """ - - NODE = 0x01 - NAME = 0x02 - MODE = 0x03 - NUMBER = 0x04 - TYPE = 0x05 - SOURCE_NAME = 0x06 - SESSION = 0x0A - DATA = 0x10 - COMPRESSED_DATA = 0x11 - - -class InterfaceTlvs(Enum): - """ - Interface type, length, value enumerations. - """ - - NODE = 0x01 - NUMBER = 0x02 - NAME = 0x03 - IP_ADDRESS = 0x04 - MASK = 0x05 - MAC_ADDRESS = 0x06 - IP6_ADDRESS = 0x07 - IP6_MASK = 0x08 - TYPE = 0x09 - SESSION = 0x0A - STATE = 0x0B - EMULATION_ID = 0x23 - NETWORK_ID = 0x24 - - -class EventTlvs(Enum): - """ - Event type, length, value enumerations. - """ - - NODE = 0x01 - TYPE = 0x02 - NAME = 0x03 - DATA = 0x04 - TIME = 0x05 - SESSION = 0x0A - - class EventTypes(Enum): """ Event types. @@ -293,34 +103,8 @@ class EventTypes(Enum): RECONFIGURE = 14 INSTANTIATION_COMPLETE = 15 - -class SessionTlvs(Enum): - """ - Session type, length, value enumerations. - """ - - NUMBER = 0x01 - NAME = 0x02 - FILE = 0x03 - NODE_COUNT = 0x04 - DATE = 0x05 - THUMB = 0x06 - USER = 0x07 - OPAQUE = 0x0A - - -class ExceptionTlvs(Enum): - """ - Exception type, length, value enumerations. - """ - - NODE = 0x01 - SESSION = 0x02 - LEVEL = 0x03 - SOURCE = 0x04 - DATE = 0x05 - TEXT = 0x06 - OPAQUE = 0x0A + def should_start(self) -> bool: + return self.value > self.DEFINITION_STATE.value class ExceptionLevels(Enum): diff --git a/daemon/core/emulator/session.py b/daemon/core/emulator/session.py index 3a02412f..8bc10826 100644 --- a/daemon/core/emulator/session.py +++ b/daemon/core/emulator/session.py @@ -112,8 +112,7 @@ class Session: self.nodes = {} self._nodes_lock = threading.Lock() - # TODO: should the default state be definition? - self.state = EventTypes.NONE.value + self.state = EventTypes.DEFINITION_STATE self._state_time = time.monotonic() self._state_file = os.path.join(self.session_dir, "state") @@ -121,7 +120,7 @@ class Session: self._hooks = {} self._state_hooks = {} self.add_state_hook( - state=EventTypes.RUNTIME_STATE.value, hook=self.runtime_state_hook + state=EventTypes.RUNTIME_STATE, hook=self.runtime_state_hook ) # handlers for broadcasting information @@ -345,7 +344,7 @@ class Session: node_one.name, node_two.name, ) - start = self.state > EventTypes.DEFINITION_STATE.value + start = self.state.should_start() net_one = self.create_node(cls=PtpNet, start=start) # node to network @@ -578,7 +577,7 @@ class Session: try: # wireless link - if link_options.type == LinkTypes.WIRELESS.value: + if link_options.type == LinkTypes.WIRELESS: raise CoreError("cannot update wireless link") else: if not node_one and not node_two: @@ -680,7 +679,7 @@ class Session: node_class = _cls # set node start based on current session state, override and check when rj45 - start = self.state > EventTypes.DEFINITION_STATE.value + start = self.state.should_start() enable_rj45 = self.options.get_config("enablerj45") == "1" if _type == NodeTypes.RJ45 and not enable_rj45: start = False @@ -755,7 +754,7 @@ class Session: # boot nodes after runtime, CoreNodes, Physical, and RJ45 are all nodes is_boot_node = isinstance(node, CoreNodeBase) and not isinstance(node, Rj45Node) - if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node: + if self.state == EventTypes.RUNTIME_STATE and is_boot_node: self.write_nodes() self.add_remove_control_interface(node=node, remove=False) self.services.boot_services(node) @@ -851,10 +850,7 @@ class Session: :return: True if active, False otherwise """ - result = self.state in { - EventTypes.RUNTIME_STATE.value, - EventTypes.DATACOLLECT_STATE.value, - } + result = self.state in {EventTypes.RUNTIME_STATE, EventTypes.DATACOLLECT_STATE} logging.info("session(%s) checking if active: %s", self.id, result) return result @@ -895,7 +891,9 @@ class Session: """ CoreXmlWriter(self).write(file_name) - def add_hook(self, state: int, file_name: str, source_name: str, data: str) -> None: + def add_hook( + self, state: EventTypes, file_name: str, source_name: str, data: str + ) -> None: """ Store a hook from a received file message. @@ -905,9 +903,17 @@ class Session: :param data: hook data :return: nothing """ - # hack to conform with old logic until updated - state = f":{state}" - self.set_hook(state, file_name, source_name, data) + logging.info( + "setting state hook: %s - %s from %s", state, file_name, source_name + ) + hook = file_name, data + state_hooks = self._hooks.setdefault(state, []) + state_hooks.append(hook) + + # immediately run a hook if it is in the current state + if self.state == state: + logging.info("immediately running new state hook") + self.run_hook(hook) def add_node_file( self, node_id: int, source_name: str, file_name: str, data: str @@ -1072,10 +1078,8 @@ class Session: :param send_event: if true, generate core API event messages :return: nothing """ - state_value = state.value state_name = state.name - - if self.state == state_value: + if self.state == state: logging.info( "session(%s) is already in state: %s, skipping change", self.id, @@ -1083,33 +1087,32 @@ class Session: ) return - self.state = state_value + self.state = state self._state_time = time.monotonic() logging.info("changing session(%s) to state %s", self.id, state_name) - - self.write_state(state_value) - self.run_hooks(state_value) - self.run_state_hooks(state_value) + self.write_state(state) + self.run_hooks(state) + self.run_state_hooks(state) if send_event: - event_data = EventData(event_type=state_value, time=str(time.monotonic())) + event_data = EventData(event_type=state, time=str(time.monotonic())) self.broadcast_event(event_data) - def write_state(self, state: int) -> None: + def write_state(self, state: EventTypes) -> None: """ - Write the current state to a state file in the session dir. + Write the state to a state file in the session dir. :param state: state to write to file :return: nothing """ try: state_file = open(self._state_file, "w") - state_file.write(f"{state} {EventTypes(self.state).name}\n") + state_file.write(f"{state.value} {state.name}\n") state_file.close() except IOError: - logging.exception("error writing state file: %s", state) + logging.exception("error writing state file: %s", state.name) - def run_hooks(self, state: int) -> None: + def run_hooks(self, state: EventTypes) -> None: """ Run hook scripts upon changing states. If hooks is not specified, run all hooks in the given state. @@ -1213,7 +1216,7 @@ class Session: except (OSError, subprocess.CalledProcessError): logging.exception("error running hook: %s", file_name) - def run_state_hooks(self, state: int) -> None: + def run_state_hooks(self, state: EventTypes) -> None: """ Run state hooks. @@ -1224,16 +1227,17 @@ class Session: try: hook(state) except Exception: - state_name = EventTypes(self.state).name message = ( - f"exception occured when running {state_name} state hook: {hook}" + f"exception occured when running {state.name} state hook: {hook}" ) logging.exception(message) self.exception( ExceptionLevels.ERROR, "Session.run_state_hooks", None, message ) - def add_state_hook(self, state: int, hook: Callable[[int], None]) -> None: + def add_state_hook( + self, state: EventTypes, hook: Callable[[EventTypes], None] + ) -> None: """ Add a state hook. @@ -1260,14 +1264,14 @@ class Session: hooks = self._state_hooks.setdefault(state, []) hooks.remove(hook) - def runtime_state_hook(self, state: int) -> None: + def runtime_state_hook(self, state: EventTypes) -> None: """ Runtime state hook check. :param state: state to check :return: nothing """ - if state == EventTypes.RUNTIME_STATE.value: + if state == EventTypes.RUNTIME_STATE: self.emane.poststartup() # create session deployed xml @@ -1511,7 +1515,7 @@ class Session: self.mobility.startup() # notify listeners that instantiation is complete - event = EventData(event_type=EventTypes.INSTANTIATION_COMPLETE.value) + event = EventData(event_type=EventTypes.INSTANTIATION_COMPLETE) self.broadcast_event(event) # assume either all nodes have booted already, or there are some @@ -1554,9 +1558,9 @@ class Session: logging.debug( "session(%s) checking if not in runtime state, current state: %s", self.id, - EventTypes(self.state).name, + self.state.name, ) - if self.state == EventTypes.RUNTIME_STATE.value: + if self.state == EventTypes.RUNTIME_STATE: logging.info("valid runtime state found, returning") return @@ -1893,7 +1897,7 @@ class Session: Return the current time we have been in the runtime state, or zero if not in runtime. """ - if self.state == EventTypes.RUNTIME_STATE.value: + if self.state == EventTypes.RUNTIME_STATE: return time.monotonic() - self._state_time else: return 0.0 diff --git a/daemon/core/emulator/sessionconfig.py b/daemon/core/emulator/sessionconfig.py index 5f2d5916..ffeccdc4 100644 --- a/daemon/core/emulator/sessionconfig.py +++ b/daemon/core/emulator/sessionconfig.py @@ -57,7 +57,7 @@ class SessionConfig(ConfigurableManager, ConfigurableOptions): label="SDT3D URL", ), ] - config_type = RegisterTlvs.UTILITY.value + config_type = RegisterTlvs.UTILITY def __init__(self) -> None: super().__init__() diff --git a/daemon/core/location/geo.py b/daemon/core/location/geo.py index 7d3aea22..1f78f329 100644 --- a/daemon/core/location/geo.py +++ b/daemon/core/location/geo.py @@ -21,7 +21,7 @@ class GeoLocation: """ name = "location" - config_type = RegisterTlvs.UTILITY.value + config_type = RegisterTlvs.UTILITY def __init__(self) -> None: """ diff --git a/daemon/core/location/mobility.py b/daemon/core/location/mobility.py index bf02385a..62d954fa 100644 --- a/daemon/core/location/mobility.py +++ b/daemon/core/location/mobility.py @@ -36,7 +36,7 @@ class MobilityManager(ModelManager): """ name = "MobilityManager" - config_type = RegisterTlvs.WIRELESS.value + config_type = RegisterTlvs.WIRELESS def __init__(self, session: "Session") -> None: """ @@ -121,10 +121,7 @@ class MobilityManager(ModelManager): logging.warning("Ignoring event for unknown model '%s'", model) continue - if cls.config_type in [ - RegisterTlvs.WIRELESS.value, - RegisterTlvs.MOBILITY.value, - ]: + if cls.config_type in [RegisterTlvs.WIRELESS, RegisterTlvs.MOBILITY]: model = node.mobility else: continue @@ -142,17 +139,11 @@ class MobilityManager(ModelManager): ) continue - if ( - event_type == EventTypes.STOP.value - or event_type == EventTypes.RESTART.value - ): + if event_type in [EventTypes.STOP, EventTypes.RESTART]: model.stop(move_initial=True) - if ( - event_type == EventTypes.START.value - or event_type == EventTypes.RESTART.value - ): + if event_type in [EventTypes.START, EventTypes.RESTART]: model.start() - if event_type == EventTypes.PAUSE.value: + if event_type == EventTypes.PAUSE: model.pause() def sendevent(self, model: "WayPointMobility") -> None: @@ -163,13 +154,13 @@ class MobilityManager(ModelManager): :param model: mobility model to send event for :return: nothing """ - event_type = EventTypes.NONE.value + event_type = EventTypes.NONE if model.state == model.STATE_STOPPED: - event_type = EventTypes.STOP.value + event_type = EventTypes.STOP elif model.state == model.STATE_RUNNING: - event_type = EventTypes.START.value + event_type = EventTypes.START elif model.state == model.STATE_PAUSED: - event_type = EventTypes.PAUSE.value + event_type = EventTypes.PAUSE start_time = int(model.lasttime - model.timezero) end_time = int(model.endtime) @@ -212,7 +203,7 @@ class WirelessModel(ConfigurableOptions): Used for managing arbitrary configuration parameters. """ - config_type = RegisterTlvs.WIRELESS.value + config_type = RegisterTlvs.WIRELESS bitmap = None position_callback = None @@ -226,7 +217,7 @@ class WirelessModel(ConfigurableOptions): self.session = session self.id = _id - def all_link_data(self, flags: int) -> List: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List: """ May be used if the model can populate the GUI with wireless (green) link lines. @@ -486,7 +477,10 @@ class BasicRangeModel(WirelessModel): return True def create_link_data( - self, interface1: CoreInterface, interface2: CoreInterface, message_type: int + self, + interface1: CoreInterface, + interface2: CoreInterface, + message_type: MessageFlags, ) -> LinkData: """ Create a wireless link/unlink data message. @@ -501,7 +495,7 @@ class BasicRangeModel(WirelessModel): node1_id=interface1.node.id, node2_id=interface2.node.id, network_id=self.wlan.id, - link_type=LinkTypes.WIRELESS.value, + link_type=LinkTypes.WIRELESS, ) def sendlinkmsg( @@ -516,14 +510,14 @@ class BasicRangeModel(WirelessModel): :return: nothing """ if unlink: - message_type = MessageFlags.DELETE.value + message_type = MessageFlags.DELETE else: - message_type = MessageFlags.ADD.value + message_type = MessageFlags.ADD link_data = self.create_link_data(netif, netif2, message_type) self.session.broadcast_link(link_data) - def all_link_data(self, flags: int) -> List[LinkData]: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Return a list of wireless link messages for when the GUI reconnects. @@ -578,7 +572,7 @@ class WayPointMobility(WirelessModel): """ name = "waypoint" - config_type = RegisterTlvs.MOBILITY.value + config_type = RegisterTlvs.MOBILITY STATE_STOPPED = 0 STATE_RUNNING = 1 @@ -818,7 +812,7 @@ class WayPointMobility(WirelessModel): :return: nothing """ node.position.set(x, y, z) - node_data = node.data(message_type=0) + node_data = node.data() self.session.broadcast_node(node_data) def setendtime(self) -> None: diff --git a/daemon/core/nodes/base.py b/daemon/core/nodes/base.py index 1c9417a9..8f5354f2 100644 --- a/daemon/core/nodes/base.py +++ b/daemon/core/nodes/base.py @@ -14,7 +14,7 @@ from core import utils from core.configservice.dependencies import ConfigServiceDependencies from core.constants import MOUNT_BIN, VNODED_BIN from core.emulator.data import LinkData, NodeData -from core.emulator.enumerations import LinkTypes, NodeTypes +from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes from core.errors import CoreCommandError, CoreError from core.nodes import client from core.nodes.interface import CoreInterface, TunTap, Veth @@ -193,7 +193,7 @@ class NodeBase: def data( self, - message_type: int, + message_type: MessageFlags = MessageFlags.NONE, lat: float = None, lon: float = None, alt: float = None, @@ -244,7 +244,7 @@ class NodeBase: return node_data - def all_link_data(self, flags: int) -> List: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build CORE Link data for this object. There is no default method for PyCoreObjs as PyCoreNodes do not implement this but @@ -472,7 +472,7 @@ class CoreNode(CoreNodeBase): Provides standard core node logic. """ - apitype = NodeTypes.DEFAULT.value + apitype = NodeTypes.DEFAULT valid_address_types = {"inet", "inet6", "inet6link"} def __init__( @@ -982,7 +982,7 @@ class CoreNetworkBase(NodeBase): Base class for networks """ - linktype = LinkTypes.WIRED.value + linktype = LinkTypes.WIRED is_emane = False def __init__( @@ -1069,7 +1069,7 @@ class CoreNetworkBase(NodeBase): with self._linked_lock: del self._linked[netif] - def all_link_data(self, flags: int) -> List[LinkData]: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build link data objects for this network. Each link object describes a link between this network and a node. diff --git a/daemon/core/nodes/docker.py b/daemon/core/nodes/docker.py index 4622f4f5..60adfe32 100644 --- a/daemon/core/nodes/docker.py +++ b/daemon/core/nodes/docker.py @@ -72,7 +72,7 @@ class DockerClient: class DockerNode(CoreNode): - apitype = NodeTypes.DOCKER.value + apitype = NodeTypes.DOCKER def __init__( self, diff --git a/daemon/core/nodes/interface.py b/daemon/core/nodes/interface.py index ea8e5012..8da7c95b 100644 --- a/daemon/core/nodes/interface.py +++ b/daemon/core/nodes/interface.py @@ -7,6 +7,7 @@ import time from typing import TYPE_CHECKING, Callable, Dict, List, Tuple from core import utils +from core.emulator.enumerations import MessageFlags from core.errors import CoreCommandError from core.nodes.netclient import get_net_client @@ -552,7 +553,7 @@ class GreTap(CoreInterface): """ return None - def all_link_data(self, flags: int) -> List: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List: """ Retrieve link data. diff --git a/daemon/core/nodes/lxd.py b/daemon/core/nodes/lxd.py index b64c0206..3ca399b5 100644 --- a/daemon/core/nodes/lxd.py +++ b/daemon/core/nodes/lxd.py @@ -66,7 +66,7 @@ class LxdClient: class LxcNode(CoreNode): - apitype = NodeTypes.LXC.value + apitype = NodeTypes.LXC def __init__( self, diff --git a/daemon/core/nodes/network.py b/daemon/core/nodes/network.py index 9547e6dc..dded924d 100644 --- a/daemon/core/nodes/network.py +++ b/daemon/core/nodes/network.py @@ -12,7 +12,7 @@ import netaddr from core import utils from core.constants import EBTABLES_BIN, TC_BIN from core.emulator.data import LinkData, NodeData -from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs +from core.emulator.enumerations import LinkTypes, MessageFlags, NodeTypes, RegisterTlvs from core.errors import CoreCommandError, CoreError from core.nodes.base import CoreNetworkBase from core.nodes.interface import CoreInterface, GreTap, Veth @@ -848,7 +848,7 @@ class CtrlNet(CoreNetwork): super().shutdown() - def all_link_data(self, flags: int) -> List[LinkData]: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Do not include CtrlNet in link messages describing this session. @@ -899,7 +899,7 @@ class PtpNet(CoreNetwork): """ return None - def all_link_data(self, flags: int) -> List[LinkData]: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build CORE API TLVs for a point-to-point link. One Link message describes this network. @@ -999,7 +999,7 @@ class SwitchNode(CoreNetwork): Provides switch functionality within a core node. """ - apitype = NodeTypes.SWITCH.value + apitype = NodeTypes.SWITCH policy = "ACCEPT" type = "lanswitch" @@ -1010,7 +1010,7 @@ class HubNode(CoreNetwork): ports by turning off MAC address learning. """ - apitype = NodeTypes.HUB.value + apitype = NodeTypes.HUB policy = "ACCEPT" type = "hub" @@ -1029,8 +1029,8 @@ class WlanNode(CoreNetwork): Provides wireless lan functionality within a core node. """ - apitype = NodeTypes.WIRELESS_LAN.value - linktype = LinkTypes.WIRED.value + apitype = NodeTypes.WIRELESS_LAN + linktype = LinkTypes.WIRED policy = "DROP" type = "wlan" @@ -1090,13 +1090,13 @@ class WlanNode(CoreNetwork): :return: nothing """ logging.debug("node(%s) setting model: %s", self.name, model.name) - if model.config_type == RegisterTlvs.WIRELESS.value: + if model.config_type == RegisterTlvs.WIRELESS: self.model = model(session=self.session, _id=self.id) for netif in self.netifs(): netif.poshook = self.model.position_callback netif.setposition() self.updatemodel(config) - elif model.config_type == RegisterTlvs.MOBILITY.value: + elif model.config_type == RegisterTlvs.MOBILITY: self.mobility = model(session=self.session, _id=self.id) self.mobility.update_config(config) @@ -1115,7 +1115,7 @@ class WlanNode(CoreNetwork): for netif in self.netifs(): netif.setposition() - def all_link_data(self, flags: int) -> List[LinkData]: + def all_link_data(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Retrieve all link data. @@ -1133,6 +1133,6 @@ class TunnelNode(GreTapBridge): Provides tunnel functionality in a core node. """ - apitype = NodeTypes.TUNNEL.value + apitype = NodeTypes.TUNNEL policy = "ACCEPT" type = "tunnel" diff --git a/daemon/core/nodes/physical.py b/daemon/core/nodes/physical.py index 4d9d21f4..e8c999c6 100644 --- a/daemon/core/nodes/physical.py +++ b/daemon/core/nodes/physical.py @@ -264,7 +264,7 @@ class Rj45Node(CoreNodeBase, CoreInterface): network. """ - apitype = NodeTypes.RJ45.value + apitype = NodeTypes.RJ45 type = "rj45" def __init__( diff --git a/daemon/core/plugins/sdt.py b/daemon/core/plugins/sdt.py index 1ccf40a5..a759228d 100644 --- a/daemon/core/plugins/sdt.py +++ b/daemon/core/plugins/sdt.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: def link_data_params(link_data: LinkData) -> Tuple[int, int, bool]: node_one = link_data.node1_id node_two = link_data.node2_id - is_wireless = link_data.link_type == LinkTypes.WIRELESS.value + is_wireless = link_data.link_type == LinkTypes.WIRELESS return node_one, node_two, is_wireless @@ -90,7 +90,7 @@ class Sdt: self.address = (self.url.hostname, self.url.port) self.protocol = self.url.scheme - def connect(self, flags: int = 0) -> bool: + def connect(self) -> bool: """ Connect to the SDT address/port if enabled. @@ -100,7 +100,7 @@ class Sdt: return False if self.connected: return True - if self.session.state == EventTypes.SHUTDOWN_STATE.value: + if self.session.state == EventTypes.SHUTDOWN_STATE: return False self.seturl() @@ -122,7 +122,7 @@ class Sdt: self.connected = True # refresh all objects in SDT3D when connecting after session start - if not flags & MessageFlags.ADD.value and not self.sendobjs(): + if not self.sendobjs(): return False return True @@ -210,7 +210,7 @@ class Sdt: self.add_node(node) for net in nets: - all_links = net.all_link_data(flags=MessageFlags.ADD.value) + all_links = net.all_link_data(flags=MessageFlags.ADD) for link_data in all_links: is_wireless = isinstance(net, (WlanNode, EmaneNet)) if is_wireless and link_data.node1_id == net.id: @@ -302,7 +302,7 @@ class Sdt: return # delete node - if node_data.message_type == MessageFlags.DELETE.value: + if node_data.message_type == MessageFlags.DELETE: self.cmd(f"delete node,{node_data.id}") else: x = node_data.x_position @@ -375,9 +375,9 @@ class Sdt: :param link_data: link data to handle :return: nothing """ - if link_data.message_type == MessageFlags.ADD.value: + if link_data.message_type == MessageFlags.ADD: params = link_data_params(link_data) self.add_link(*params) - elif link_data.message_type == MessageFlags.DELETE.value: + elif link_data.message_type == MessageFlags.DELETE: params = link_data_params(link_data) self.delete_link(*params[:2]) diff --git a/daemon/core/services/coreservices.py b/daemon/core/services/coreservices.py index a561b843..6323ceab 100644 --- a/daemon/core/services/coreservices.py +++ b/daemon/core/services/coreservices.py @@ -315,7 +315,7 @@ class CoreServices: """ name = "services" - config_type = RegisterTlvs.UTILITY.value + config_type = RegisterTlvs.UTILITY def __init__(self, session: "Session") -> None: """ @@ -672,7 +672,7 @@ class CoreServices: filetypestr = "service:%s" % service.name return FileData( - message_type=MessageFlags.ADD.value, + message_type=MessageFlags.ADD, node=node.id, name=filename, type=filetypestr, diff --git a/daemon/core/services/quagga.py b/daemon/core/services/quagga.py index 11de9c54..7979dd23 100644 --- a/daemon/core/services/quagga.py +++ b/daemon/core/services/quagga.py @@ -551,7 +551,7 @@ class Babel(QuaggaService): @classmethod def generatequaggaifcconfig(cls, node, ifc): - if ifc.net and ifc.net.linktype == LinkTypes.WIRELESS.value: + if ifc.net and ifc.net.linktype == LinkTypes.WIRELESS: return " babel wireless\n no babel split-horizon\n" else: return " babel wired\n babel split-horizon\n" diff --git a/daemon/core/xml/corexml.py b/daemon/core/xml/corexml.py index 8eab98c2..68426905 100644 --- a/daemon/core/xml/corexml.py +++ b/daemon/core/xml/corexml.py @@ -8,7 +8,7 @@ import core.nodes.physical from core.emane.nodes import EmaneNet from core.emulator.data import LinkData from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions -from core.emulator.enumerations import NodeTypes +from core.emulator.enumerations import EventTypes, NodeTypes from core.nodes.base import CoreNetworkBase, CoreNodeBase, NodeBase from core.nodes.docker import DockerNode from core.nodes.lxd import LxcNode @@ -260,7 +260,7 @@ class NetworkElement(NodeElement): def add_type(self) -> None: if self.node.apitype: - node_type = NodeTypes(self.node.apitype).name + node_type = self.node.apitype.name else: node_type = self.node.__class__.__name__ add_attribute(self.element, "type", node_type) @@ -324,7 +324,7 @@ class CoreXmlWriter: for file_name, data in self.session._hooks[state]: hook = etree.SubElement(hooks, "hook") add_attribute(hook, "name", file_name) - add_attribute(hook, "state", state) + add_attribute(hook, "state", state.value) hook.text = data if hooks.getchildren(): @@ -476,7 +476,7 @@ class CoreXmlWriter: self.write_device(node) # add known links - links.extend(node.all_link_data(0)) + links.extend(node.all_link_data()) return links @@ -666,13 +666,11 @@ class CoreXmlReader: for hook in session_hooks.iterchildren(): name = hook.get("name") - state = hook.get("state") + state = get_int(hook, "state") + state = EventTypes(state) data = hook.text - hook_type = f"hook:{state}" logging.info("reading hook: state(%s) name(%s)", state, name) - self.session.set_hook( - hook_type, file_name=name, source_name=None, data=data - ) + self.session.add_hook(state, name, None, data) def read_session_origin(self) -> None: session_origin = self.scenario.find("session_origin") diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 6b55c14f..866c5472 100755 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -17,8 +17,8 @@ from core import constants from core.api.grpc.server import CoreGrpcServer from core.api.tlv.corehandlers import CoreHandler, CoreUdpHandler from core.api.tlv.coreserver import CoreServer, CoreUdpServer +from core.api.tlv.enumerations import CORE_API_PORT from core.constants import CORE_CONF_DIR, COREDPY_VERSION -from core.emulator.enumerations import CORE_API_PORT from core.utils import close_onexec, load_logging_config diff --git a/daemon/scripts/coresendmsg b/daemon/scripts/coresendmsg index c8dccfd7..a909522f 100755 --- a/daemon/scripts/coresendmsg +++ b/daemon/scripts/coresendmsg @@ -9,12 +9,8 @@ import socket import sys from core.api.tlv import coreapi -from core.emulator.enumerations import ( - CORE_API_PORT, - MessageFlags, - MessageTypes, - SessionTlvs, -) +from core.api.tlv.enumerations import CORE_API_PORT, MessageTypes, SessionTlvs +from core.emulator.enumerations import MessageFlags def print_available_tlvs(t, tlv_class): diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 80cf6787..cc9ba2a4 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -114,7 +114,7 @@ class TestCore: session.instantiate() # check link data gets generated - assert ptp_node.all_link_data(MessageFlags.ADD.value) + assert ptp_node.all_link_data(MessageFlags.ADD) # check common nets exist between linked nodes assert node_one.commonnets(node_two) diff --git a/daemon/tests/test_grpc.py b/daemon/tests/test_grpc.py index d26c46e4..6feacac3 100644 --- a/daemon/tests/test_grpc.py +++ b/daemon/tests/test_grpc.py @@ -7,16 +7,12 @@ from mock import patch from core.api.grpc import core_pb2 from core.api.grpc.client import CoreGrpcClient, InterfaceHelper -from core.config import ConfigShim +from core.api.tlv.dataconversion import ConfigShim +from core.api.tlv.enumerations import ConfigFlags from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emulator.data import EventData from core.emulator.emudata import NodeOptions -from core.emulator.enumerations import ( - ConfigFlags, - EventTypes, - ExceptionLevels, - NodeTypes, -) +from core.emulator.enumerations import EventTypes, ExceptionLevels, NodeTypes from core.errors import CoreError from core.location.mobility import BasicRangeModel, Ns2ScriptedMobility from core.xml.corexml import CoreXmlWriter @@ -127,7 +123,7 @@ class TestGrpc: assert wlan_node.id in session.nodes assert session.nodes[node_one.id].netif(0) is not None assert session.nodes[node_two.id].netif(0) is not None - hook_file, hook_data = session._hooks[core_pb2.SessionState.RUNTIME][0] + hook_file, hook_data = session._hooks[EventTypes.RUNTIME_STATE][0] assert hook_file == hook.file assert hook_data == hook.data assert session.location.refxyz == (location_x, location_y, location_z) @@ -169,7 +165,7 @@ class TestGrpc: assert isinstance(response.state, int) session = grpc_server.coreemu.sessions.get(response.session_id) assert session is not None - assert session.state == response.state + assert session.state == EventTypes(response.state) if session_id is not None: assert response.session_id == session_id assert session.id == session_id @@ -341,7 +337,7 @@ class TestGrpc: # then assert response.result is True - assert session.state == core_pb2.SessionState.DEFINITION + assert session.state == EventTypes.DEFINITION_STATE def test_add_node(self, grpc_server): # given @@ -447,7 +443,7 @@ class TestGrpc: session = grpc_server.coreemu.create_session() file_name = "test" file_data = "echo hello" - session.add_hook(EventTypes.RUNTIME_STATE.value, file_name, None, file_data) + session.add_hook(EventTypes.RUNTIME_STATE, file_name, None, file_data) # then with client.context_connect(): @@ -540,7 +536,7 @@ class TestGrpc: session = grpc_server.coreemu.create_session() switch = session.add_node(_type=NodeTypes.SWITCH) node = session.add_node() - assert len(switch.all_link_data(0)) == 0 + assert len(switch.all_link_data()) == 0 # then interface = interface_helper.create_interface(node.id, 0) @@ -549,7 +545,7 @@ class TestGrpc: # then assert response.result is True - assert len(switch.all_link_data(0)) == 1 + assert len(switch.all_link_data()) == 1 def test_add_link_exception(self, grpc_server, interface_helper): # given @@ -572,7 +568,7 @@ class TestGrpc: interface = ip_prefixes.create_interface(node) session.add_link(node.id, switch.id, interface) options = core_pb2.LinkOptions(bandwidth=30000) - link = switch.all_link_data(0)[0] + link = switch.all_link_data()[0] assert options.bandwidth != link.bandwidth # then @@ -583,7 +579,7 @@ class TestGrpc: # then assert response.result is True - link = switch.all_link_data(0)[0] + link = switch.all_link_data()[0] assert options.bandwidth == link.bandwidth def test_delete_link(self, grpc_server, ip_prefixes): @@ -986,7 +982,7 @@ class TestGrpc: client = CoreGrpcClient() session = grpc_server.coreemu.create_session() node = session.add_node() - node_data = node.data(message_type=0) + node_data = node.data() queue = Queue() def handle_event(event_data): @@ -1011,7 +1007,7 @@ class TestGrpc: node = session.add_node() interface = ip_prefixes.create_interface(node) session.add_link(node.id, wlan.id, interface) - link_data = wlan.all_link_data(0)[0] + link_data = wlan.all_link_data()[0] queue = Queue() def handle_event(event_data): @@ -1065,7 +1061,7 @@ class TestGrpc: client.events(session.id, handle_event) time.sleep(0.1) event = EventData( - event_type=EventTypes.RUNTIME_STATE.value, time=str(time.monotonic()) + event_type=EventTypes.RUNTIME_STATE, time=str(time.monotonic()) ) session.broadcast_event(event) diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index a47aba75..481a0fa9 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -10,21 +10,18 @@ import pytest from mock import MagicMock from core.api.tlv import coreapi -from core.emane.ieee80211abg import EmaneIeee80211abgModel -from core.emulator.enumerations import ( +from core.api.tlv.enumerations import ( ConfigFlags, ConfigTlvs, EventTlvs, - EventTypes, ExecuteTlvs, FileTlvs, LinkTlvs, - MessageFlags, NodeTlvs, - NodeTypes, - RegisterTlvs, SessionTlvs, ) +from core.emane.ieee80211abg import EmaneIeee80211abgModel +from core.emulator.enumerations import EventTypes, MessageFlags, NodeTypes, RegisterTlvs from core.errors import CoreError from core.location.mobility import BasicRangeModel @@ -117,7 +114,7 @@ class TestGui: coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 def test_link_add_net_to_node(self, coretlv): @@ -141,7 +138,7 @@ class TestGui: coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 def test_link_add_node_to_node(self, coretlv): @@ -171,7 +168,7 @@ class TestGui: all_links = [] for node_id in coretlv.session.nodes: node = coretlv.session.nodes[node_id] - all_links += node.all_link_data(0) + all_links += node.all_link_data() assert len(all_links) == 1 def test_link_update(self, coretlv): @@ -193,7 +190,7 @@ class TestGui: ) coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 link = all_links[0] assert link.bandwidth is None @@ -211,7 +208,7 @@ class TestGui: coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 link = all_links[0] assert link.bandwidth == bandwidth @@ -240,7 +237,7 @@ class TestGui: all_links = [] for node_id in coretlv.session.nodes: node = coretlv.session.nodes[node_id] - all_links += node.all_link_data(0) + all_links += node.all_link_data() assert len(all_links) == 1 message = coreapi.CoreLinkMessage.create( @@ -257,7 +254,7 @@ class TestGui: all_links = [] for node_id in coretlv.session.nodes: node = coretlv.session.nodes[node_id] - all_links += node.all_link_data(0) + all_links += node.all_link_data() assert len(all_links) == 0 def test_link_delete_node_to_net(self, coretlv): @@ -279,7 +276,7 @@ class TestGui: ) coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 message = coreapi.CoreLinkMessage.create( @@ -293,7 +290,7 @@ class TestGui: coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 0 def test_link_delete_net_to_node(self, coretlv): @@ -315,7 +312,7 @@ class TestGui: ) coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 1 message = coreapi.CoreLinkMessage.create( @@ -329,7 +326,7 @@ class TestGui: coretlv.handle_message(message) switch_node = coretlv.session.get_node(switch) - all_links = switch_node.all_link_data(0) + all_links = switch_node.all_link_data() assert len(all_links) == 0 def test_session_update(self, coretlv): @@ -376,14 +373,14 @@ class TestGui: assert len(coretlv.coreemu.sessions) == 0 def test_file_hook_add(self, coretlv): - state = EventTypes.DATACOLLECT_STATE.value + state = EventTypes.DATACOLLECT_STATE assert coretlv.session._hooks.get(state) is None file_name = "test.sh" file_data = "echo hello" message = coreapi.CoreFileMessage.create( MessageFlags.ADD.value, [ - (FileTlvs.TYPE, f"hook:{state}"), + (FileTlvs.TYPE, f"hook:{state.value}"), (FileTlvs.NAME, file_name), (FileTlvs.DATA, file_data), ], @@ -514,7 +511,7 @@ class TestGui: coretlv.handle_message(message) - assert coretlv.session.state == state.value + assert coretlv.session.state == state def test_event_schedule(self, coretlv): coretlv.session.add_event = mock.MagicMock() diff --git a/daemon/tests/test_links.py b/daemon/tests/test_links.py index ceef3a02..d32a1c5f 100644 --- a/daemon/tests/test_links.py +++ b/daemon/tests/test_links.py @@ -43,7 +43,7 @@ class TestLinks: session.add_link(node_one.id, node_two.id, interface_one) # then - assert node_two.all_link_data(0) + assert node_two.all_link_data() assert node_one.netif(interface_one.id) def test_net_to_node(self, session, ip_prefixes): @@ -56,7 +56,7 @@ class TestLinks: session.add_link(node_one.id, node_two.id, interface_two=interface_two) # then - assert node_one.all_link_data(0) + assert node_one.all_link_data() assert node_two.netif(interface_two.id) def test_net_to_net(self, session): @@ -68,7 +68,7 @@ class TestLinks: session.add_link(node_one.id, node_two.id) # then - assert node_one.all_link_data(0) + assert node_one.all_link_data() def test_link_update(self, session, ip_prefixes): # given diff --git a/daemon/tests/test_xml.py b/daemon/tests/test_xml.py index 496623a6..783e2722 100644 --- a/daemon/tests/test_xml.py +++ b/daemon/tests/test_xml.py @@ -3,7 +3,7 @@ from xml.etree import ElementTree import pytest from core.emulator.emudata import LinkOptions, NodeOptions -from core.emulator.enumerations import NodeTypes +from core.emulator.enumerations import EventTypes, NodeTypes from core.errors import CoreError from core.location.mobility import BasicRangeModel from core.services.utility import SshService @@ -20,7 +20,8 @@ class TestXml: # create hook file_name = "runtime_hook.sh" data = "#!/bin/sh\necho hello" - session.set_hook("hook:4", file_name, None, data) + state = EventTypes.RUNTIME_STATE + session.add_hook(state, file_name, None, data) # save xml xml_file = tmpdir.join("session.xml") @@ -38,7 +39,7 @@ class TestXml: session.open_xml(file_path, start=True) # verify nodes have been recreated - runtime_hooks = session._hooks.get(4) + runtime_hooks = session._hooks.get(state) assert runtime_hooks runtime_hook = runtime_hooks[0] assert file_name == runtime_hook[0] @@ -269,7 +270,7 @@ class TestXml: switch_two = session.get_node(n2_id) assert switch_one assert switch_two - assert len(switch_one.all_link_data(0) + switch_two.all_link_data(0)) == 1 + assert len(switch_one.all_link_data() + switch_two.all_link_data()) == 1 def test_link_options(self, session, tmpdir, ip_prefixes): """ @@ -329,7 +330,7 @@ class TestXml: links = [] for node_id in session.nodes: node = session.nodes[node_id] - links += node.all_link_data(0) + links += node.all_link_data() link = links[0] assert link_options.per == link.per assert link_options.bandwidth == link.bandwidth @@ -396,7 +397,7 @@ class TestXml: links = [] for node_id in session.nodes: node = session.nodes[node_id] - links += node.all_link_data(0) + links += node.all_link_data() link = links[0] assert link_options.per == link.per assert link_options.bandwidth == link.bandwidth @@ -478,7 +479,7 @@ class TestXml: links = [] for node_id in session.nodes: node = session.nodes[node_id] - links += node.all_link_data(0) + links += node.all_link_data() assert len(links) == 2 link_one = links[0] link_two = links[1]