added type hinting to core.emane functions

This commit is contained in:
Blake Harnden 2020-01-14 16:27:08 -08:00
parent 49f09a25cc
commit fa095431fb
9 changed files with 147 additions and 108 deletions

View file

@ -1,6 +1,8 @@
""" """
EMANE Bypass model for CORE EMANE Bypass model for CORE
""" """
from typing import List
from core.config import ConfigGroup, Configuration from core.config import ConfigGroup, Configuration
from core.emane import emanemodel from core.emane import emanemodel
from core.emulator.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
@ -29,11 +31,11 @@ class EmaneBypassModel(emanemodel.EmaneModel):
phy_config = [] phy_config = []
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
# ignore default logic # ignore default logic
pass pass
# override config groups # override config groups
@classmethod @classmethod
def config_groups(cls): def config_groups(cls) -> List[ConfigGroup]:
return [ConfigGroup("Bypass Parameters", 1, 1)] return [ConfigGroup("Bypass Parameters", 1, 1)]

View file

@ -4,11 +4,13 @@ commeffect.py: EMANE CommEffect model for CORE
import logging import logging
import os import os
from typing import Dict, List
from lxml import etree from lxml import etree
from core.config import ConfigGroup from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest, emanemodel from core.emane import emanemanifest, emanemodel
from core.nodes.interface import CoreInterface
from core.xml import emanexml from core.xml import emanexml
try: try:
@ -20,7 +22,7 @@ except ImportError:
logging.debug("compatible emane python bindings not installed") logging.debug("compatible emane python bindings not installed")
def convert_none(x): def convert_none(x: float) -> int:
""" """
Helper to use 0 for None values. Helper to use 0 for None values.
""" """
@ -45,19 +47,21 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
external_config = [] external_config = []
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
shim_xml_path = os.path.join(emane_prefix, "share/emane/manifest", cls.shim_xml) shim_xml_path = os.path.join(emane_prefix, "share/emane/manifest", cls.shim_xml)
cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults) cls.config_shim = emanemanifest.parse(shim_xml_path, cls.shim_defaults)
@classmethod @classmethod
def configurations(cls): def configurations(cls) -> List[Configuration]:
return cls.config_shim return cls.config_shim
@classmethod @classmethod
def config_groups(cls): def config_groups(cls) -> List[ConfigGroup]:
return [ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))] return [ConfigGroup("CommEffect SHIM Parameters", 1, len(cls.configurations()))]
def build_xml_files(self, config, interface=None): def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
) -> None:
""" """
Build the necessary nem and commeffect XMLs in the given path. Build the necessary nem and commeffect XMLs in the given path.
If an individual NEM has a nonstandard config, we need to build If an individual NEM has a nonstandard config, we need to build
@ -109,14 +113,14 @@ class EmaneCommEffectModel(emanemodel.EmaneModel):
def linkconfig( def linkconfig(
self, self,
netif, netif: CoreInterface,
bw=None, bw: float = None,
delay=None, delay: float = None,
loss=None, loss: float = None,
duplicate=None, duplicate: float = None,
jitter=None, jitter: float = None,
netif2=None, netif2: CoreInterface = None,
): ) -> None:
""" """
Generate CommEffect events when a Link Message is received having Generate CommEffect events when a Link Message is received having
link parameters. link parameters.

View file

@ -6,6 +6,7 @@ import logging
import os import os
import threading import threading
from collections import OrderedDict from collections import OrderedDict
from typing import TYPE_CHECKING, Dict, List, Set, Tuple, Type
from core import utils from core import utils
from core.config import ConfigGroup, Configuration, ModelManager from core.config import ConfigGroup, Configuration, ModelManager
@ -19,8 +20,15 @@ from core.emane.rfpipe import EmaneRfPipeModel
from core.emane.tdma import EmaneTdmaModel from core.emane.tdma import EmaneTdmaModel
from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs from core.emulator.enumerations import ConfigDataTypes, RegisterTlvs
from core.errors import CoreCommandError, CoreError from core.errors import CoreCommandError, CoreError
from core.nodes.base import CoreNode
from core.nodes.interface import CoreInterface
from core.nodes.network import CtrlNet
from core.xml import emanexml from core.xml import emanexml
if TYPE_CHECKING:
from core.emulator.session import Session
try: try:
from emane.events import EventService from emane.events import EventService
from emane.events import LocationEvent from emane.events import LocationEvent
@ -57,7 +65,7 @@ class EmaneManager(ModelManager):
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG" EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL = 3 DEFAULT_LOG_LEVEL = 3
def __init__(self, session): def __init__(self, session: "Session") -> None:
""" """
Creates a Emane instance. Creates a Emane instance.
@ -86,7 +94,9 @@ class EmaneManager(ModelManager):
self.event_device = None self.event_device = None
self.emane_check() self.emane_check()
def getifcconfig(self, node_id, interface, model_name): def getifcconfig(
self, node_id: int, interface: CoreInterface, model_name: str
) -> Dict[str, str]:
""" """
Retrieve interface configuration or node configuration if not provided. Retrieve interface configuration or node configuration if not provided.
@ -129,11 +139,11 @@ class EmaneManager(ModelManager):
return config return config
def config_reset(self, node_id=None): def config_reset(self, node_id: int = None) -> None:
super().config_reset(node_id) super().config_reset(node_id)
self.set_configs(self.emane_config.default_values()) self.set_configs(self.emane_config.default_values())
def emane_check(self): def emane_check(self) -> None:
""" """
Check if emane is installed and load models. Check if emane is installed and load models.
@ -157,7 +167,7 @@ class EmaneManager(ModelManager):
except CoreCommandError: except CoreCommandError:
logging.info("emane is not installed") logging.info("emane is not installed")
def deleteeventservice(self): def deleteeventservice(self) -> None:
if self.service: if self.service:
for fd in self.service._readFd, self.service._writeFd: for fd in self.service._readFd, self.service._writeFd:
if fd >= 0: if fd >= 0:
@ -168,7 +178,7 @@ class EmaneManager(ModelManager):
self.service = None self.service = None
self.event_device = None self.event_device = None
def initeventservice(self, filename=None, shutdown=False): def initeventservice(self, filename: str = None, shutdown: bool = False) -> None:
""" """
Re-initialize the EMANE Event service. Re-initialize the EMANE Event service.
The multicast group and/or port may be configured. The multicast group and/or port may be configured.
@ -186,7 +196,7 @@ class EmaneManager(ModelManager):
logging.error( logging.error(
"invalid emane event service device provided: %s", self.event_device "invalid emane event service device provided: %s", self.event_device
) )
return False return
# make sure the event control network is in place # make sure the event control network is in place
eventnet = self.session.add_remove_control_net( eventnet = self.session.add_remove_control_net(
@ -205,9 +215,7 @@ class EmaneManager(ModelManager):
except EventServiceException: except EventServiceException:
logging.exception("error instantiating emane EventService") logging.exception("error instantiating emane EventService")
return True def load_models(self, emane_models: List[Type[EmaneModel]]) -> None:
def load_models(self, emane_models):
""" """
Load EMANE models and make them available. Load EMANE models and make them available.
""" """
@ -219,7 +227,7 @@ class EmaneManager(ModelManager):
emane_model.load(emane_prefix) emane_model.load(emane_prefix)
self.models[emane_model.name] = emane_model self.models[emane_model.name] = emane_model
def add_node(self, emane_net): def add_node(self, emane_net: EmaneNet) -> None:
""" """
Add EMANE network object to this manager. Add EMANE network object to this manager.
@ -233,7 +241,7 @@ class EmaneManager(ModelManager):
) )
self._emane_nets[emane_net.id] = emane_net self._emane_nets[emane_net.id] = emane_net
def getnodes(self): def getnodes(self) -> Set[CoreNode]:
""" """
Return a set of CoreNodes that are linked to an EMANE network, Return a set of CoreNodes that are linked to an EMANE network,
e.g. containers having one or more radio interfaces. e.g. containers having one or more radio interfaces.
@ -245,7 +253,7 @@ class EmaneManager(ModelManager):
nodes.add(netif.node) nodes.add(netif.node)
return nodes return nodes
def setup(self): def setup(self) -> int:
""" """
Setup duties for EMANE manager. Setup duties for EMANE manager.
@ -303,7 +311,7 @@ class EmaneManager(ModelManager):
self.check_node_models() self.check_node_models()
return EmaneManager.SUCCESS return EmaneManager.SUCCESS
def startup(self): def startup(self) -> int:
""" """
After all the EMANE networks have been added, build XML files After all the EMANE networks have been added, build XML files
and start the daemons. and start the daemons.
@ -347,7 +355,7 @@ class EmaneManager(ModelManager):
return EmaneManager.SUCCESS return EmaneManager.SUCCESS
def poststartup(self): def poststartup(self) -> None:
""" """
Retransmit location events now that all NEMs are active. Retransmit location events now that all NEMs are active.
""" """
@ -367,7 +375,7 @@ class EmaneManager(ModelManager):
x, y, z = netif.node.position.get() x, y, z = netif.node.position.get()
emane_node.setnemposition(netif, x, y, z) emane_node.setnemposition(netif, x, y, z)
def reset(self): def reset(self) -> None:
""" """
Remove all EMANE networks from the dictionary, reset port numbers and Remove all EMANE networks from the dictionary, reset port numbers and
nem id counters nem id counters
@ -382,7 +390,7 @@ class EmaneManager(ModelManager):
"emane_transform_port", 8200 "emane_transform_port", 8200
) )
def shutdown(self): def shutdown(self) -> None:
""" """
stop all EMANE daemons stop all EMANE daemons
""" """
@ -394,7 +402,7 @@ class EmaneManager(ModelManager):
self.stopdaemons() self.stopdaemons()
self.stopeventmonitor() self.stopeventmonitor()
def buildxml(self): def buildxml(self) -> None:
""" """
Build XML files required to run EMANE on each node. Build XML files required to run EMANE on each node.
NEMs run inside containers using the control network for passing NEMs run inside containers using the control network for passing
@ -410,7 +418,7 @@ class EmaneManager(ModelManager):
self.buildnemxml() self.buildnemxml()
self.buildeventservicexml() self.buildeventservicexml()
def check_node_models(self): def check_node_models(self) -> None:
""" """
Associate EMANE model classes with EMANE network nodes. Associate EMANE model classes with EMANE network nodes.
""" """
@ -438,7 +446,7 @@ class EmaneManager(ModelManager):
model_class = self.models[model_name] model_class = self.models[model_name]
emane_node.setmodel(model_class, config) emane_node.setmodel(model_class, config)
def nemlookup(self, nemid): def nemlookup(self, nemid) -> Tuple[EmaneNet, CoreInterface]:
""" """
Look for the given numerical NEM ID and return the first matching Look for the given numerical NEM ID and return the first matching
EMANE network and NEM interface. EMANE network and NEM interface.
@ -456,7 +464,7 @@ class EmaneManager(ModelManager):
return emane_node, netif return emane_node, netif
def numnems(self): def numnems(self) -> int:
""" """
Return the number of NEMs emulated locally. Return the number of NEMs emulated locally.
""" """
@ -466,7 +474,7 @@ class EmaneManager(ModelManager):
count += len(emane_node.netifs()) count += len(emane_node.netifs())
return count return count
def buildplatformxml(self, ctrlnet): def buildplatformxml(self, ctrlnet: CtrlNet) -> None:
""" """
Build a platform.xml file now that all nodes are configured. Build a platform.xml file now that all nodes are configured.
""" """
@ -480,7 +488,7 @@ class EmaneManager(ModelManager):
self, ctrlnet, emane_node, nemid, platform_xmls self, ctrlnet, emane_node, nemid, platform_xmls
) )
def buildnemxml(self): def buildnemxml(self) -> None:
""" """
Builds the nem, mac, and phy xml files for each EMANE network. Builds the nem, mac, and phy xml files for each EMANE network.
""" """
@ -488,7 +496,7 @@ class EmaneManager(ModelManager):
emane_net = self._emane_nets[key] emane_net = self._emane_nets[key]
emanexml.build_xml_files(self, emane_net) emanexml.build_xml_files(self, emane_net)
def buildeventservicexml(self): def buildeventservicexml(self) -> None:
""" """
Build the libemaneeventservice.xml file if event service options Build the libemaneeventservice.xml file if event service options
were changed in the global config. were changed in the global config.
@ -520,7 +528,7 @@ class EmaneManager(ModelManager):
) )
) )
def startdaemons(self): def startdaemons(self) -> None:
""" """
Start one EMANE daemon per node having a radio. Start one EMANE daemon per node having a radio.
Add a control network even if the user has not configured one. Add a control network even if the user has not configured one.
@ -596,7 +604,7 @@ class EmaneManager(ModelManager):
self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path)) self.session.distributed.execute(lambda x: x.remote_cmd(emanecmd, cwd=path))
logging.info("host emane daemon running: %s", emanecmd) logging.info("host emane daemon running: %s", emanecmd)
def stopdaemons(self): def stopdaemons(self) -> None:
""" """
Kill the appropriate EMANE daemons. Kill the appropriate EMANE daemons.
""" """
@ -623,7 +631,7 @@ class EmaneManager(ModelManager):
except CoreCommandError: except CoreCommandError:
logging.exception("error shutting down emane daemons") logging.exception("error shutting down emane daemons")
def installnetifs(self): def installnetifs(self) -> None:
""" """
Install TUN/TAP virtual interfaces into their proper namespaces Install TUN/TAP virtual interfaces into their proper namespaces
now that the EMANE daemons are running. now that the EMANE daemons are running.
@ -633,7 +641,7 @@ class EmaneManager(ModelManager):
logging.info("emane install netifs for node: %d", key) logging.info("emane install netifs for node: %d", key)
emane_node.installnetifs() emane_node.installnetifs()
def deinstallnetifs(self): def deinstallnetifs(self) -> None:
""" """
Uninstall TUN/TAP virtual interfaces. Uninstall TUN/TAP virtual interfaces.
""" """
@ -641,7 +649,7 @@ class EmaneManager(ModelManager):
emane_node = self._emane_nets[key] emane_node = self._emane_nets[key]
emane_node.deinstallnetifs() emane_node.deinstallnetifs()
def doeventmonitor(self): def doeventmonitor(self) -> bool:
""" """
Returns boolean whether or not EMANE events will be monitored. Returns boolean whether or not EMANE events will be monitored.
""" """
@ -649,7 +657,7 @@ class EmaneManager(ModelManager):
# generate the EMANE events when nodes are moved # generate the EMANE events when nodes are moved
return self.session.options.get_config_bool("emane_event_monitor") return self.session.options.get_config_bool("emane_event_monitor")
def genlocationevents(self): def genlocationevents(self) -> bool:
""" """
Returns boolean whether or not EMANE events will be generated. Returns boolean whether or not EMANE events will be generated.
""" """
@ -660,7 +668,7 @@ class EmaneManager(ModelManager):
tmp = not self.doeventmonitor() tmp = not self.doeventmonitor()
return tmp return tmp
def starteventmonitor(self): def starteventmonitor(self) -> None:
""" """
Start monitoring EMANE location events if configured to do so. Start monitoring EMANE location events if configured to do so.
""" """
@ -681,7 +689,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.daemon = True self.eventmonthread.daemon = True
self.eventmonthread.start() self.eventmonthread.start()
def stopeventmonitor(self): def stopeventmonitor(self) -> None:
""" """
Stop monitoring EMANE location events. Stop monitoring EMANE location events.
""" """
@ -697,7 +705,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.join() self.eventmonthread.join()
self.eventmonthread = None self.eventmonthread = None
def eventmonitorloop(self): def eventmonitorloop(self) -> None:
""" """
Thread target that monitors EMANE location events. Thread target that monitors EMANE location events.
""" """
@ -724,7 +732,7 @@ class EmaneManager(ModelManager):
threading.currentThread().getName(), threading.currentThread().getName(),
) )
def handlelocationevent(self, rxnemid, eid, data): def handlelocationevent(self, rxnemid: int, eid: int, data: str) -> None:
""" """
Handle an EMANE location event. Handle an EMANE location event.
""" """
@ -747,7 +755,9 @@ class EmaneManager(ModelManager):
logging.debug("emane location event: %s,%s,%s", lat, lon, alt) logging.debug("emane location event: %s,%s,%s", lat, lon, alt)
self.handlelocationeventtoxyz(txnemid, lat, lon, alt) self.handlelocationeventtoxyz(txnemid, lat, lon, alt)
def handlelocationeventtoxyz(self, nemid, lat, lon, alt): def handlelocationeventtoxyz(
self, nemid: int, lat: float, lon: float, alt: float
) -> bool:
""" """
Convert the (NEM ID, lat, long, alt) from a received location event Convert the (NEM ID, lat, long, alt) from a received location event
into a node and x,y,z coordinate values, sending a Node Message. into a node and x,y,z coordinate values, sending a Node Message.
@ -800,11 +810,11 @@ class EmaneManager(ModelManager):
# don"t use node.setposition(x,y,z) which generates an event # don"t use node.setposition(x,y,z) which generates an event
node.position.set(x, y, z) node.position.set(x, y, z)
node_data = node.data(message_type=0, lat=str(lat), lon=str(lon), alt=str(alt)) node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt)
self.session.broadcast_node(node_data) self.session.broadcast_node(node_data)
return True return True
def emanerunning(self, node): def emanerunning(self, node: CoreNode) -> bool:
""" """
Return True if an EMANE process associated with the given node is running, Return True if an EMANE process associated with the given node is running,
False otherwise. False otherwise.
@ -827,7 +837,7 @@ class EmaneGlobalModel:
name = "emane" name = "emane"
bitmap = None bitmap = None
def __init__(self, session): def __init__(self, session: "Session") -> None:
self.session = session self.session = session
self.nem_config = [ self.nem_config = [
Configuration( Configuration(
@ -840,7 +850,7 @@ class EmaneGlobalModel:
self.emulator_config = None self.emulator_config = None
self.parse_config() self.parse_config()
def parse_config(self): def parse_config(self) -> None:
emane_prefix = self.session.options.get_config( emane_prefix = self.session.options.get_config(
"emane_prefix", default=DEFAULT_EMANE_PREFIX "emane_prefix", default=DEFAULT_EMANE_PREFIX
) )
@ -862,10 +872,10 @@ class EmaneGlobalModel:
), ),
) )
def configurations(self): def configurations(self) -> List[Configuration]:
return self.emulator_config + self.nem_config return self.emulator_config + self.nem_config
def config_groups(self): def config_groups(self) -> List[ConfigGroup]:
emulator_len = len(self.emulator_config) emulator_len = len(self.emulator_config)
config_len = len(self.configurations()) config_len = len(self.configurations())
return [ return [
@ -873,7 +883,7 @@ class EmaneGlobalModel:
ConfigGroup("NEM Parameters", emulator_len + 1, config_len), ConfigGroup("NEM Parameters", emulator_len + 1, config_len),
] ]
def default_values(self): def default_values(self) -> Dict[str, str]:
return OrderedDict( return OrderedDict(
[(config.id, config.default) for config in self.configurations()] [(config.id, config.default) for config in self.configurations()]
) )

View file

@ -1,4 +1,5 @@
import logging import logging
from typing import Dict, List
from core.config import Configuration from core.config import Configuration
from core.emulator.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
@ -13,12 +14,12 @@ except ImportError:
logging.debug("compatible emane python bindings not installed") logging.debug("compatible emane python bindings not installed")
def _type_value(config_type): def _type_value(config_type: str) -> ConfigDataTypes:
""" """
Convert emane configuration type to core configuration value. Convert emane configuration type to core configuration value.
:param str config_type: emane configuration type :param str config_type: emane configuration type
:return: :return: core config type
""" """
config_type = config_type.upper() config_type = config_type.upper()
if config_type == "DOUBLE": if config_type == "DOUBLE":
@ -28,7 +29,7 @@ def _type_value(config_type):
return ConfigDataTypes[config_type] return ConfigDataTypes[config_type]
def _get_possible(config_type, config_regex): def _get_possible(config_type: str, config_regex: str) -> List[str]:
""" """
Retrieve possible config value options based on emane regexes. Retrieve possible config value options based on emane regexes.
@ -47,7 +48,7 @@ def _get_possible(config_type, config_regex):
return [] return []
def _get_default(config_type_name, config_value): def _get_default(config_type_name: str, config_value: List[str]) -> str:
""" """
Convert default configuration values to one used by core. Convert default configuration values to one used by core.
@ -72,7 +73,7 @@ def _get_default(config_type_name, config_value):
return config_default return config_default
def parse(manifest_path, defaults): def parse(manifest_path: str, defaults: Dict[str, str]) -> List[Configuration]:
""" """
Parses a valid emane manifest file and converts the provided configuration values into ones used by core. Parses a valid emane manifest file and converts the provided configuration values into ones used by core.

View file

@ -3,12 +3,14 @@ Defines Emane Models used within CORE.
""" """
import logging import logging
import os import os
from typing import Dict, List
from core.config import ConfigGroup, Configuration from core.config import ConfigGroup, Configuration
from core.emane import emanemanifest from core.emane import emanemanifest
from core.emulator.enumerations import ConfigDataTypes from core.emulator.enumerations import ConfigDataTypes
from core.errors import CoreError from core.errors import CoreError
from core.location.mobility import WirelessModel from core.location.mobility import WirelessModel
from core.nodes.interface import CoreInterface
from core.xml import emanexml from core.xml import emanexml
@ -45,7 +47,7 @@ class EmaneModel(WirelessModel):
config_ignore = set() config_ignore = set()
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
""" """
Called after being loaded within the EmaneManager. Provides configured emane_prefix for Called after being loaded within the EmaneManager. Provides configured emane_prefix for
parsing xml files. parsing xml files.
@ -63,7 +65,7 @@ class EmaneModel(WirelessModel):
cls.phy_config = emanemanifest.parse(phy_xml_path, cls.phy_defaults) cls.phy_config = emanemanifest.parse(phy_xml_path, cls.phy_defaults)
@classmethod @classmethod
def configurations(cls): def configurations(cls) -> List[Configuration]:
""" """
Returns the combination all all configurations (mac, phy, and external). Returns the combination all all configurations (mac, phy, and external).
@ -73,7 +75,7 @@ class EmaneModel(WirelessModel):
return cls.mac_config + cls.phy_config + cls.external_config return cls.mac_config + cls.phy_config + cls.external_config
@classmethod @classmethod
def config_groups(cls): def config_groups(cls) -> List[ConfigGroup]:
""" """
Returns the defined configuration groups. Returns the defined configuration groups.
@ -89,10 +91,12 @@ class EmaneModel(WirelessModel):
ConfigGroup("External Parameters", phy_len + 1, config_len), ConfigGroup("External Parameters", phy_len + 1, config_len),
] ]
def build_xml_files(self, config, interface=None): def build_xml_files(
self, config: Dict[str, str], interface: CoreInterface = None
) -> None:
""" """
Builds xml files for this emane model. Creates a nem.xml file that points to both mac.xml and phy.xml Builds xml files for this emane model. Creates a nem.xml file that points to
definitions. both mac.xml and phy.xml definitions.
:param dict config: emane model configuration for the node and interface :param dict config: emane model configuration for the node and interface
:param interface: interface for the emane node :param interface: interface for the emane node
@ -127,7 +131,7 @@ class EmaneModel(WirelessModel):
phy_file = os.path.join(self.session.session_dir, phy_name) phy_file = os.path.join(self.session.session_dir, phy_name)
emanexml.create_phy_xml(self, config, phy_file, server) emanexml.create_phy_xml(self, config, phy_file, server)
def post_startup(self): def post_startup(self) -> None:
""" """
Logic to execute after the emane manager is finished with startup. Logic to execute after the emane manager is finished with startup.
@ -135,7 +139,7 @@ class EmaneModel(WirelessModel):
""" """
logging.debug("emane model(%s) has no post setup tasks", self.name) logging.debug("emane model(%s) has no post setup tasks", self.name)
def update(self, moved, moved_netifs): def update(self, moved: bool, moved_netifs: List[CoreInterface]) -> None:
""" """
Invoked from MobilityModel when nodes are moved; this causes Invoked from MobilityModel when nodes are moved; this causes
emane location events to be generated for the nodes in the moved emane location events to be generated for the nodes in the moved
@ -143,7 +147,7 @@ class EmaneModel(WirelessModel):
:param bool moved: were nodes moved :param bool moved: were nodes moved
:param list moved_netifs: interfaces that were moved :param list moved_netifs: interfaces that were moved
:return: :return: nothing
""" """
try: try:
wlan = self.session.get_node(self.id) wlan = self.session.get_node(self.id)
@ -153,14 +157,14 @@ class EmaneModel(WirelessModel):
def linkconfig( def linkconfig(
self, self,
netif, netif: CoreInterface,
bw=None, bw: float = None,
delay=None, delay: float = None,
loss=None, loss: float = None,
duplicate=None, duplicate: float = None,
jitter=None, jitter: float = None,
netif2=None, netif2: CoreInterface = None,
): ) -> None:
""" """
Invoked when a Link Message is received. Default is unimplemented. Invoked when a Link Message is received. Default is unimplemented.

View file

@ -15,7 +15,7 @@ class EmaneIeee80211abgModel(emanemodel.EmaneModel):
mac_xml = "ieee80211abgmaclayer.xml" mac_xml = "ieee80211abgmaclayer.xml"
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join( cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix, "share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml" emane_prefix, "share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml"
) )

View file

@ -4,9 +4,18 @@ share the same MAC+PHY model.
""" """
import logging import logging
from typing import TYPE_CHECKING, Dict, List, Optional, Type
from core.emulator.distributed import DistributedServer
from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs from core.emulator.enumerations import LinkTypes, NodeTypes, RegisterTlvs
from core.nodes.base import CoreNetworkBase from core.nodes.base import CoreNetworkBase
from core.nodes.interface import CoreInterface
if TYPE_CHECKING:
from core.emulator.session import Session
from core.location.mobility import WirelessModel
WirelessModelType = Type[WirelessModel]
try: try:
from emane.events import LocationEvent from emane.events import LocationEvent
@ -29,7 +38,14 @@ class EmaneNet(CoreNetworkBase):
type = "wlan" type = "wlan"
is_emane = True is_emane = True
def __init__(self, session, _id=None, name=None, start=True, server=None): def __init__(
self,
session: "Session",
_id: int = None,
name: str = None,
start: bool = True,
server: DistributedServer = None,
) -> None:
super().__init__(session, _id, name, start, server) super().__init__(session, _id, name, start, server)
self.conf = "" self.conf = ""
self.up = False self.up = False
@ -39,20 +55,20 @@ class EmaneNet(CoreNetworkBase):
def linkconfig( def linkconfig(
self, self,
netif, netif: CoreInterface,
bw=None, bw: float = None,
delay=None, delay: float = None,
loss=None, loss: float = None,
duplicate=None, duplicate: float = None,
jitter=None, jitter: float = None,
netif2=None, netif2: CoreInterface = None,
): ) -> None:
""" """
The CommEffect model supports link configuration. The CommEffect model supports link configuration.
""" """
if not self.model: if not self.model:
return return
return self.model.linkconfig( self.model.linkconfig(
netif=netif, netif=netif,
bw=bw, bw=bw,
delay=delay, delay=delay,
@ -62,19 +78,19 @@ class EmaneNet(CoreNetworkBase):
netif2=netif2, netif2=netif2,
) )
def config(self, conf): def config(self, conf: str) -> None:
self.conf = conf self.conf = conf
def shutdown(self): def shutdown(self) -> None:
pass pass
def link(self, netif1, netif2): def link(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
pass pass
def unlink(self, netif1, netif2): def unlink(self, netif1: CoreInterface, netif2: CoreInterface) -> None:
pass pass
def updatemodel(self, config): def updatemodel(self, config: Dict[str, str]) -> None:
if not self.model: if not self.model:
raise ValueError("no model set to update for node(%s)", self.id) raise ValueError("no model set to update for node(%s)", self.id)
logging.info( logging.info(
@ -82,7 +98,7 @@ class EmaneNet(CoreNetworkBase):
) )
self.model.set_configs(config, node_id=self.id) self.model.set_configs(config, node_id=self.id)
def setmodel(self, model, config): def setmodel(self, model: "WirelessModelType", config: Dict[str, str]) -> None:
""" """
set the EmaneModel associated with this node set the EmaneModel associated with this node
""" """
@ -96,14 +112,14 @@ class EmaneNet(CoreNetworkBase):
self.mobility = model(session=self.session, _id=self.id) self.mobility = model(session=self.session, _id=self.id)
self.mobility.update_config(config) self.mobility.update_config(config)
def setnemid(self, netif, nemid): def setnemid(self, netif: CoreInterface, nemid: int) -> None:
""" """
Record an interface to numerical ID mapping. The Emane controller Record an interface to numerical ID mapping. The Emane controller
object manages and assigns these IDs for all NEMs. object manages and assigns these IDs for all NEMs.
""" """
self.nemidmap[netif] = nemid self.nemidmap[netif] = nemid
def getnemid(self, netif): def getnemid(self, netif: CoreInterface) -> Optional[int]:
""" """
Given an interface, return its numerical ID. Given an interface, return its numerical ID.
""" """
@ -112,7 +128,7 @@ class EmaneNet(CoreNetworkBase):
else: else:
return self.nemidmap[netif] return self.nemidmap[netif]
def getnemnetif(self, nemid): def getnemnetif(self, nemid: int) -> Optional[CoreInterface]:
""" """
Given a numerical NEM ID, return its interface. This returns the Given a numerical NEM ID, return its interface. This returns the
first interface that matches the given NEM ID. first interface that matches the given NEM ID.
@ -122,13 +138,13 @@ class EmaneNet(CoreNetworkBase):
return netif return netif
return None return None
def netifs(self, sort=True): def netifs(self, sort: bool = True) -> List[CoreInterface]:
""" """
Retrieve list of linked interfaces sorted by node number. Retrieve list of linked interfaces sorted by node number.
""" """
return sorted(self._netif.values(), key=lambda ifc: ifc.node.id) return sorted(self._netif.values(), key=lambda ifc: ifc.node.id)
def installnetifs(self): def installnetifs(self) -> None:
""" """
Install TAP devices into their namespaces. This is done after Install TAP devices into their namespaces. This is done after
EMANE daemons have been started, because that is their only chance EMANE daemons have been started, because that is their only chance
@ -159,7 +175,7 @@ class EmaneNet(CoreNetworkBase):
x, y, z = netif.node.position.get() x, y, z = netif.node.position.get()
self.setnemposition(netif, x, y, z) self.setnemposition(netif, x, y, z)
def deinstallnetifs(self): def deinstallnetifs(self) -> None:
""" """
Uninstall TAP devices. This invokes their shutdown method for Uninstall TAP devices. This invokes their shutdown method for
any required cleanup; the device may be actually removed when any required cleanup; the device may be actually removed when
@ -170,7 +186,9 @@ class EmaneNet(CoreNetworkBase):
netif.shutdown() netif.shutdown()
netif.poshook = None netif.poshook = None
def setnemposition(self, netif, x, y, z): def setnemposition(
self, netif: CoreInterface, x: float, y: float, z: float
) -> None:
""" """
Publish a NEM location change event using the EMANE event service. Publish a NEM location change event using the EMANE event service.
""" """
@ -191,7 +209,7 @@ class EmaneNet(CoreNetworkBase):
event.append(nemid, latitude=lat, longitude=lon, altitude=alt) event.append(nemid, latitude=lat, longitude=lon, altitude=alt)
self.session.emane.service.publish(0, event) self.session.emane.service.publish(0, event)
def setnempositions(self, moved_netifs): def setnempositions(self, moved_netifs: List[CoreInterface]) -> None:
""" """
Several NEMs have moved, from e.g. a WaypointMobilityModel Several NEMs have moved, from e.g. a WaypointMobilityModel
calculation. Generate an EMANE Location Event having several calculation. Generate an EMANE Location Event having several

View file

@ -15,7 +15,7 @@ class EmaneRfPipeModel(emanemodel.EmaneModel):
mac_xml = "rfpipemaclayer.xml" mac_xml = "rfpipemaclayer.xml"
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join( cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix, "share/emane/xml/models/mac/rfpipe/rfpipepcr.xml" emane_prefix, "share/emane/xml/models/mac/rfpipe/rfpipepcr.xml"
) )

View file

@ -27,7 +27,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
config_ignore = {schedule_name} config_ignore = {schedule_name}
@classmethod @classmethod
def load(cls, emane_prefix): def load(cls, emane_prefix: str) -> None:
cls.mac_defaults["pcrcurveuri"] = os.path.join( cls.mac_defaults["pcrcurveuri"] = os.path.join(
emane_prefix, emane_prefix,
"share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml", "share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml",
@ -43,7 +43,7 @@ class EmaneTdmaModel(emanemodel.EmaneModel):
), ),
) )
def post_startup(self): def post_startup(self) -> None:
""" """
Logic to execute after the emane manager is finished with startup. Logic to execute after the emane manager is finished with startup.