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
|
||||
"""
|
||||
from core.conf import ConfigGroup
|
||||
from core.conf import Configuration
|
||||
from core.emane import emanemodel
|
||||
from core.enumerations import ConfigDataTypes
|
||||
|
@ -31,4 +32,6 @@ class EmaneBypassModel(emanemodel.EmaneModel):
|
|||
# override config groups
|
||||
@classmethod
|
||||
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 threading
|
||||
from lxml import etree
|
||||
from xml.dom.minidom import parseString
|
||||
|
||||
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):
|
||||
"""
|
||||
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()):
|
||||
emane_node = self._emane_nodes[key]
|
||||
nems = emane_node.buildplatformxmlentry(self.xmldoc("platform"))
|
||||
|
||||
for netif in sorted(nems, key=lambda x: x.node.objid):
|
||||
nementry = nems[netif]
|
||||
nementry.setAttribute("id", "%d" % nemid)
|
||||
|
|
|
@ -1,30 +1,65 @@
|
|||
"""
|
||||
Defines Emane Models used within CORE.
|
||||
"""
|
||||
import os
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from core import logger
|
||||
from core.conf import ConfigGroup
|
||||
from core.emane import emanemanifest
|
||||
from core.misc import utils
|
||||
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
|
||||
multiple values.
|
||||
Create emane xml doctype for xml files.
|
||||
|
||||
: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
|
||||
:return: xml document with added params or None, when an invalid value has been provided
|
||||
:return: parameter tuple, None otherwise
|
||||
"""
|
||||
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
|
||||
|
@ -32,7 +67,36 @@ def value_to_params(doc, name, value):
|
|||
if len(values) < 2:
|
||||
return None
|
||||
|
||||
return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values)
|
||||
return values
|
||||
|
||||
except SyntaxError:
|
||||
logger.exception("error in value string to param list")
|
||||
return None
|
||||
|
||||
|
||||
# def value_to_params(doc, name, value):
|
||||
# """
|
||||
# Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to
|
||||
# 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):
|
||||
|
@ -88,112 +152,82 @@ class EmaneModel(WirelessModel):
|
|||
return
|
||||
|
||||
# create document and write to disk
|
||||
nem_name = self.nem_name(interface)
|
||||
nem_document = self.create_nem_doc(emane_manager, interface)
|
||||
emane_manager.xmlwrite(nem_document, nem_name)
|
||||
self.create_nem_doc(interface)
|
||||
|
||||
# create mac document and write to disk
|
||||
mac_name = self.mac_name(interface)
|
||||
mac_document = self.create_mac_doc(emane_manager, config)
|
||||
emane_manager.xmlwrite(mac_document, mac_name)
|
||||
self.create_mac_doc(interface, config)
|
||||
|
||||
# create phy document and write to disk
|
||||
phy_name = self.phy_name(interface)
|
||||
phy_document = self.create_phy_doc(emane_manager, config)
|
||||
emane_manager.xmlwrite(phy_document, phy_name)
|
||||
self.create_phy_doc(interface, config)
|
||||
|
||||
def create_nem_doc(self, emane_manager, interface):
|
||||
def create_nem_doc(self, interface):
|
||||
"""
|
||||
Create the nem xml document.
|
||||
|
||||
:param core.emane.emanemanager.EmaneManager emane_manager: core emane manager
|
||||
:param interface: interface for the emane node
|
||||
:return: nem document
|
||||
:rtype: xml.dom.minidom.Document
|
||||
:return: nothing
|
||||
"""
|
||||
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)
|
||||
etree.SubElement(nem_element, "mac", definition=mac_name)
|
||||
|
||||
# create phy
|
||||
phy_name = self.phy_name(interface)
|
||||
etree.SubElement(nem_element, "phy", definition=phy_name)
|
||||
|
||||
nem_document = emane_manager.xmldoc("nem")
|
||||
nem_element = nem_document.getElementsByTagName("nem").pop()
|
||||
nem_element.setAttribute("name", "%s NEM" % self.name)
|
||||
emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface)
|
||||
# write out xml
|
||||
nem_name = self.nem_name(interface)
|
||||
self.create_file(nem_element, nem_name, "nem")
|
||||
|
||||
mac_element = nem_document.createElement("mac")
|
||||
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):
|
||||
def create_mac_doc(self, interface, config):
|
||||
"""
|
||||
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
|
||||
:return: nem document
|
||||
:rtype: xml.dom.minidom.Document
|
||||
:return: nothing
|
||||
"""
|
||||
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:
|
||||
raise ValueError("must define emane model library")
|
||||
mac_element.setAttribute("library", self.mac_library)
|
||||
|
||||
for mac_configuration in self.mac_config:
|
||||
# ignore custom configurations
|
||||
name = mac_configuration.id
|
||||
if name in self.config_ignore:
|
||||
continue
|
||||
mac_element = etree.Element("mac", name="%s MAC" % self.name, library=self.mac_library)
|
||||
add_emane_configurations(mac_element, self.mac_config, config, self.config_ignore)
|
||||
|
||||
# check if value is a multi param
|
||||
value = str(config[name])
|
||||
param = value_to_params(mac_document, name, value)
|
||||
if not param:
|
||||
param = emane_manager.xmlparam(mac_document, name, value)
|
||||
# write out xml
|
||||
mac_name = self.mac_name(interface)
|
||||
self.create_file(mac_element, mac_name, "mac")
|
||||
|
||||
mac_element.appendChild(param)
|
||||
|
||||
return mac_document
|
||||
|
||||
def create_phy_doc(self, emane_manager, config):
|
||||
def create_phy_doc(self, interface, config):
|
||||
"""
|
||||
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
|
||||
:return: nem document
|
||||
:rtype: xml.dom.minidom.Document
|
||||
:return: nothing
|
||||
"""
|
||||
phy_document = emane_manager.xmldoc("phy")
|
||||
phy_element = phy_document.getElementsByTagName("phy").pop()
|
||||
phy_element.setAttribute("name", "%s PHY" % self.name)
|
||||
|
||||
phy_element = etree.Element("phy", name="%s PHY" % self.name)
|
||||
if self.phy_library:
|
||||
phy_element.setAttribute("library", self.phy_library)
|
||||
phy_element.set("library", self.phy_library)
|
||||
|
||||
# append all phy options
|
||||
for phy_configuration in self.phy_config:
|
||||
# ignore custom configurations
|
||||
name = phy_configuration.id
|
||||
if name in self.config_ignore:
|
||||
continue
|
||||
add_emane_configurations(phy_element, self.phy_config, config, self.config_ignore)
|
||||
|
||||
# check if value is a multi param
|
||||
value = str(config[name])
|
||||
param = value_to_params(phy_document, name, value)
|
||||
if not param:
|
||||
param = emane_manager.xmlparam(phy_document, name, value)
|
||||
# write out xml
|
||||
phy_name = self.phy_name(interface)
|
||||
self.create_file(phy_element, phy_name, "phy")
|
||||
|
||||
phy_element.appendChild(param)
|
||||
|
||||
return phy_document
|
||||
def create_file(self, xml_element, file_name, doc_name):
|
||||
file_path = os.path.join(self.session.session_dir, file_name)
|
||||
doctype = emane_xml_doctype(doc_name)
|
||||
corexml.write_xml_file(xml_element, file_path, doctype=doctype)
|
||||
|
||||
def post_startup(self):
|
||||
"""
|
||||
|
|
|
@ -12,6 +12,12 @@ from core.misc.ipaddress import MacAddress
|
|||
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):
|
||||
value = element.get(name)
|
||||
if value is not None:
|
||||
|
|
Loading…
Add table
Reference in a new issue