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

@ -6,6 +6,7 @@ import logging
import os
import threading
from collections import OrderedDict
from typing import TYPE_CHECKING, Dict, List, Set, Tuple, Type
from core import utils
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.emulator.enumerations import ConfigDataTypes, RegisterTlvs
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
if TYPE_CHECKING:
from core.emulator.session import Session
try:
from emane.events import EventService
from emane.events import LocationEvent
@ -57,7 +65,7 @@ class EmaneManager(ModelManager):
EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG"
DEFAULT_LOG_LEVEL = 3
def __init__(self, session):
def __init__(self, session: "Session") -> None:
"""
Creates a Emane instance.
@ -86,7 +94,9 @@ class EmaneManager(ModelManager):
self.event_device = None
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.
@ -129,11 +139,11 @@ class EmaneManager(ModelManager):
return config
def config_reset(self, node_id=None):
def config_reset(self, node_id: int = None) -> None:
super().config_reset(node_id)
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.
@ -157,7 +167,7 @@ class EmaneManager(ModelManager):
except CoreCommandError:
logging.info("emane is not installed")
def deleteeventservice(self):
def deleteeventservice(self) -> None:
if self.service:
for fd in self.service._readFd, self.service._writeFd:
if fd >= 0:
@ -168,7 +178,7 @@ class EmaneManager(ModelManager):
self.service = 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.
The multicast group and/or port may be configured.
@ -186,7 +196,7 @@ class EmaneManager(ModelManager):
logging.error(
"invalid emane event service device provided: %s", self.event_device
)
return False
return
# make sure the event control network is in place
eventnet = self.session.add_remove_control_net(
@ -205,9 +215,7 @@ class EmaneManager(ModelManager):
except EventServiceException:
logging.exception("error instantiating emane EventService")
return True
def load_models(self, emane_models):
def load_models(self, emane_models: List[Type[EmaneModel]]) -> None:
"""
Load EMANE models and make them available.
"""
@ -219,7 +227,7 @@ class EmaneManager(ModelManager):
emane_model.load(emane_prefix)
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.
@ -233,7 +241,7 @@ class EmaneManager(ModelManager):
)
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,
e.g. containers having one or more radio interfaces.
@ -245,7 +253,7 @@ class EmaneManager(ModelManager):
nodes.add(netif.node)
return nodes
def setup(self):
def setup(self) -> int:
"""
Setup duties for EMANE manager.
@ -303,7 +311,7 @@ class EmaneManager(ModelManager):
self.check_node_models()
return EmaneManager.SUCCESS
def startup(self):
def startup(self) -> int:
"""
After all the EMANE networks have been added, build XML files
and start the daemons.
@ -347,7 +355,7 @@ class EmaneManager(ModelManager):
return EmaneManager.SUCCESS
def poststartup(self):
def poststartup(self) -> None:
"""
Retransmit location events now that all NEMs are active.
"""
@ -367,7 +375,7 @@ class EmaneManager(ModelManager):
x, y, z = netif.node.position.get()
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
nem id counters
@ -382,7 +390,7 @@ class EmaneManager(ModelManager):
"emane_transform_port", 8200
)
def shutdown(self):
def shutdown(self) -> None:
"""
stop all EMANE daemons
"""
@ -394,7 +402,7 @@ class EmaneManager(ModelManager):
self.stopdaemons()
self.stopeventmonitor()
def buildxml(self):
def buildxml(self) -> None:
"""
Build XML files required to run EMANE on each node.
NEMs run inside containers using the control network for passing
@ -410,7 +418,7 @@ class EmaneManager(ModelManager):
self.buildnemxml()
self.buildeventservicexml()
def check_node_models(self):
def check_node_models(self) -> None:
"""
Associate EMANE model classes with EMANE network nodes.
"""
@ -438,7 +446,7 @@ class EmaneManager(ModelManager):
model_class = self.models[model_name]
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
EMANE network and NEM interface.
@ -456,7 +464,7 @@ class EmaneManager(ModelManager):
return emane_node, netif
def numnems(self):
def numnems(self) -> int:
"""
Return the number of NEMs emulated locally.
"""
@ -466,7 +474,7 @@ class EmaneManager(ModelManager):
count += len(emane_node.netifs())
return count
def buildplatformxml(self, ctrlnet):
def buildplatformxml(self, ctrlnet: CtrlNet) -> None:
"""
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
)
def buildnemxml(self):
def buildnemxml(self) -> None:
"""
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]
emanexml.build_xml_files(self, emane_net)
def buildeventservicexml(self):
def buildeventservicexml(self) -> None:
"""
Build the libemaneeventservice.xml file if event service options
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.
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))
logging.info("host emane daemon running: %s", emanecmd)
def stopdaemons(self):
def stopdaemons(self) -> None:
"""
Kill the appropriate EMANE daemons.
"""
@ -623,7 +631,7 @@ class EmaneManager(ModelManager):
except CoreCommandError:
logging.exception("error shutting down emane daemons")
def installnetifs(self):
def installnetifs(self) -> None:
"""
Install TUN/TAP virtual interfaces into their proper namespaces
now that the EMANE daemons are running.
@ -633,7 +641,7 @@ class EmaneManager(ModelManager):
logging.info("emane install netifs for node: %d", key)
emane_node.installnetifs()
def deinstallnetifs(self):
def deinstallnetifs(self) -> None:
"""
Uninstall TUN/TAP virtual interfaces.
"""
@ -641,7 +649,7 @@ class EmaneManager(ModelManager):
emane_node = self._emane_nets[key]
emane_node.deinstallnetifs()
def doeventmonitor(self):
def doeventmonitor(self) -> bool:
"""
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
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.
"""
@ -660,7 +668,7 @@ class EmaneManager(ModelManager):
tmp = not self.doeventmonitor()
return tmp
def starteventmonitor(self):
def starteventmonitor(self) -> None:
"""
Start monitoring EMANE location events if configured to do so.
"""
@ -681,7 +689,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.daemon = True
self.eventmonthread.start()
def stopeventmonitor(self):
def stopeventmonitor(self) -> None:
"""
Stop monitoring EMANE location events.
"""
@ -697,7 +705,7 @@ class EmaneManager(ModelManager):
self.eventmonthread.join()
self.eventmonthread = None
def eventmonitorloop(self):
def eventmonitorloop(self) -> None:
"""
Thread target that monitors EMANE location events.
"""
@ -724,7 +732,7 @@ class EmaneManager(ModelManager):
threading.currentThread().getName(),
)
def handlelocationevent(self, rxnemid, eid, data):
def handlelocationevent(self, rxnemid: int, eid: int, data: str) -> None:
"""
Handle an EMANE location event.
"""
@ -747,7 +755,9 @@ class EmaneManager(ModelManager):
logging.debug("emane location event: %s,%s,%s", 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
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
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)
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,
False otherwise.
@ -827,7 +837,7 @@ class EmaneGlobalModel:
name = "emane"
bitmap = None
def __init__(self, session):
def __init__(self, session: "Session") -> None:
self.session = session
self.nem_config = [
Configuration(
@ -840,7 +850,7 @@ class EmaneGlobalModel:
self.emulator_config = None
self.parse_config()
def parse_config(self):
def parse_config(self) -> None:
emane_prefix = self.session.options.get_config(
"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
def config_groups(self):
def config_groups(self) -> List[ConfigGroup]:
emulator_len = len(self.emulator_config)
config_len = len(self.configurations())
return [
@ -873,7 +883,7 @@ class EmaneGlobalModel:
ConfigGroup("NEM Parameters", emulator_len + 1, config_len),
]
def default_values(self):
def default_values(self) -> Dict[str, str]:
return OrderedDict(
[(config.id, config.default) for config in self.configurations()]
)