updated emane model xml to leverage lxml
This commit is contained in:
parent
4ccb1ed9f3
commit
ae94c78fbb
4 changed files with 166 additions and 88 deletions
|
@ -1,6 +1,7 @@
|
||||||
"""
|
"""
|
||||||
EMANE Bypass model for CORE
|
EMANE Bypass model for CORE
|
||||||
"""
|
"""
|
||||||
|
from core.conf import ConfigGroup
|
||||||
from core.conf import Configuration
|
from core.conf import Configuration
|
||||||
from core.emane import emanemodel
|
from core.emane import emanemodel
|
||||||
from core.enumerations import ConfigDataTypes
|
from core.enumerations import ConfigDataTypes
|
||||||
|
@ -31,4 +32,6 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
||||||
# override config groups
|
# override config groups
|
||||||
@classmethod
|
@classmethod
|
||||||
def config_groups(cls):
|
def config_groups(cls):
|
||||||
return "Bypass Parameters:1-1"
|
return [
|
||||||
|
ConfigGroup("Bypass Parameters", 1, 1),
|
||||||
|
]
|
||||||
|
|
|
@ -4,6 +4,7 @@ emane.py: definition of an Emane class for implementing configuration control of
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
from lxml import etree
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
|
|
||||||
from core import CoreCommandError
|
from core import CoreCommandError
|
||||||
|
@ -55,6 +56,39 @@ EMANE_MODELS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def build_node_platform_xml(node):
|
||||||
|
platform_element = etree.Element("platform")
|
||||||
|
|
||||||
|
nem_entries = {}
|
||||||
|
|
||||||
|
if node.model is None:
|
||||||
|
logger.info("warning: EmaneNode %s has no associated model", node.name)
|
||||||
|
return nem_entries
|
||||||
|
|
||||||
|
for netif in node.netifs():
|
||||||
|
# build nem xml
|
||||||
|
# nementry = node.model.build_nem_xml(doc, node, netif)
|
||||||
|
nem_name = node.model.nem_name(netif)
|
||||||
|
nem_element = etree.Element("nem", name=netif.localname, definition=nem_name)
|
||||||
|
|
||||||
|
# build transport xml
|
||||||
|
# trans = node.model.build_transport_xml(doc, node, netif)
|
||||||
|
transport_type = netif.transport_type
|
||||||
|
if not transport_type:
|
||||||
|
logger.info("warning: %s interface type unsupported!", netif.name)
|
||||||
|
transport_type = "raw"
|
||||||
|
transport_name = node.transportxmlname(transport_type)
|
||||||
|
transport_element = etree.SubElement(nem_element, "transport", definition=transport_name)
|
||||||
|
|
||||||
|
# add transport parameter
|
||||||
|
etree.SubElement(transport_element, "param", name="device", value=netif.name)
|
||||||
|
|
||||||
|
# add nem entry
|
||||||
|
nem_entries[netif] = nem_element
|
||||||
|
|
||||||
|
return nem_entries
|
||||||
|
|
||||||
|
|
||||||
class EmaneManager(ModelManager):
|
class EmaneManager(ModelManager):
|
||||||
"""
|
"""
|
||||||
EMANE controller object. Lives in a Session instance and is used for
|
EMANE controller object. Lives in a Session instance and is used for
|
||||||
|
@ -637,6 +671,7 @@ class EmaneManager(ModelManager):
|
||||||
for key in sorted(self._emane_nodes.keys()):
|
for key in sorted(self._emane_nodes.keys()):
|
||||||
emane_node = self._emane_nodes[key]
|
emane_node = self._emane_nodes[key]
|
||||||
nems = emane_node.buildplatformxmlentry(self.xmldoc("platform"))
|
nems = emane_node.buildplatformxmlentry(self.xmldoc("platform"))
|
||||||
|
|
||||||
for netif in sorted(nems, key=lambda x: x.node.objid):
|
for netif in sorted(nems, key=lambda x: x.node.objid):
|
||||||
nementry = nems[netif]
|
nementry = nems[netif]
|
||||||
nementry.setAttribute("id", "%d" % nemid)
|
nementry.setAttribute("id", "%d" % nemid)
|
||||||
|
|
|
@ -1,38 +1,102 @@
|
||||||
"""
|
"""
|
||||||
Defines Emane Models used within CORE.
|
Defines Emane Models used within CORE.
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
from core import logger
|
from core import logger
|
||||||
from core.conf import ConfigGroup
|
from core.conf import ConfigGroup
|
||||||
from core.emane import emanemanifest
|
from core.emane import emanemanifest
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
from core.mobility import WirelessModel
|
from core.mobility import WirelessModel
|
||||||
from core.xml import xmlutils
|
from core.xml import corexml
|
||||||
|
|
||||||
|
|
||||||
def value_to_params(doc, name, value):
|
def emane_xml_doctype(name):
|
||||||
"""
|
"""
|
||||||
Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to
|
Create emane xml doctype for xml files.
|
||||||
multiple values.
|
|
||||||
|
:param str name: name for xml doctype
|
||||||
|
:return: emane xml doctype
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
return '<!DOCTYPE %s SYSTEM "file:///usr/share/emane/dtd/%s.dtd">' % (name, name)
|
||||||
|
|
||||||
|
|
||||||
|
def add_emane_configurations(xml_element, configurations, config, config_ignore):
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
:param lxml.etree.Element xml_element: xml element to add emane configurations to
|
||||||
|
:param list[core.config.Configuration] configurations: configurations to add to xml
|
||||||
|
:param dict config: configuration values
|
||||||
|
:param set config_ignore: configuration options to ignore
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
for configuration in configurations:
|
||||||
|
# ignore custom configurations
|
||||||
|
name = configuration.id
|
||||||
|
if name in config_ignore:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# check if value is a multi param
|
||||||
|
value = str(config[name])
|
||||||
|
params = lxml_value_to_params(value)
|
||||||
|
if params:
|
||||||
|
params_element = etree.SubElement(xml_element, "paramlist", name=name)
|
||||||
|
for param in params:
|
||||||
|
etree.SubElement(params_element, "item", value=param)
|
||||||
|
else:
|
||||||
|
etree.SubElement(xml_element, "param", name=name, value=value)
|
||||||
|
|
||||||
|
|
||||||
|
def lxml_value_to_params(value):
|
||||||
|
"""
|
||||||
|
Helper to convert a parameter to a parameter tuple.
|
||||||
|
|
||||||
:param xml.dom.minidom.Document doc: xml document
|
|
||||||
:param name: name of element for params
|
|
||||||
:param str value: value string to convert to tuple
|
:param str value: value string to convert to tuple
|
||||||
:return: xml document with added params or None, when an invalid value has been provided
|
:return: parameter tuple, None otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
values = utils.make_tuple_fromstr(value, str)
|
values = utils.make_tuple_fromstr(value, str)
|
||||||
|
|
||||||
|
if not hasattr(values, "__iter__"):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if len(values) < 2:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
logger.exception("error in value string to param list")
|
logger.exception("error in value string to param list")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if not hasattr(values, "__iter__"):
|
|
||||||
return None
|
|
||||||
|
|
||||||
if len(values) < 2:
|
# def value_to_params(doc, name, value):
|
||||||
return None
|
# """
|
||||||
|
# Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to
|
||||||
return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values)
|
# multiple values.
|
||||||
|
#
|
||||||
|
# :param xml.dom.minidom.Document doc: xml document
|
||||||
|
# :param name: name of element for params
|
||||||
|
# :param str value: value string to convert to tuple
|
||||||
|
# :return: xml document with added params or None, when an invalid value has been provided
|
||||||
|
# """
|
||||||
|
# try:
|
||||||
|
# values = utils.make_tuple_fromstr(value, str)
|
||||||
|
# except SyntaxError:
|
||||||
|
# logger.exception("error in value string to param list")
|
||||||
|
# return None
|
||||||
|
#
|
||||||
|
# if not hasattr(values, "__iter__"):
|
||||||
|
# return None
|
||||||
|
#
|
||||||
|
# if len(values) < 2:
|
||||||
|
# return None
|
||||||
|
#
|
||||||
|
# return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values)
|
||||||
|
|
||||||
|
|
||||||
class EmaneModel(WirelessModel):
|
class EmaneModel(WirelessModel):
|
||||||
|
@ -88,112 +152,82 @@ class EmaneModel(WirelessModel):
|
||||||
return
|
return
|
||||||
|
|
||||||
# create document and write to disk
|
# create document and write to disk
|
||||||
nem_name = self.nem_name(interface)
|
self.create_nem_doc(interface)
|
||||||
nem_document = self.create_nem_doc(emane_manager, interface)
|
|
||||||
emane_manager.xmlwrite(nem_document, nem_name)
|
|
||||||
|
|
||||||
# create mac document and write to disk
|
# create mac document and write to disk
|
||||||
mac_name = self.mac_name(interface)
|
self.create_mac_doc(interface, config)
|
||||||
mac_document = self.create_mac_doc(emane_manager, config)
|
|
||||||
emane_manager.xmlwrite(mac_document, mac_name)
|
|
||||||
|
|
||||||
# create phy document and write to disk
|
# create phy document and write to disk
|
||||||
phy_name = self.phy_name(interface)
|
self.create_phy_doc(interface, config)
|
||||||
phy_document = self.create_phy_doc(emane_manager, config)
|
|
||||||
emane_manager.xmlwrite(phy_document, phy_name)
|
|
||||||
|
|
||||||
def create_nem_doc(self, emane_manager, interface):
|
def create_nem_doc(self, interface):
|
||||||
"""
|
"""
|
||||||
Create the nem xml document.
|
Create the nem xml document.
|
||||||
|
|
||||||
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
|
|
||||||
:param interface: interface for the emane node
|
:param interface: interface for the emane node
|
||||||
:return: nem document
|
:return: nothing
|
||||||
:rtype: xml.dom.minidom.Document
|
|
||||||
"""
|
"""
|
||||||
|
nem_element = etree.Element("nem", name="%s NEM" % self.name)
|
||||||
|
|
||||||
|
# add transport
|
||||||
|
transport_type = "virtual"
|
||||||
|
if interface and interface.transport_type == "raw":
|
||||||
|
transport_type = "raw"
|
||||||
|
transport_type = "n%strans%s.xml" % (self.object_id, transport_type)
|
||||||
|
etree.SubElement(nem_element, "transport", definition=transport_type)
|
||||||
|
|
||||||
|
# create mac
|
||||||
mac_name = self.mac_name(interface)
|
mac_name = self.mac_name(interface)
|
||||||
|
etree.SubElement(nem_element, "mac", definition=mac_name)
|
||||||
|
|
||||||
|
# create phy
|
||||||
phy_name = self.phy_name(interface)
|
phy_name = self.phy_name(interface)
|
||||||
|
etree.SubElement(nem_element, "phy", definition=phy_name)
|
||||||
|
|
||||||
nem_document = emane_manager.xmldoc("nem")
|
# write out xml
|
||||||
nem_element = nem_document.getElementsByTagName("nem").pop()
|
nem_name = self.nem_name(interface)
|
||||||
nem_element.setAttribute("name", "%s NEM" % self.name)
|
self.create_file(nem_element, nem_name, "nem")
|
||||||
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
|
|
||||||
|
|
||||||
mac_element = nem_document.createElement("mac")
|
def create_mac_doc(self, interface, config):
|
||||||
mac_element.setAttribute("definition", mac_name)
|
|
||||||
nem_element.appendChild(mac_element)
|
|
||||||
|
|
||||||
phy_element = nem_document.createElement("phy")
|
|
||||||
phy_element.setAttribute("definition", phy_name)
|
|
||||||
nem_element.appendChild(phy_element)
|
|
||||||
|
|
||||||
return nem_document
|
|
||||||
|
|
||||||
def create_mac_doc(self, emane_manager, config):
|
|
||||||
"""
|
"""
|
||||||
Create the mac xml document.
|
Create the mac xml document.
|
||||||
|
|
||||||
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
|
:param interface: interface for the emane node
|
||||||
:param dict config: all current configuration values, mac + phy
|
:param dict config: all current configuration values, mac + phy
|
||||||
:return: nem document
|
:return: nothing
|
||||||
:rtype: xml.dom.minidom.Document
|
|
||||||
"""
|
"""
|
||||||
mac_document = emane_manager.xmldoc("mac")
|
|
||||||
mac_element = mac_document.getElementsByTagName("mac").pop()
|
|
||||||
mac_element.setAttribute("name", "%s MAC" % self.name)
|
|
||||||
|
|
||||||
if not self.mac_library:
|
if not self.mac_library:
|
||||||
raise ValueError("must define emane model library")
|
raise ValueError("must define emane model library")
|
||||||
mac_element.setAttribute("library", self.mac_library)
|
|
||||||
|
|
||||||
for mac_configuration in self.mac_config:
|
mac_element = etree.Element("mac", name="%s MAC" % self.name, library=self.mac_library)
|
||||||
# ignore custom configurations
|
add_emane_configurations(mac_element, self.mac_config, config, self.config_ignore)
|
||||||
name = mac_configuration.id
|
|
||||||
if name in self.config_ignore:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# check if value is a multi param
|
# write out xml
|
||||||
value = str(config[name])
|
mac_name = self.mac_name(interface)
|
||||||
param = value_to_params(mac_document, name, value)
|
self.create_file(mac_element, mac_name, "mac")
|
||||||
if not param:
|
|
||||||
param = emane_manager.xmlparam(mac_document, name, value)
|
|
||||||
|
|
||||||
mac_element.appendChild(param)
|
def create_phy_doc(self, interface, config):
|
||||||
|
|
||||||
return mac_document
|
|
||||||
|
|
||||||
def create_phy_doc(self, emane_manager, config):
|
|
||||||
"""
|
"""
|
||||||
Create the phy xml document.
|
Create the phy xml document.
|
||||||
|
|
||||||
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
|
:param interface: interface for the emane node
|
||||||
:param dict config: all current configuration values, mac + phy
|
:param dict config: all current configuration values, mac + phy
|
||||||
:return: nem document
|
:return: nothing
|
||||||
:rtype: xml.dom.minidom.Document
|
|
||||||
"""
|
"""
|
||||||
phy_document = emane_manager.xmldoc("phy")
|
phy_element = etree.Element("phy", name="%s PHY" % self.name)
|
||||||
phy_element = phy_document.getElementsByTagName("phy").pop()
|
|
||||||
phy_element.setAttribute("name", "%s PHY" % self.name)
|
|
||||||
|
|
||||||
if self.phy_library:
|
if self.phy_library:
|
||||||
phy_element.setAttribute("library", self.phy_library)
|
phy_element.set("library", self.phy_library)
|
||||||
|
|
||||||
# append all phy options
|
add_emane_configurations(phy_element, self.phy_config, config, self.config_ignore)
|
||||||
for phy_configuration in self.phy_config:
|
|
||||||
# ignore custom configurations
|
|
||||||
name = phy_configuration.id
|
|
||||||
if name in self.config_ignore:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# check if value is a multi param
|
# write out xml
|
||||||
value = str(config[name])
|
phy_name = self.phy_name(interface)
|
||||||
param = value_to_params(phy_document, name, value)
|
self.create_file(phy_element, phy_name, "phy")
|
||||||
if not param:
|
|
||||||
param = emane_manager.xmlparam(phy_document, name, value)
|
|
||||||
|
|
||||||
phy_element.appendChild(param)
|
def create_file(self, xml_element, file_name, doc_name):
|
||||||
|
file_path = os.path.join(self.session.session_dir, file_name)
|
||||||
return phy_document
|
doctype = emane_xml_doctype(doc_name)
|
||||||
|
corexml.write_xml_file(xml_element, file_path, doctype=doctype)
|
||||||
|
|
||||||
def post_startup(self):
|
def post_startup(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -12,6 +12,12 @@ from core.misc.ipaddress import MacAddress
|
||||||
from core.netns import nodes
|
from core.netns import nodes
|
||||||
|
|
||||||
|
|
||||||
|
def write_xml_file(xml_element, file_path, doctype=None):
|
||||||
|
xml_data = etree.tostring(xml_element, xml_declaration=True, pretty_print=True, encoding="UTF-8", doctype=doctype)
|
||||||
|
with open(file_path, "w") as xml_file:
|
||||||
|
xml_file.write(xml_data)
|
||||||
|
|
||||||
|
|
||||||
def get_type(element, name, _type):
|
def get_type(element, name, _type):
|
||||||
value = element.get(name)
|
value = element.get(name)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue