added type hinting to core.xml
This commit is contained in:
parent
02156867e2
commit
8cd8b2ae2c
3 changed files with 178 additions and 93 deletions
|
@ -1,17 +1,30 @@
|
||||||
import logging
|
import logging
|
||||||
|
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Optional, Type, TypeVar
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
import core.nodes.base
|
import core.nodes.base
|
||||||
import core.nodes.physical
|
import core.nodes.physical
|
||||||
from core.emane.nodes import EmaneNet
|
from core.emane.nodes import EmaneNet
|
||||||
|
from core.emulator.data import LinkData
|
||||||
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
from core.emulator.emudata import InterfaceData, LinkOptions, NodeOptions
|
||||||
from core.emulator.enumerations import NodeTypes
|
from core.emulator.enumerations import NodeTypes
|
||||||
from core.nodes.base import CoreNetworkBase
|
from core.nodes.base import CoreNetworkBase, NodeBase
|
||||||
from core.nodes.network import CtrlNet
|
from core.nodes.network import CtrlNet
|
||||||
|
from core.services.coreservices import CoreService
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from core.emane.emanemanager import EmaneGlobalModel
|
||||||
|
from core.emane.emanemodel import EmaneModel
|
||||||
|
from core.emulator.session import Session
|
||||||
|
|
||||||
|
EmaneModelType = Type[EmaneModel]
|
||||||
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
def write_xml_file(xml_element, file_path, doctype=None):
|
def write_xml_file(
|
||||||
|
xml_element: etree.Element, file_path: str, doctype: str = None
|
||||||
|
) -> None:
|
||||||
xml_data = etree.tostring(
|
xml_data = etree.tostring(
|
||||||
xml_element,
|
xml_element,
|
||||||
xml_declaration=True,
|
xml_declaration=True,
|
||||||
|
@ -23,27 +36,27 @@ def write_xml_file(xml_element, file_path, doctype=None):
|
||||||
xml_file.write(xml_data)
|
xml_file.write(xml_data)
|
||||||
|
|
||||||
|
|
||||||
def get_type(element, name, _type):
|
def get_type(element: etree.Element, name: str, _type: Generic[T]) -> Optional[T]:
|
||||||
value = element.get(name)
|
value = element.get(name)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
value = _type(value)
|
value = _type(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def get_float(element, name):
|
def get_float(element: etree.Element, name: str) -> float:
|
||||||
return get_type(element, name, float)
|
return get_type(element, name, float)
|
||||||
|
|
||||||
|
|
||||||
def get_int(element, name):
|
def get_int(element: etree.Element, name: str) -> int:
|
||||||
return get_type(element, name, int)
|
return get_type(element, name, int)
|
||||||
|
|
||||||
|
|
||||||
def add_attribute(element, name, value):
|
def add_attribute(element: etree.Element, name: str, value: Any) -> None:
|
||||||
if value is not None:
|
if value is not None:
|
||||||
element.set(name, str(value))
|
element.set(name, str(value))
|
||||||
|
|
||||||
|
|
||||||
def create_interface_data(interface_element):
|
def create_interface_data(interface_element: etree.Element) -> InterfaceData:
|
||||||
interface_id = int(interface_element.get("id"))
|
interface_id = int(interface_element.get("id"))
|
||||||
name = interface_element.get("name")
|
name = interface_element.get("name")
|
||||||
mac = interface_element.get("mac")
|
mac = interface_element.get("mac")
|
||||||
|
@ -54,7 +67,9 @@ def create_interface_data(interface_element):
|
||||||
return InterfaceData(interface_id, name, mac, ip4, ip4_mask, ip6, ip6_mask)
|
return InterfaceData(interface_id, name, mac, ip4, ip4_mask, ip6, ip6_mask)
|
||||||
|
|
||||||
|
|
||||||
def create_emane_config(node_id, emane_config, config):
|
def create_emane_config(
|
||||||
|
node_id: int, emane_config: "EmaneGlobalModel", config: Dict[str, str]
|
||||||
|
) -> etree.Element:
|
||||||
emane_configuration = etree.Element("emane_configuration")
|
emane_configuration = etree.Element("emane_configuration")
|
||||||
add_attribute(emane_configuration, "node", node_id)
|
add_attribute(emane_configuration, "node", node_id)
|
||||||
add_attribute(emane_configuration, "model", "emane")
|
add_attribute(emane_configuration, "model", "emane")
|
||||||
|
@ -72,7 +87,9 @@ def create_emane_config(node_id, emane_config, config):
|
||||||
return emane_configuration
|
return emane_configuration
|
||||||
|
|
||||||
|
|
||||||
def create_emane_model_config(node_id, model, config):
|
def create_emane_model_config(
|
||||||
|
node_id: int, model: "EmaneModelType", config: Dict[str, str]
|
||||||
|
) -> etree.Element:
|
||||||
emane_element = etree.Element("emane_configuration")
|
emane_element = etree.Element("emane_configuration")
|
||||||
add_attribute(emane_element, "node", node_id)
|
add_attribute(emane_element, "node", node_id)
|
||||||
add_attribute(emane_element, "model", model.name)
|
add_attribute(emane_element, "model", model.name)
|
||||||
|
@ -95,14 +112,14 @@ def create_emane_model_config(node_id, model, config):
|
||||||
return emane_element
|
return emane_element
|
||||||
|
|
||||||
|
|
||||||
def add_configuration(parent, name, value):
|
def add_configuration(parent: etree.Element, name: str, value: str) -> None:
|
||||||
config_element = etree.SubElement(parent, "configuration")
|
config_element = etree.SubElement(parent, "configuration")
|
||||||
add_attribute(config_element, "name", name)
|
add_attribute(config_element, "name", name)
|
||||||
add_attribute(config_element, "value", value)
|
add_attribute(config_element, "value", value)
|
||||||
|
|
||||||
|
|
||||||
class NodeElement:
|
class NodeElement:
|
||||||
def __init__(self, session, node, element_name):
|
def __init__(self, session: "Session", node: NodeBase, element_name: str) -> None:
|
||||||
self.session = session
|
self.session = session
|
||||||
self.node = node
|
self.node = node
|
||||||
self.element = etree.Element(element_name)
|
self.element = etree.Element(element_name)
|
||||||
|
@ -112,7 +129,7 @@ class NodeElement:
|
||||||
add_attribute(self.element, "canvas", node.canvas)
|
add_attribute(self.element, "canvas", node.canvas)
|
||||||
self.add_position()
|
self.add_position()
|
||||||
|
|
||||||
def add_position(self):
|
def add_position(self) -> None:
|
||||||
x = self.node.position.x
|
x = self.node.position.x
|
||||||
y = self.node.position.y
|
y = self.node.position.y
|
||||||
z = self.node.position.z
|
z = self.node.position.z
|
||||||
|
@ -129,7 +146,7 @@ class NodeElement:
|
||||||
|
|
||||||
|
|
||||||
class ServiceElement:
|
class ServiceElement:
|
||||||
def __init__(self, service):
|
def __init__(self, service: Type[CoreService]) -> None:
|
||||||
self.service = service
|
self.service = service
|
||||||
self.element = etree.Element("service")
|
self.element = etree.Element("service")
|
||||||
add_attribute(self.element, "name", service.name)
|
add_attribute(self.element, "name", service.name)
|
||||||
|
@ -139,7 +156,7 @@ class ServiceElement:
|
||||||
self.add_shutdown()
|
self.add_shutdown()
|
||||||
self.add_files()
|
self.add_files()
|
||||||
|
|
||||||
def add_directories(self):
|
def add_directories(self) -> None:
|
||||||
# get custom directories
|
# get custom directories
|
||||||
directories = etree.Element("directories")
|
directories = etree.Element("directories")
|
||||||
for directory in self.service.dirs:
|
for directory in self.service.dirs:
|
||||||
|
@ -149,7 +166,7 @@ class ServiceElement:
|
||||||
if directories.getchildren():
|
if directories.getchildren():
|
||||||
self.element.append(directories)
|
self.element.append(directories)
|
||||||
|
|
||||||
def add_files(self):
|
def add_files(self) -> None:
|
||||||
# get custom files
|
# get custom files
|
||||||
file_elements = etree.Element("files")
|
file_elements = etree.Element("files")
|
||||||
for file_name in self.service.config_data:
|
for file_name in self.service.config_data:
|
||||||
|
@ -161,7 +178,7 @@ class ServiceElement:
|
||||||
if file_elements.getchildren():
|
if file_elements.getchildren():
|
||||||
self.element.append(file_elements)
|
self.element.append(file_elements)
|
||||||
|
|
||||||
def add_startup(self):
|
def add_startup(self) -> None:
|
||||||
# get custom startup
|
# get custom startup
|
||||||
startup_elements = etree.Element("startups")
|
startup_elements = etree.Element("startups")
|
||||||
for startup in self.service.startup:
|
for startup in self.service.startup:
|
||||||
|
@ -171,7 +188,7 @@ class ServiceElement:
|
||||||
if startup_elements.getchildren():
|
if startup_elements.getchildren():
|
||||||
self.element.append(startup_elements)
|
self.element.append(startup_elements)
|
||||||
|
|
||||||
def add_validate(self):
|
def add_validate(self) -> None:
|
||||||
# get custom validate
|
# get custom validate
|
||||||
validate_elements = etree.Element("validates")
|
validate_elements = etree.Element("validates")
|
||||||
for validate in self.service.validate:
|
for validate in self.service.validate:
|
||||||
|
@ -181,7 +198,7 @@ class ServiceElement:
|
||||||
if validate_elements.getchildren():
|
if validate_elements.getchildren():
|
||||||
self.element.append(validate_elements)
|
self.element.append(validate_elements)
|
||||||
|
|
||||||
def add_shutdown(self):
|
def add_shutdown(self) -> None:
|
||||||
# get custom shutdown
|
# get custom shutdown
|
||||||
shutdown_elements = etree.Element("shutdowns")
|
shutdown_elements = etree.Element("shutdowns")
|
||||||
for shutdown in self.service.shutdown:
|
for shutdown in self.service.shutdown:
|
||||||
|
@ -193,12 +210,12 @@ class ServiceElement:
|
||||||
|
|
||||||
|
|
||||||
class DeviceElement(NodeElement):
|
class DeviceElement(NodeElement):
|
||||||
def __init__(self, session, node):
|
def __init__(self, session: "Session", node: NodeBase) -> None:
|
||||||
super().__init__(session, node, "device")
|
super().__init__(session, node, "device")
|
||||||
add_attribute(self.element, "type", node.type)
|
add_attribute(self.element, "type", node.type)
|
||||||
self.add_services()
|
self.add_services()
|
||||||
|
|
||||||
def add_services(self):
|
def add_services(self) -> None:
|
||||||
service_elements = etree.Element("services")
|
service_elements = etree.Element("services")
|
||||||
for service in self.node.services:
|
for service in self.node.services:
|
||||||
etree.SubElement(service_elements, "service", name=service.name)
|
etree.SubElement(service_elements, "service", name=service.name)
|
||||||
|
@ -208,7 +225,7 @@ class DeviceElement(NodeElement):
|
||||||
|
|
||||||
|
|
||||||
class NetworkElement(NodeElement):
|
class NetworkElement(NodeElement):
|
||||||
def __init__(self, session, node):
|
def __init__(self, session: "Session", node: NodeBase) -> None:
|
||||||
super().__init__(session, node, "network")
|
super().__init__(session, node, "network")
|
||||||
model = getattr(self.node, "model", None)
|
model = getattr(self.node, "model", None)
|
||||||
if model:
|
if model:
|
||||||
|
@ -221,7 +238,7 @@ class NetworkElement(NodeElement):
|
||||||
add_attribute(self.element, "grekey", grekey)
|
add_attribute(self.element, "grekey", grekey)
|
||||||
self.add_type()
|
self.add_type()
|
||||||
|
|
||||||
def add_type(self):
|
def add_type(self) -> None:
|
||||||
if self.node.apitype:
|
if self.node.apitype:
|
||||||
node_type = NodeTypes(self.node.apitype).name
|
node_type = NodeTypes(self.node.apitype).name
|
||||||
else:
|
else:
|
||||||
|
@ -230,14 +247,14 @@ class NetworkElement(NodeElement):
|
||||||
|
|
||||||
|
|
||||||
class CoreXmlWriter:
|
class CoreXmlWriter:
|
||||||
def __init__(self, session):
|
def __init__(self, session: "Session") -> None:
|
||||||
self.session = session
|
self.session = session
|
||||||
self.scenario = etree.Element("scenario")
|
self.scenario = etree.Element("scenario")
|
||||||
self.networks = None
|
self.networks = None
|
||||||
self.devices = None
|
self.devices = None
|
||||||
self.write_session()
|
self.write_session()
|
||||||
|
|
||||||
def write_session(self):
|
def write_session(self) -> None:
|
||||||
# generate xml content
|
# generate xml content
|
||||||
links = self.write_nodes()
|
links = self.write_nodes()
|
||||||
self.write_links(links)
|
self.write_links(links)
|
||||||
|
@ -250,7 +267,7 @@ class CoreXmlWriter:
|
||||||
self.write_session_metadata()
|
self.write_session_metadata()
|
||||||
self.write_default_services()
|
self.write_default_services()
|
||||||
|
|
||||||
def write(self, file_name):
|
def write(self, file_name: str) -> None:
|
||||||
self.scenario.set("name", file_name)
|
self.scenario.set("name", file_name)
|
||||||
|
|
||||||
# write out generated xml
|
# write out generated xml
|
||||||
|
@ -259,7 +276,7 @@ class CoreXmlWriter:
|
||||||
file_name, xml_declaration=True, pretty_print=True, encoding="UTF-8"
|
file_name, xml_declaration=True, pretty_print=True, encoding="UTF-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
def write_session_origin(self):
|
def write_session_origin(self) -> None:
|
||||||
# origin: geolocation of cartesian coordinate 0,0,0
|
# origin: geolocation of cartesian coordinate 0,0,0
|
||||||
lat, lon, alt = self.session.location.refgeo
|
lat, lon, alt = self.session.location.refgeo
|
||||||
origin = etree.Element("session_origin")
|
origin = etree.Element("session_origin")
|
||||||
|
@ -279,7 +296,7 @@ class CoreXmlWriter:
|
||||||
add_attribute(origin, "y", y)
|
add_attribute(origin, "y", y)
|
||||||
add_attribute(origin, "z", z)
|
add_attribute(origin, "z", z)
|
||||||
|
|
||||||
def write_session_hooks(self):
|
def write_session_hooks(self) -> None:
|
||||||
# hook scripts
|
# hook scripts
|
||||||
hooks = etree.Element("session_hooks")
|
hooks = etree.Element("session_hooks")
|
||||||
for state in sorted(self.session._hooks.keys()):
|
for state in sorted(self.session._hooks.keys()):
|
||||||
|
@ -292,7 +309,7 @@ class CoreXmlWriter:
|
||||||
if hooks.getchildren():
|
if hooks.getchildren():
|
||||||
self.scenario.append(hooks)
|
self.scenario.append(hooks)
|
||||||
|
|
||||||
def write_session_options(self):
|
def write_session_options(self) -> None:
|
||||||
option_elements = etree.Element("session_options")
|
option_elements = etree.Element("session_options")
|
||||||
options_config = self.session.options.get_configs()
|
options_config = self.session.options.get_configs()
|
||||||
if not options_config:
|
if not options_config:
|
||||||
|
@ -307,7 +324,7 @@ class CoreXmlWriter:
|
||||||
if option_elements.getchildren():
|
if option_elements.getchildren():
|
||||||
self.scenario.append(option_elements)
|
self.scenario.append(option_elements)
|
||||||
|
|
||||||
def write_session_metadata(self):
|
def write_session_metadata(self) -> None:
|
||||||
# metadata
|
# metadata
|
||||||
metadata_elements = etree.Element("session_metadata")
|
metadata_elements = etree.Element("session_metadata")
|
||||||
config = self.session.metadata
|
config = self.session.metadata
|
||||||
|
@ -321,7 +338,7 @@ class CoreXmlWriter:
|
||||||
if metadata_elements.getchildren():
|
if metadata_elements.getchildren():
|
||||||
self.scenario.append(metadata_elements)
|
self.scenario.append(metadata_elements)
|
||||||
|
|
||||||
def write_emane_configs(self):
|
def write_emane_configs(self) -> None:
|
||||||
emane_configurations = etree.Element("emane_configurations")
|
emane_configurations = etree.Element("emane_configurations")
|
||||||
for node_id in self.session.emane.nodes():
|
for node_id in self.session.emane.nodes():
|
||||||
all_configs = self.session.emane.get_all_configs(node_id)
|
all_configs = self.session.emane.get_all_configs(node_id)
|
||||||
|
@ -347,7 +364,7 @@ class CoreXmlWriter:
|
||||||
if emane_configurations.getchildren():
|
if emane_configurations.getchildren():
|
||||||
self.scenario.append(emane_configurations)
|
self.scenario.append(emane_configurations)
|
||||||
|
|
||||||
def write_mobility_configs(self):
|
def write_mobility_configs(self) -> None:
|
||||||
mobility_configurations = etree.Element("mobility_configurations")
|
mobility_configurations = etree.Element("mobility_configurations")
|
||||||
for node_id in self.session.mobility.nodes():
|
for node_id in self.session.mobility.nodes():
|
||||||
all_configs = self.session.mobility.get_all_configs(node_id)
|
all_configs = self.session.mobility.get_all_configs(node_id)
|
||||||
|
@ -371,7 +388,7 @@ class CoreXmlWriter:
|
||||||
if mobility_configurations.getchildren():
|
if mobility_configurations.getchildren():
|
||||||
self.scenario.append(mobility_configurations)
|
self.scenario.append(mobility_configurations)
|
||||||
|
|
||||||
def write_service_configs(self):
|
def write_service_configs(self) -> None:
|
||||||
service_configurations = etree.Element("service_configurations")
|
service_configurations = etree.Element("service_configurations")
|
||||||
service_configs = self.session.services.all_configs()
|
service_configs = self.session.services.all_configs()
|
||||||
for node_id, service in service_configs:
|
for node_id, service in service_configs:
|
||||||
|
@ -382,7 +399,7 @@ class CoreXmlWriter:
|
||||||
if service_configurations.getchildren():
|
if service_configurations.getchildren():
|
||||||
self.scenario.append(service_configurations)
|
self.scenario.append(service_configurations)
|
||||||
|
|
||||||
def write_default_services(self):
|
def write_default_services(self) -> None:
|
||||||
node_types = etree.Element("default_services")
|
node_types = etree.Element("default_services")
|
||||||
for node_type in self.session.services.default_services:
|
for node_type in self.session.services.default_services:
|
||||||
services = self.session.services.default_services[node_type]
|
services = self.session.services.default_services[node_type]
|
||||||
|
@ -393,7 +410,7 @@ class CoreXmlWriter:
|
||||||
if node_types.getchildren():
|
if node_types.getchildren():
|
||||||
self.scenario.append(node_types)
|
self.scenario.append(node_types)
|
||||||
|
|
||||||
def write_nodes(self):
|
def write_nodes(self) -> List[LinkData]:
|
||||||
self.networks = etree.SubElement(self.scenario, "networks")
|
self.networks = etree.SubElement(self.scenario, "networks")
|
||||||
self.devices = etree.SubElement(self.scenario, "devices")
|
self.devices = etree.SubElement(self.scenario, "devices")
|
||||||
|
|
||||||
|
@ -416,7 +433,7 @@ class CoreXmlWriter:
|
||||||
|
|
||||||
return links
|
return links
|
||||||
|
|
||||||
def write_network(self, node):
|
def write_network(self, node: NodeBase) -> None:
|
||||||
# ignore p2p and other nodes that are not part of the api
|
# ignore p2p and other nodes that are not part of the api
|
||||||
if not node.apitype:
|
if not node.apitype:
|
||||||
return
|
return
|
||||||
|
@ -424,7 +441,7 @@ class CoreXmlWriter:
|
||||||
network = NetworkElement(self.session, node)
|
network = NetworkElement(self.session, node)
|
||||||
self.networks.append(network.element)
|
self.networks.append(network.element)
|
||||||
|
|
||||||
def write_links(self, links):
|
def write_links(self, links: List[LinkData]) -> None:
|
||||||
link_elements = etree.Element("links")
|
link_elements = etree.Element("links")
|
||||||
# add link data
|
# add link data
|
||||||
for link_data in links:
|
for link_data in links:
|
||||||
|
@ -438,13 +455,21 @@ class CoreXmlWriter:
|
||||||
if link_elements.getchildren():
|
if link_elements.getchildren():
|
||||||
self.scenario.append(link_elements)
|
self.scenario.append(link_elements)
|
||||||
|
|
||||||
def write_device(self, node):
|
def write_device(self, node: NodeBase) -> None:
|
||||||
device = DeviceElement(self.session, node)
|
device = DeviceElement(self.session, node)
|
||||||
self.devices.append(device.element)
|
self.devices.append(device.element)
|
||||||
|
|
||||||
def create_interface_element(
|
def create_interface_element(
|
||||||
self, element_name, node_id, interface_id, mac, ip4, ip4_mask, ip6, ip6_mask
|
self,
|
||||||
):
|
element_name: str,
|
||||||
|
node_id: int,
|
||||||
|
interface_id: int,
|
||||||
|
mac: str,
|
||||||
|
ip4: str,
|
||||||
|
ip4_mask: int,
|
||||||
|
ip6: str,
|
||||||
|
ip6_mask: int,
|
||||||
|
) -> etree.Element:
|
||||||
interface = etree.Element(element_name)
|
interface = etree.Element(element_name)
|
||||||
node = self.session.get_node(node_id)
|
node = self.session.get_node(node_id)
|
||||||
interface_name = None
|
interface_name = None
|
||||||
|
@ -467,7 +492,7 @@ class CoreXmlWriter:
|
||||||
|
|
||||||
return interface
|
return interface
|
||||||
|
|
||||||
def create_link_element(self, link_data):
|
def create_link_element(self, link_data: LinkData) -> etree.Element:
|
||||||
link_element = etree.Element("link")
|
link_element = etree.Element("link")
|
||||||
add_attribute(link_element, "node_one", link_data.node1_id)
|
add_attribute(link_element, "node_one", link_data.node1_id)
|
||||||
add_attribute(link_element, "node_two", link_data.node2_id)
|
add_attribute(link_element, "node_two", link_data.node2_id)
|
||||||
|
@ -525,11 +550,11 @@ class CoreXmlWriter:
|
||||||
|
|
||||||
|
|
||||||
class CoreXmlReader:
|
class CoreXmlReader:
|
||||||
def __init__(self, session):
|
def __init__(self, session: "Session") -> None:
|
||||||
self.session = session
|
self.session = session
|
||||||
self.scenario = None
|
self.scenario = None
|
||||||
|
|
||||||
def read(self, file_name):
|
def read(self, file_name: str) -> None:
|
||||||
xml_tree = etree.parse(file_name)
|
xml_tree = etree.parse(file_name)
|
||||||
self.scenario = xml_tree.getroot()
|
self.scenario = xml_tree.getroot()
|
||||||
|
|
||||||
|
@ -545,7 +570,7 @@ class CoreXmlReader:
|
||||||
self.read_nodes()
|
self.read_nodes()
|
||||||
self.read_links()
|
self.read_links()
|
||||||
|
|
||||||
def read_default_services(self):
|
def read_default_services(self) -> None:
|
||||||
default_services = self.scenario.find("default_services")
|
default_services = self.scenario.find("default_services")
|
||||||
if default_services is None:
|
if default_services is None:
|
||||||
return
|
return
|
||||||
|
@ -560,7 +585,7 @@ class CoreXmlReader:
|
||||||
)
|
)
|
||||||
self.session.services.default_services[node_type] = services
|
self.session.services.default_services[node_type] = services
|
||||||
|
|
||||||
def read_session_metadata(self):
|
def read_session_metadata(self) -> None:
|
||||||
session_metadata = self.scenario.find("session_metadata")
|
session_metadata = self.scenario.find("session_metadata")
|
||||||
if session_metadata is None:
|
if session_metadata is None:
|
||||||
return
|
return
|
||||||
|
@ -573,7 +598,7 @@ class CoreXmlReader:
|
||||||
logging.info("reading session metadata: %s", configs)
|
logging.info("reading session metadata: %s", configs)
|
||||||
self.session.metadata = configs
|
self.session.metadata = configs
|
||||||
|
|
||||||
def read_session_options(self):
|
def read_session_options(self) -> None:
|
||||||
session_options = self.scenario.find("session_options")
|
session_options = self.scenario.find("session_options")
|
||||||
if session_options is None:
|
if session_options is None:
|
||||||
return
|
return
|
||||||
|
@ -586,7 +611,7 @@ class CoreXmlReader:
|
||||||
logging.info("reading session options: %s", configs)
|
logging.info("reading session options: %s", configs)
|
||||||
self.session.options.set_configs(configs)
|
self.session.options.set_configs(configs)
|
||||||
|
|
||||||
def read_session_hooks(self):
|
def read_session_hooks(self) -> None:
|
||||||
session_hooks = self.scenario.find("session_hooks")
|
session_hooks = self.scenario.find("session_hooks")
|
||||||
if session_hooks is None:
|
if session_hooks is None:
|
||||||
return
|
return
|
||||||
|
@ -601,7 +626,7 @@ class CoreXmlReader:
|
||||||
hook_type, file_name=name, source_name=None, data=data
|
hook_type, file_name=name, source_name=None, data=data
|
||||||
)
|
)
|
||||||
|
|
||||||
def read_session_origin(self):
|
def read_session_origin(self) -> None:
|
||||||
session_origin = self.scenario.find("session_origin")
|
session_origin = self.scenario.find("session_origin")
|
||||||
if session_origin is None:
|
if session_origin is None:
|
||||||
return
|
return
|
||||||
|
@ -625,7 +650,7 @@ class CoreXmlReader:
|
||||||
logging.info("reading session reference xyz: %s, %s, %s", x, y, z)
|
logging.info("reading session reference xyz: %s, %s, %s", x, y, z)
|
||||||
self.session.location.refxyz = (x, y, z)
|
self.session.location.refxyz = (x, y, z)
|
||||||
|
|
||||||
def read_service_configs(self):
|
def read_service_configs(self) -> None:
|
||||||
service_configurations = self.scenario.find("service_configurations")
|
service_configurations = self.scenario.find("service_configurations")
|
||||||
if service_configurations is None:
|
if service_configurations is None:
|
||||||
return
|
return
|
||||||
|
@ -669,7 +694,7 @@ class CoreXmlReader:
|
||||||
files.add(name)
|
files.add(name)
|
||||||
service.configs = tuple(files)
|
service.configs = tuple(files)
|
||||||
|
|
||||||
def read_emane_configs(self):
|
def read_emane_configs(self) -> None:
|
||||||
emane_configurations = self.scenario.find("emane_configurations")
|
emane_configurations = self.scenario.find("emane_configurations")
|
||||||
if emane_configurations is None:
|
if emane_configurations is None:
|
||||||
return
|
return
|
||||||
|
@ -702,7 +727,7 @@ class CoreXmlReader:
|
||||||
)
|
)
|
||||||
self.session.emane.set_model_config(node_id, model_name, configs)
|
self.session.emane.set_model_config(node_id, model_name, configs)
|
||||||
|
|
||||||
def read_mobility_configs(self):
|
def read_mobility_configs(self) -> None:
|
||||||
mobility_configurations = self.scenario.find("mobility_configurations")
|
mobility_configurations = self.scenario.find("mobility_configurations")
|
||||||
if mobility_configurations is None:
|
if mobility_configurations is None:
|
||||||
return
|
return
|
||||||
|
@ -722,7 +747,7 @@ class CoreXmlReader:
|
||||||
)
|
)
|
||||||
self.session.mobility.set_model_config(node_id, model_name, configs)
|
self.session.mobility.set_model_config(node_id, model_name, configs)
|
||||||
|
|
||||||
def read_nodes(self):
|
def read_nodes(self) -> None:
|
||||||
device_elements = self.scenario.find("devices")
|
device_elements = self.scenario.find("devices")
|
||||||
if device_elements is not None:
|
if device_elements is not None:
|
||||||
for device_element in device_elements.iterchildren():
|
for device_element in device_elements.iterchildren():
|
||||||
|
@ -733,7 +758,7 @@ class CoreXmlReader:
|
||||||
for network_element in network_elements.iterchildren():
|
for network_element in network_elements.iterchildren():
|
||||||
self.read_network(network_element)
|
self.read_network(network_element)
|
||||||
|
|
||||||
def read_device(self, device_element):
|
def read_device(self, device_element: etree.Element) -> None:
|
||||||
node_id = get_int(device_element, "id")
|
node_id = get_int(device_element, "id")
|
||||||
name = device_element.get("name")
|
name = device_element.get("name")
|
||||||
model = device_element.get("type")
|
model = device_element.get("type")
|
||||||
|
@ -759,7 +784,7 @@ class CoreXmlReader:
|
||||||
logging.info("reading node id(%s) model(%s) name(%s)", node_id, model, name)
|
logging.info("reading node id(%s) model(%s) name(%s)", node_id, model, name)
|
||||||
self.session.add_node(_id=node_id, options=options)
|
self.session.add_node(_id=node_id, options=options)
|
||||||
|
|
||||||
def read_network(self, network_element):
|
def read_network(self, network_element: etree.Element) -> None:
|
||||||
node_id = get_int(network_element, "id")
|
node_id = get_int(network_element, "id")
|
||||||
name = network_element.get("name")
|
name = network_element.get("name")
|
||||||
node_type = NodeTypes[network_element.get("type")]
|
node_type = NodeTypes[network_element.get("type")]
|
||||||
|
@ -783,7 +808,7 @@ class CoreXmlReader:
|
||||||
)
|
)
|
||||||
self.session.add_node(_type=node_type, _id=node_id, options=options)
|
self.session.add_node(_type=node_type, _id=node_id, options=options)
|
||||||
|
|
||||||
def read_links(self):
|
def read_links(self) -> None:
|
||||||
link_elements = self.scenario.find("links")
|
link_elements = self.scenario.find("links")
|
||||||
if link_elements is None:
|
if link_elements is None:
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
from typing import TYPE_CHECKING, List, Tuple
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
@ -7,26 +8,40 @@ from lxml import etree
|
||||||
from core import utils
|
from core import utils
|
||||||
from core.constants import IP_BIN
|
from core.constants import IP_BIN
|
||||||
from core.emane.nodes import EmaneNet
|
from core.emane.nodes import EmaneNet
|
||||||
from core.nodes.base import CoreNodeBase
|
from core.nodes.base import CoreNodeBase, NodeBase
|
||||||
|
from core.nodes.interface import CoreInterface
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from core.emulator.session import Session
|
||||||
|
|
||||||
|
|
||||||
def add_type(parent_element, name):
|
def add_type(parent_element: etree.Element, name: str) -> None:
|
||||||
type_element = etree.SubElement(parent_element, "type")
|
type_element = etree.SubElement(parent_element, "type")
|
||||||
type_element.text = name
|
type_element.text = name
|
||||||
|
|
||||||
|
|
||||||
def add_address(parent_element, address_type, address, interface_name=None):
|
def add_address(
|
||||||
|
parent_element: etree.Element,
|
||||||
|
address_type: str,
|
||||||
|
address: str,
|
||||||
|
interface_name: str = None,
|
||||||
|
) -> None:
|
||||||
address_element = etree.SubElement(parent_element, "address", type=address_type)
|
address_element = etree.SubElement(parent_element, "address", type=address_type)
|
||||||
address_element.text = address
|
address_element.text = address
|
||||||
if interface_name is not None:
|
if interface_name is not None:
|
||||||
address_element.set("iface", interface_name)
|
address_element.set("iface", interface_name)
|
||||||
|
|
||||||
|
|
||||||
def add_mapping(parent_element, maptype, mapref):
|
def add_mapping(parent_element: etree.Element, maptype: str, mapref: str) -> None:
|
||||||
etree.SubElement(parent_element, "mapping", type=maptype, ref=mapref)
|
etree.SubElement(parent_element, "mapping", type=maptype, ref=mapref)
|
||||||
|
|
||||||
|
|
||||||
def add_emane_interface(host_element, netif, platform_name="p1", transport_name="t1"):
|
def add_emane_interface(
|
||||||
|
host_element: etree.Element,
|
||||||
|
netif: CoreInterface,
|
||||||
|
platform_name: str = "p1",
|
||||||
|
transport_name: str = "t1",
|
||||||
|
) -> etree.Element:
|
||||||
nem_id = netif.net.nemidmap[netif]
|
nem_id = netif.net.nemidmap[netif]
|
||||||
host_id = host_element.get("id")
|
host_id = host_element.get("id")
|
||||||
|
|
||||||
|
@ -54,7 +69,7 @@ def add_emane_interface(host_element, netif, platform_name="p1", transport_name=
|
||||||
return platform_element
|
return platform_element
|
||||||
|
|
||||||
|
|
||||||
def get_address_type(address):
|
def get_address_type(address: str) -> str:
|
||||||
addr, _slash, _prefixlen = address.partition("/")
|
addr, _slash, _prefixlen = address.partition("/")
|
||||||
if netaddr.valid_ipv4(addr):
|
if netaddr.valid_ipv4(addr):
|
||||||
address_type = "IPv4"
|
address_type = "IPv4"
|
||||||
|
@ -65,7 +80,7 @@ def get_address_type(address):
|
||||||
return address_type
|
return address_type
|
||||||
|
|
||||||
|
|
||||||
def get_ipv4_addresses(hostname):
|
def get_ipv4_addresses(hostname: str) -> List[Tuple[str, str]]:
|
||||||
if hostname == "localhost":
|
if hostname == "localhost":
|
||||||
addresses = []
|
addresses = []
|
||||||
args = f"{IP_BIN} -o -f inet address show"
|
args = f"{IP_BIN} -o -f inet address show"
|
||||||
|
@ -85,7 +100,7 @@ def get_ipv4_addresses(hostname):
|
||||||
|
|
||||||
|
|
||||||
class CoreXmlDeployment:
|
class CoreXmlDeployment:
|
||||||
def __init__(self, session, scenario):
|
def __init__(self, session: "Session", scenario: etree.Element) -> None:
|
||||||
self.session = session
|
self.session = session
|
||||||
self.scenario = scenario
|
self.scenario = scenario
|
||||||
self.root = etree.SubElement(
|
self.root = etree.SubElement(
|
||||||
|
@ -93,17 +108,17 @@ class CoreXmlDeployment:
|
||||||
)
|
)
|
||||||
self.add_deployment()
|
self.add_deployment()
|
||||||
|
|
||||||
def find_device(self, name):
|
def find_device(self, name: str) -> etree.Element:
|
||||||
device = self.scenario.find(f"devices/device[@name='{name}']")
|
device = self.scenario.find(f"devices/device[@name='{name}']")
|
||||||
return device
|
return device
|
||||||
|
|
||||||
def find_interface(self, device, name):
|
def find_interface(self, device: NodeBase, name: str) -> etree.Element:
|
||||||
interface = self.scenario.find(
|
interface = self.scenario.find(
|
||||||
f"devices/device[@name='{device.name}']/interfaces/interface[@name='{name}']"
|
f"devices/device[@name='{device.name}']/interfaces/interface[@name='{name}']"
|
||||||
)
|
)
|
||||||
return interface
|
return interface
|
||||||
|
|
||||||
def add_deployment(self):
|
def add_deployment(self) -> None:
|
||||||
physical_host = self.add_physical_host(socket.gethostname())
|
physical_host = self.add_physical_host(socket.gethostname())
|
||||||
|
|
||||||
for node_id in self.session.nodes:
|
for node_id in self.session.nodes:
|
||||||
|
@ -111,7 +126,7 @@ class CoreXmlDeployment:
|
||||||
if isinstance(node, CoreNodeBase):
|
if isinstance(node, CoreNodeBase):
|
||||||
self.add_virtual_host(physical_host, node)
|
self.add_virtual_host(physical_host, node)
|
||||||
|
|
||||||
def add_physical_host(self, name):
|
def add_physical_host(self, name: str) -> etree.Element:
|
||||||
# add host
|
# add host
|
||||||
root_id = self.root.get("id")
|
root_id = self.root.get("id")
|
||||||
host_id = f"{root_id}/{name}"
|
host_id = f"{root_id}/{name}"
|
||||||
|
@ -126,7 +141,7 @@ class CoreXmlDeployment:
|
||||||
|
|
||||||
return host_element
|
return host_element
|
||||||
|
|
||||||
def add_virtual_host(self, physical_host, node):
|
def add_virtual_host(self, physical_host: etree.Element, node: NodeBase) -> None:
|
||||||
if not isinstance(node, CoreNodeBase):
|
if not isinstance(node, CoreNodeBase):
|
||||||
raise TypeError(f"invalid node type: {node}")
|
raise TypeError(f"invalid node type: {node}")
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
|
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
|
from core.config import Configuration
|
||||||
|
from core.emane.nodes import EmaneNet
|
||||||
|
from core.emulator.distributed import DistributedServer
|
||||||
|
from core.nodes.interface import CoreInterface
|
||||||
|
from core.nodes.network import CtrlNet
|
||||||
from core.xml import corexml
|
from core.xml import corexml
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from core.emane.emanemanager import EmaneManager
|
||||||
|
from core.emane.emanemodel import EmaneModel
|
||||||
|
|
||||||
_hwaddr_prefix = "02:02"
|
_hwaddr_prefix = "02:02"
|
||||||
|
|
||||||
|
|
||||||
def is_external(config):
|
def is_external(config: Dict[str, str]) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if the configuration is for an external transport.
|
Checks if the configuration is for an external transport.
|
||||||
|
|
||||||
|
@ -21,7 +31,7 @@ def is_external(config):
|
||||||
return config.get("external") == "1"
|
return config.get("external") == "1"
|
||||||
|
|
||||||
|
|
||||||
def _value_to_params(value):
|
def _value_to_params(value: str) -> Optional[Tuple[str]]:
|
||||||
"""
|
"""
|
||||||
Helper to convert a parameter to a parameter tuple.
|
Helper to convert a parameter to a parameter tuple.
|
||||||
|
|
||||||
|
@ -44,7 +54,12 @@ def _value_to_params(value):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def create_file(xml_element, doc_name, file_path, server=None):
|
def create_file(
|
||||||
|
xml_element: etree.Element,
|
||||||
|
doc_name: str,
|
||||||
|
file_path: str,
|
||||||
|
server: DistributedServer = None,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create xml file.
|
Create xml file.
|
||||||
|
|
||||||
|
@ -68,7 +83,7 @@ def create_file(xml_element, doc_name, file_path, server=None):
|
||||||
corexml.write_xml_file(xml_element, file_path, doctype=doctype)
|
corexml.write_xml_file(xml_element, file_path, doctype=doctype)
|
||||||
|
|
||||||
|
|
||||||
def add_param(xml_element, name, value):
|
def add_param(xml_element: etree.Element, name: str, value: str) -> None:
|
||||||
"""
|
"""
|
||||||
Add emane configuration parameter to xml element.
|
Add emane configuration parameter to xml element.
|
||||||
|
|
||||||
|
@ -80,7 +95,12 @@ def add_param(xml_element, name, value):
|
||||||
etree.SubElement(xml_element, "param", name=name, value=value)
|
etree.SubElement(xml_element, "param", name=name, value=value)
|
||||||
|
|
||||||
|
|
||||||
def add_configurations(xml_element, configurations, config, config_ignore):
|
def add_configurations(
|
||||||
|
xml_element: etree.Element,
|
||||||
|
configurations: List[Configuration],
|
||||||
|
config: Dict[str, str],
|
||||||
|
config_ignore: Set,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Add emane model configurations to xml element.
|
Add emane model configurations to xml element.
|
||||||
|
|
||||||
|
@ -107,7 +127,13 @@ def add_configurations(xml_element, configurations, config, config_ignore):
|
||||||
add_param(xml_element, name, value)
|
add_param(xml_element, name, value)
|
||||||
|
|
||||||
|
|
||||||
def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_xmls):
|
def build_node_platform_xml(
|
||||||
|
emane_manager: "EmaneManager",
|
||||||
|
control_net: CtrlNet,
|
||||||
|
node: EmaneNet,
|
||||||
|
nem_id: int,
|
||||||
|
platform_xmls: Dict[str, etree.Element],
|
||||||
|
) -> int:
|
||||||
"""
|
"""
|
||||||
Create platform xml for a specific node.
|
Create platform xml for a specific node.
|
||||||
|
|
||||||
|
@ -131,7 +157,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
|
||||||
|
|
||||||
if node.model is None:
|
if node.model is None:
|
||||||
logging.warning("warning: EMANE network %s has no associated model", node.name)
|
logging.warning("warning: EMANE network %s has no associated model", node.name)
|
||||||
return nem_entries
|
return nem_id
|
||||||
|
|
||||||
for netif in node.netifs():
|
for netif in node.netifs():
|
||||||
logging.debug(
|
logging.debug(
|
||||||
|
@ -228,7 +254,7 @@ def build_node_platform_xml(emane_manager, control_net, node, nem_id, platform_x
|
||||||
return nem_id
|
return nem_id
|
||||||
|
|
||||||
|
|
||||||
def build_xml_files(emane_manager, node):
|
def build_xml_files(emane_manager: "EmaneManager", node: EmaneNet) -> None:
|
||||||
"""
|
"""
|
||||||
Generate emane xml files required for node.
|
Generate emane xml files required for node.
|
||||||
|
|
||||||
|
@ -276,7 +302,9 @@ def build_xml_files(emane_manager, node):
|
||||||
build_transport_xml(emane_manager, node, rtype)
|
build_transport_xml(emane_manager, node, rtype)
|
||||||
|
|
||||||
|
|
||||||
def build_transport_xml(emane_manager, node, transport_type):
|
def build_transport_xml(
|
||||||
|
emane_manager: "EmaneManager", node: EmaneNet, transport_type: str
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Build transport xml file for node and transport type.
|
Build transport xml file for node and transport type.
|
||||||
|
|
||||||
|
@ -317,7 +345,12 @@ def build_transport_xml(emane_manager, node, transport_type):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_phy_xml(emane_model, config, file_path, server):
|
def create_phy_xml(
|
||||||
|
emane_model: "EmaneModel",
|
||||||
|
config: Dict[str, str],
|
||||||
|
file_path: str,
|
||||||
|
server: DistributedServer,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create the phy xml document.
|
Create the phy xml document.
|
||||||
|
|
||||||
|
@ -345,7 +378,12 @@ def create_phy_xml(emane_model, config, file_path, server):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_mac_xml(emane_model, config, file_path, server):
|
def create_mac_xml(
|
||||||
|
emane_model: "EmaneModel",
|
||||||
|
config: Dict[str, str],
|
||||||
|
file_path: str,
|
||||||
|
server: DistributedServer,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create the mac xml document.
|
Create the mac xml document.
|
||||||
|
|
||||||
|
@ -376,14 +414,14 @@ def create_mac_xml(emane_model, config, file_path, server):
|
||||||
|
|
||||||
|
|
||||||
def create_nem_xml(
|
def create_nem_xml(
|
||||||
emane_model,
|
emane_model: "EmaneModel",
|
||||||
config,
|
config: Dict[str, str],
|
||||||
nem_file,
|
nem_file: str,
|
||||||
transport_definition,
|
transport_definition: str,
|
||||||
mac_definition,
|
mac_definition: str,
|
||||||
phy_definition,
|
phy_definition: str,
|
||||||
server,
|
server: DistributedServer,
|
||||||
):
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create the nem xml document.
|
Create the nem xml document.
|
||||||
|
|
||||||
|
@ -413,7 +451,13 @@ def create_nem_xml(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_event_service_xml(group, port, device, file_directory, server=None):
|
def create_event_service_xml(
|
||||||
|
group: str,
|
||||||
|
port: str,
|
||||||
|
device: str,
|
||||||
|
file_directory: str,
|
||||||
|
server: DistributedServer = None,
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Create a emane event service xml file.
|
Create a emane event service xml file.
|
||||||
|
|
||||||
|
@ -440,7 +484,7 @@ def create_event_service_xml(group, port, device, file_directory, server=None):
|
||||||
create_file(event_element, "emaneeventmsgsvc", file_path, server)
|
create_file(event_element, "emaneeventmsgsvc", file_path, server)
|
||||||
|
|
||||||
|
|
||||||
def transport_file_name(node_id, transport_type):
|
def transport_file_name(node_id: int, transport_type: str) -> str:
|
||||||
"""
|
"""
|
||||||
Create name for a transport xml file.
|
Create name for a transport xml file.
|
||||||
|
|
||||||
|
@ -451,10 +495,11 @@ def transport_file_name(node_id, transport_type):
|
||||||
return f"n{node_id}trans{transport_type}.xml"
|
return f"n{node_id}trans{transport_type}.xml"
|
||||||
|
|
||||||
|
|
||||||
def _basename(emane_model, interface=None):
|
def _basename(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
|
||||||
"""
|
"""
|
||||||
Create name that is leveraged for configuration file creation.
|
Create name that is leveraged for configuration file creation.
|
||||||
|
|
||||||
|
:param emane_model: emane model to create name for
|
||||||
:param interface: interface for this model
|
:param interface: interface for this model
|
||||||
:return: basename used for file creation
|
:return: basename used for file creation
|
||||||
:rtype: str
|
:rtype: str
|
||||||
|
@ -469,7 +514,7 @@ def _basename(emane_model, interface=None):
|
||||||
return f"{name}{emane_model.name}"
|
return f"{name}{emane_model.name}"
|
||||||
|
|
||||||
|
|
||||||
def nem_file_name(emane_model, interface=None):
|
def nem_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
|
||||||
"""
|
"""
|
||||||
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
|
Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml"
|
||||||
|
|
||||||
|
@ -485,7 +530,7 @@ def nem_file_name(emane_model, interface=None):
|
||||||
return f"{basename}nem{append}.xml"
|
return f"{basename}nem{append}.xml"
|
||||||
|
|
||||||
|
|
||||||
def shim_file_name(emane_model, interface=None):
|
def shim_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
|
||||||
"""
|
"""
|
||||||
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
|
Return the string name for the SHIM XML file, e.g. "commeffectshim.xml"
|
||||||
|
|
||||||
|
@ -498,7 +543,7 @@ def shim_file_name(emane_model, interface=None):
|
||||||
return f"{name}shim.xml"
|
return f"{name}shim.xml"
|
||||||
|
|
||||||
|
|
||||||
def mac_file_name(emane_model, interface=None):
|
def mac_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
|
||||||
"""
|
"""
|
||||||
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
|
Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml"
|
||||||
|
|
||||||
|
@ -511,7 +556,7 @@ def mac_file_name(emane_model, interface=None):
|
||||||
return f"{name}mac.xml"
|
return f"{name}mac.xml"
|
||||||
|
|
||||||
|
|
||||||
def phy_file_name(emane_model, interface=None):
|
def phy_file_name(emane_model: "EmaneModel", interface: CoreInterface = None) -> str:
|
||||||
"""
|
"""
|
||||||
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
|
Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue