daemon: Add an example script that generates skeleton CORE bindings

from EMANE model manifest files.
This commit is contained in:
Tom Goff 2015-09-23 16:45:47 -04:00
parent 1c8c9ce6ea
commit 63ff54243e
2 changed files with 215 additions and 0 deletions

View file

@ -32,6 +32,7 @@ dist_coreconf_DATA = $(CONF_FILES)
EXAMPLE_FILES = \ EXAMPLE_FILES = \
examples/controlnet_updown \ examples/controlnet_updown \
examples/emanemanifest2core.py \
examples/emanemodel2core.py \ examples/emanemodel2core.py \
examples/findcore.py \ examples/findcore.py \
examples/stopsession.py examples/stopsession.py

View file

@ -0,0 +1,214 @@
#!/usr/bin/env python
from emanesh import manifest
import os.path
import re
import textwrap
class EmaneManifest2Model(object):
class EmaneModel(object):
class EmaneModelParameter(object):
intfloat_regex = re.compile(r'^([0-9]+)\.(0*)$')
indent = ' ' * 16
def __init__(self, name, apitype, default, caption,
possible_values = ()):
self.name = name
self.apitype = apitype
self.default = self.intfloat_regex.sub(r'\1.0', default)
self.possible_values = possible_values
self.caption = caption
def __str__(self):
return '''%s('%s', %s,\n%s '%s', '%s', '%s')''' % \
(self.indent, self.name, self.apitype,
self.indent, self.default,
','.join(self.possible_values), self.caption)
def __init__(self, name):
self.name = name
self.parameters = []
def add_parameter(self, name, apitype, default, caption,
possible_values = ()):
p = self.EmaneModelParameter(name, apitype, default, caption,
possible_values)
self.parameters.append(p)
mac_xml_path = '/usr/share/emane/xml/models/mac'
# map emane parameter types to CORE api data types
core_api_type = {
'uint8': 'coreapi.CONF_DATA_TYPE_UINT8',
'uint16': 'coreapi.CONF_DATA_TYPE_UINT16',
'uint32': 'coreapi.CONF_DATA_TYPE_UINT32',
'uint64': 'coreapi.CONF_DATA_TYPE_UINT64',
'int8': 'coreapi.CONF_DATA_TYPE_INT8',
'int16': 'coreapi.CONF_DATA_TYPE_INT16',
'int32': 'coreapi.CONF_DATA_TYPE_INT32',
'int64': 'coreapi.CONF_DATA_TYPE_INT64',
'float': 'coreapi.CONF_DATA_TYPE_FLOAT',
'double': 'coreapi.CONF_DATA_TYPE_FLOAT',
'bool': 'coreapi.CONF_DATA_TYPE_BOOL',
'string': 'coreapi.CONF_DATA_TYPE_STRING',
}
parameter_regex = re.compile(r'^\^\(([\|\-\w]+)\)\$$')
@classmethod
def emane_model(cls, xmlfile):
m = manifest.Manifest(xmlfile)
model = cls.EmaneModel(m.getName())
for name in m.getAllConfiguration():
info = m.getConfigurationInfo(name)
apitype = None
for t in 'numeric', 'nonnumeric':
if t in info:
apitype = cls.core_api_type[info[t]['type']]
break
default = ''
if info['default']:
values = info['values']
if values:
default = values[0]
caption = name
possible_values = []
if apitype == 'coreapi.CONF_DATA_TYPE_BOOL':
possible_values = ['On,Off']
elif apitype == 'coreapi.CONF_DATA_TYPE_STRING':
if name == 'pcrcurveuri':
default = os.path.join(cls.mac_xml_path,
model.name, model.name + 'pcr.xml')
else:
regex = info['regex']
if regex:
match = cls.parameter_regex.match(regex)
if match:
possible_values = match.group(1).split('|')
model.add_parameter(name, apitype, default,
caption, possible_values)
model.parameters.sort(key = lambda x: x.name)
return model
@classmethod
def core_emane_model(cls, class_name, macmanifest_filename,
phymanifest_filename):
template = '''\
from core.emane.emane import EmaneModel
from core.api import coreapi
class BaseEmaneModel(EmaneModel):
def __init__(self, session, objid = None, verbose = False):
EmaneModel.__init__(self, session, objid, verbose)
def buildnemxmlfiles(self, e, ifc):
\'\'\'\\
Build the necessary nem, mac, and phy XMLs in the given path.
If an individual NEM has a nonstandard config, we need to
build that file also. Otherwise the WLAN-wide
nXXemane_*nem.xml, nXXemane_*mac.xml, nXXemane_*phy.xml are
used.
\'\'\'
values = e.getifcconfig(self.objid, self._name,
self.getdefaultvalues(), ifc)
if values is None:
return
nemdoc = e.xmldoc('nem')
nem = nemdoc.getElementsByTagName('nem').pop()
e.appendtransporttonem(nemdoc, nem, self.objid, ifc)
def append_definition(tag, name, xmlname, doc):
el = doc.createElement(name)
el.setAttribute('definition', xmlname)
tag.appendChild(el)
append_definition(nem, 'mac', self.macxmlname(ifc), nemdoc)
append_definition(nem, 'phy', self.phyxmlname(ifc), nemdoc)
e.xmlwrite(nemdoc, self.nemxmlname(ifc))
names = list(self.getnames())
def append_options(tag, optnames, doc):
for name in optnames:
value = self.valueof(name, values).strip()
if value:
tag.appendChild(e.xmlparam(doc, name, value))
macdoc = e.xmldoc('mac')
mac = macdoc.getElementsByTagName('mac').pop()
mac.setAttribute('library', '%(modelLibrary)s')
# append MAC options to macdoc
append_options(mac, names[:len(self._confmatrix_mac)], macdoc)
e.xmlwrite(macdoc, self.macxmlname(ifc))
phydoc = e.xmldoc('phy')
phy = phydoc.getElementsByTagName('phy').pop()
# append PHY options to phydoc
append_options(phy, names[len(self._confmatrix_mac):], phydoc)
e.xmlwrite(phydoc, self.phyxmlname(ifc))
class %(modelClass)s(BaseEmaneModel):
# model name
_name = 'emane_%(modelName)s'
# configuration parameters are
# ( 'name', 'type', 'default', 'possible-value-list', 'caption')
# MAC parameters
_confmatrix_mac = [\n%(confMatrixMac)s
]
# PHY parameters
_confmatrix_phy = [\n%(confMatrixPhy)s
]
_confmatrix = _confmatrix_mac + _confmatrix_phy
# value groupings
_confgroups = 'MAC Parameters:1-%%s|PHY Parameters:%%s-%%s' %% \\
(len(_confmatrix_mac), \\
len(_confmatrix_mac) + 1, len(_confmatrix))
'''
macmodel = cls.emane_model(macmanifest_filename)
phymodel = cls.emane_model(phymanifest_filename)
d = {
'modelClass': 'Emane%sModel' % (class_name),
'modelName': macmodel.name,
'confMatrixMac': ',\n'.join(map(str, macmodel.parameters)) + ',',
'confMatrixPhy': ',\n'.join(map(str, phymodel.parameters)) + ',',
'modelLibrary': macmodel.name,
}
return textwrap.dedent(template % d)
def main():
import argparse
import sys
parser = argparse.ArgumentParser(
formatter_class=argparse.RawDescriptionHelpFormatter,
description = 'Create skeleton CORE bindings from ' \
'EMANE model manifest files.',
epilog = 'example:\n' \
' %(prog)s -c RadioX \\\n' \
' -m /usr/share/emane/manifest/radiox.xml \\\n' \
' -p /usr/share/emane/manifest/emanephy.xml')
parser.add_argument('-c', '--class-name', dest = 'classname',
required = True, help = 'corresponding python '
'class name: RadioX -> EmaneRadioXModel')
parser.add_argument('-m', '--mac-xmlfile', dest = 'macxmlfilename',
required = True,
help = 'MAC model manifest XML filename')
parser.add_argument('-p', '--phy-xmlfile', dest = 'phyxmlfilename',
required = True,
help = 'PHY model manifest XML filename')
args = parser.parse_args()
model = EmaneManifest2Model.core_emane_model(args.classname,
args.macxmlfilename,
args.phyxmlfilename)
sys.stdout.write(model)
if __name__ == "__main__":
main()