daemon: Initial support for exporting a scenario using the new NRL
Network Modeling Framework (NMF) XML representation.
This commit is contained in:
parent
04e98a8004
commit
08c9fd8bf5
4 changed files with 994 additions and 3 deletions
|
@ -27,7 +27,7 @@ def opensessionxml(session, filename, start=False, nodecls=nodes.CoreNode):
|
||||||
session.node_count = str(session.getnodecount())
|
session.node_count = str(session.getnodecount())
|
||||||
session.instantiate()
|
session.instantiate()
|
||||||
|
|
||||||
def savesessionxml(session, filename, version = 0.0):
|
def savesessionxml(session, filename, version):
|
||||||
''' Export a session to the EmulationScript XML format.
|
''' Export a session to the EmulationScript XML format.
|
||||||
'''
|
'''
|
||||||
doc = core_document_writer(session, version)
|
doc = core_document_writer(session, version)
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
# See the LICENSE file included in this distribution.
|
# See the LICENSE file included in this distribution.
|
||||||
|
|
||||||
from xmlwriter0 import CoreDocumentWriter0
|
from xmlwriter0 import CoreDocumentWriter0
|
||||||
|
from xmlwriter1 import CoreDocumentWriter1
|
||||||
|
|
||||||
def core_document_writer(session, version):
|
def core_document_writer(session, version):
|
||||||
if version == 0.0:
|
if version == '0.0':
|
||||||
doc = CoreDocumentWriter0(session)
|
doc = CoreDocumentWriter0(session)
|
||||||
|
elif version == '1.0':
|
||||||
|
doc = CoreDocumentWriter1(session)
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'unsupported document version: %s' % version
|
raise ValueError, 'unsupported document version: %s' % version
|
||||||
return doc
|
return doc
|
||||||
|
|
987
daemon/core/misc/xmlwriter1.py
Normal file
987
daemon/core/misc/xmlwriter1.py
Normal file
|
@ -0,0 +1,987 @@
|
||||||
|
#
|
||||||
|
# CORE
|
||||||
|
# Copyright (c)2011-2015 the Boeing Company.
|
||||||
|
# See the LICENSE file included in this distribution.
|
||||||
|
#
|
||||||
|
# Created on Dec 18, 2014
|
||||||
|
#
|
||||||
|
# @author: santiago
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pwd
|
||||||
|
import collections
|
||||||
|
from core.netns import nodes
|
||||||
|
from core.api import coreapi
|
||||||
|
from core.misc.ipaddr import *
|
||||||
|
|
||||||
|
from xml.dom.minidom import Document
|
||||||
|
from xmlutils import *
|
||||||
|
from xmldeployment import CoreDeploymentWriter
|
||||||
|
|
||||||
|
def enum(**enums):
|
||||||
|
return type('Enum', (), enums)
|
||||||
|
|
||||||
|
class Attrib(object):
|
||||||
|
''' scenario plan attribute constants
|
||||||
|
'''
|
||||||
|
NetType = enum(WIRELESS = 'wireless', ETHERNET = 'ethernet',
|
||||||
|
PTP_WIRED = 'point-to-point-wired',
|
||||||
|
PTP_WIRELESS = 'point-to-point-wireless')
|
||||||
|
MembType = enum(INTERFACE = 'interface', CHANNEL = 'channel',
|
||||||
|
SWITCH = 'switch', HUB = 'hub', TUNNEL = 'tunnel',
|
||||||
|
NETWORK = "network")
|
||||||
|
DevType = enum(HOST = 'host', ROUTER = 'router', SWITCH = 'switch',
|
||||||
|
HUB = 'hub')
|
||||||
|
NodeType = enum(ROUTER = 'router', HOST = 'host', MDR = 'mdr',
|
||||||
|
PC = 'PC', RJ45 = 'rj45')
|
||||||
|
Alias = enum(ID = "COREID")
|
||||||
|
|
||||||
|
''' A link endpoint in CORE
|
||||||
|
net: the network that the endpoint belongs to
|
||||||
|
netif: the network interface at this end
|
||||||
|
id: the identifier for the endpoint
|
||||||
|
l2devport: if the other end is a layer 2 device, this is the assigned port in that device
|
||||||
|
params: link/interface parameters
|
||||||
|
'''
|
||||||
|
Endpoint = collections.namedtuple('Endpoint',
|
||||||
|
['net', 'netif', 'type', 'id', 'l2devport', 'params'])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CoreDocumentWriter1(Document):
|
||||||
|
''' Utility class for writing a CoreSession to XML in the NMF scenPlan schema. The init
|
||||||
|
method builds an xml.dom.minidom.Document, and the writexml() method saves the XML file.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, session):
|
||||||
|
''' Create an empty Scenario XML Document, then populate it with
|
||||||
|
objects from the given session.
|
||||||
|
'''
|
||||||
|
Document.__init__(self)
|
||||||
|
session.info('Exporting to NMF XML version 1.0')
|
||||||
|
with session._objslock:
|
||||||
|
self.scenarioPlan = ScenarioPlan(self, session)
|
||||||
|
if session.getstate() == coreapi.CORE_EVENT_RUNTIME_STATE:
|
||||||
|
deployment = CoreDeploymentWriter(self, self.scenarioPlan,
|
||||||
|
session)
|
||||||
|
deployment.add_deployment()
|
||||||
|
self.scenarioPlan.setAttribute('deployed', 'true')
|
||||||
|
|
||||||
|
def writexml(self, filename):
|
||||||
|
''' Commit to file
|
||||||
|
'''
|
||||||
|
self.scenarioPlan.coreSession.info("saving session XML file %s" % filename)
|
||||||
|
f = open(filename, "w")
|
||||||
|
Document.writexml(self, writer=f, indent="", addindent=" ", newl="\n", \
|
||||||
|
encoding="UTF-8")
|
||||||
|
f.close()
|
||||||
|
if self.scenarioPlan.coreSession.user is not None:
|
||||||
|
uid = pwd.getpwnam(self.scenarioPlan.coreSession.user).pw_uid
|
||||||
|
gid = os.stat(self.scenarioPlan.coreSession.sessiondir).st_gid
|
||||||
|
os.chown(filename, uid, gid)
|
||||||
|
|
||||||
|
|
||||||
|
class XmlElement(object):
|
||||||
|
''' The base class for all XML elements in the scenario plan. Includes
|
||||||
|
convenience functions.
|
||||||
|
'''
|
||||||
|
def __init__(self, document, parent, elementType):
|
||||||
|
self.document = document
|
||||||
|
self.parent = parent
|
||||||
|
self.baseEle = document.createElement("%s" % elementType)
|
||||||
|
if self.parent is not None:
|
||||||
|
self.parent.appendChild(self.baseEle)
|
||||||
|
|
||||||
|
def createElement(self, elementTag):
|
||||||
|
return self.document.createElement(elementTag)
|
||||||
|
|
||||||
|
def getTagName(self):
|
||||||
|
return self.baseEle.tagName
|
||||||
|
|
||||||
|
def createTextNode(self, nodeTag):
|
||||||
|
return self.document.createTextNode(nodeTag)
|
||||||
|
|
||||||
|
def appendChild(self, child):
|
||||||
|
if isinstance(child, XmlElement):
|
||||||
|
self.baseEle.appendChild(child.baseEle)
|
||||||
|
else:
|
||||||
|
self.baseEle.appendChild(child)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_parameter(doc, parent, key, value):
|
||||||
|
if key and value:
|
||||||
|
parm = doc.createElement("parameter")
|
||||||
|
parm.setAttribute("name", str(key))
|
||||||
|
parm.appendChild(doc.createTextNode(str(value)))
|
||||||
|
parent.appendChild(parm)
|
||||||
|
|
||||||
|
def addParameter(self, key, value):
|
||||||
|
'''
|
||||||
|
Add a parameter to the xml element
|
||||||
|
'''
|
||||||
|
self.add_parameter(self.document, self, key, value)
|
||||||
|
|
||||||
|
def setAttribute(self, name, val):
|
||||||
|
self.baseEle.setAttribute(name, val)
|
||||||
|
|
||||||
|
def getAttribute(self, name):
|
||||||
|
return self.baseEle.getAttribute(name)
|
||||||
|
|
||||||
|
|
||||||
|
class NamedXmlElement(XmlElement):
|
||||||
|
''' The base class for all "named" xml elements. Named elements are
|
||||||
|
xml elements in the scenario plan that have an id and a name attribute.
|
||||||
|
'''
|
||||||
|
def __init__(self, scenPlan, parent, elementType, elementName):
|
||||||
|
XmlElement.__init__(self, scenPlan.document, parent, elementType)
|
||||||
|
|
||||||
|
self.scenPlan = scenPlan
|
||||||
|
self.coreSession = scenPlan.coreSession
|
||||||
|
|
||||||
|
elementPath = ''
|
||||||
|
self.id=None
|
||||||
|
if self.parent is not None and isinstance(self.parent, XmlElement) and self.parent.getTagName() != "scenario":
|
||||||
|
elementPath="%s/" % self.parent.getAttribute("id")
|
||||||
|
|
||||||
|
self.id = "%s%s" % (elementPath,elementName)
|
||||||
|
self.setAttribute("name", elementName)
|
||||||
|
self.setAttribute("id", self.id)
|
||||||
|
|
||||||
|
|
||||||
|
def addPoint(self, coreObj):
|
||||||
|
''' Add position to an object
|
||||||
|
'''
|
||||||
|
(x,y,z) = coreObj.position.get()
|
||||||
|
if x is None or y is None:
|
||||||
|
return
|
||||||
|
lat, lon, alt = self.coreSession.location.getgeo(x, y, z)
|
||||||
|
|
||||||
|
pt = self.createElement("point")
|
||||||
|
pt.setAttribute("type", "gps")
|
||||||
|
pt.setAttribute("lat", "%s" % lat)
|
||||||
|
pt.setAttribute("lon", "%s" % lon)
|
||||||
|
if z:
|
||||||
|
pt.setAttribute("z", "%s" % alt)
|
||||||
|
self.appendChild(pt)
|
||||||
|
|
||||||
|
def createAlias(self, domain, valueStr):
|
||||||
|
''' Create an alias element for CORE specific information
|
||||||
|
'''
|
||||||
|
a = self.createElement("alias")
|
||||||
|
a.setAttribute("domain", "%s" % domain)
|
||||||
|
a.appendChild(self.createTextNode(valueStr))
|
||||||
|
return a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ScenarioPlan(XmlElement):
|
||||||
|
''' Container class for ScenarioPlan.
|
||||||
|
'''
|
||||||
|
def __init__(self, document, session):
|
||||||
|
XmlElement.__init__(self, document, parent=document, elementType='scenario')
|
||||||
|
|
||||||
|
self.coreSession = session
|
||||||
|
|
||||||
|
self.setAttribute('version', '1.0')
|
||||||
|
self.setAttribute("name", "%s" % session.name)
|
||||||
|
|
||||||
|
self.setAttribute('xmlns', 'nmfPlan')
|
||||||
|
self.setAttribute('xmlns:CORE', 'coreSpecific')
|
||||||
|
self.setAttribute('compiled', 'true')
|
||||||
|
|
||||||
|
self.allChannelMembers = dict()
|
||||||
|
self.lastNetIdx = 0
|
||||||
|
self.addNetworks()
|
||||||
|
self.addDevices()
|
||||||
|
|
||||||
|
# XXX Do we need these?
|
||||||
|
#self.session.emane.setup() # not during runtime?
|
||||||
|
#self.addorigin()
|
||||||
|
|
||||||
|
self.addDefaultServices()
|
||||||
|
|
||||||
|
self.addSessionConfiguration()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def addNetworks(self):
|
||||||
|
''' Add networks in the session to the scenPlan.
|
||||||
|
'''
|
||||||
|
for net in self.coreSession.objs():
|
||||||
|
if not isinstance(net, nodes.PyCoreNet):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(net, nodes.CtrlNet):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Do not add switches and hubs that belong to another network
|
||||||
|
if isinstance(net, (nodes.SwitchNode, nodes.HubNode)):
|
||||||
|
if inOtherNetwork(net):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
NetworkElement(self, self, net)
|
||||||
|
except:
|
||||||
|
if hasattr(net, "name") and net.name:
|
||||||
|
self.coreSession.warn('Unsupported net: %s' % net.name)
|
||||||
|
else:
|
||||||
|
self.coreSession.warn('Unsupported net: %s' % net.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def addDevices(self):
|
||||||
|
''' Add device elements to the scenario plan.
|
||||||
|
'''
|
||||||
|
for node in self.coreSession.objs():
|
||||||
|
if not isinstance(node, (nodes.PyCoreNode)):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
DeviceElement(self, self, node)
|
||||||
|
except:
|
||||||
|
if hasattr(node, "name") and node.name:
|
||||||
|
self.coreSession.warn('Unsupported device: %s' % node.name)
|
||||||
|
else:
|
||||||
|
self.coreSession.warn('Unsupported device: %s' % node.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def addDefaultServices(self):
|
||||||
|
''' Add default services and node types to the ServicePlan.
|
||||||
|
'''
|
||||||
|
defaultservices = self.createElement("CORE:defaultservices")
|
||||||
|
for type in self.coreSession.services.defaultservices:
|
||||||
|
defaults = self.coreSession.services.getdefaultservices(type)
|
||||||
|
spn = self.createElement("device")
|
||||||
|
spn.setAttribute("type", type)
|
||||||
|
defaultservices.appendChild(spn)
|
||||||
|
for svc in defaults:
|
||||||
|
s = self.createElement("service")
|
||||||
|
spn.appendChild(s)
|
||||||
|
s.setAttribute("name", str(svc._name))
|
||||||
|
if defaultservices.hasChildNodes():
|
||||||
|
self.appendChild(defaultservices)
|
||||||
|
|
||||||
|
def addSessionConfiguration(self):
|
||||||
|
''' Add CORE-specific session configuration XML elements.
|
||||||
|
'''
|
||||||
|
config = self.createElement("CORE:sessionconfig")
|
||||||
|
|
||||||
|
# origin: geolocation of cartesian coordinate 0,0,0
|
||||||
|
refgeo = self.coreSession.location.refgeo
|
||||||
|
origin = self.createElement("origin")
|
||||||
|
attrs = ("lat","lon","alt")
|
||||||
|
have_origin = False
|
||||||
|
for i in xrange(3):
|
||||||
|
if refgeo[i] is not None:
|
||||||
|
origin.setAttribute(attrs[i], str(refgeo[i]))
|
||||||
|
have_origin = True
|
||||||
|
if have_origin:
|
||||||
|
if self.coreSession.location.refscale != 1.0: # 100 pixels = refscale m
|
||||||
|
origin.setAttribute("scale100", str(self.coreSession.location.refscale))
|
||||||
|
if self.coreSession.location.refxyz != (0.0, 0.0, 0.0):
|
||||||
|
pt = self.createElement("point")
|
||||||
|
origin.appendChild(pt)
|
||||||
|
x,y,z = self.coreSession.location.refxyz
|
||||||
|
coordstxt = "%s,%s" % (x,y)
|
||||||
|
if z:
|
||||||
|
coordstxt += ",%s" % z
|
||||||
|
coords = self.createTextNode(coordstxt)
|
||||||
|
pt.appendChild(coords)
|
||||||
|
config.appendChild(origin)
|
||||||
|
|
||||||
|
|
||||||
|
# options
|
||||||
|
options = self.createElement("options")
|
||||||
|
defaults = self.coreSession.options.getdefaultvalues()
|
||||||
|
for i, (k, v) in enumerate(self.coreSession.options.getkeyvaluelist()):
|
||||||
|
if str(v) != str(defaults[i]):
|
||||||
|
XmlElement.add_parameter(self.document, options, k, v)
|
||||||
|
if options.hasChildNodes():
|
||||||
|
config.appendChild(options)
|
||||||
|
|
||||||
|
# hook scripts
|
||||||
|
hooks = self.createElement("hooks")
|
||||||
|
for state in sorted(self.coreSession._hooks.keys()):
|
||||||
|
for (filename, data) in self.coreSession._hooks[state]:
|
||||||
|
hook = self.createElement("hook")
|
||||||
|
hook.setAttribute("name", filename)
|
||||||
|
hook.setAttribute("state", str(state))
|
||||||
|
txt = self.createTextNode(data)
|
||||||
|
hook.appendChild(txt)
|
||||||
|
hooks.appendChild(hook)
|
||||||
|
if hooks.hasChildNodes():
|
||||||
|
config.appendChild(hooks)
|
||||||
|
|
||||||
|
# metadata
|
||||||
|
meta = self.createElement("metadata")
|
||||||
|
for (k, v) in self.coreSession.metadata.items():
|
||||||
|
XmlElement.add_parameter(self.document, meta, k, v)
|
||||||
|
if meta.hasChildNodes():
|
||||||
|
config.appendChild(meta)
|
||||||
|
|
||||||
|
if config.hasChildNodes():
|
||||||
|
self.appendChild(config)
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkElement(NamedXmlElement):
|
||||||
|
def __init__(self, scenPlan, parent, netObj):
|
||||||
|
''' Add one PyCoreNet object as one network XML element.
|
||||||
|
'''
|
||||||
|
elementName = self.getNetworkName(scenPlan, netObj)
|
||||||
|
NamedXmlElement.__init__(self, scenPlan, parent, "network", elementName)
|
||||||
|
|
||||||
|
self.scenPlan = scenPlan
|
||||||
|
|
||||||
|
self.addPoint(netObj)
|
||||||
|
|
||||||
|
netType = None
|
||||||
|
if isinstance(netObj, (nodes.WlanNode, nodes.EmaneNode)):
|
||||||
|
netType = Attrib.NetType.WIRELESS
|
||||||
|
elif isinstance(netObj, (nodes.SwitchNode, nodes.HubNode,
|
||||||
|
nodes.PtpNet, nodes.TunnelNode)):
|
||||||
|
netType = Attrib.NetType.ETHERNET
|
||||||
|
else:
|
||||||
|
netType ="%s" % netObj.__class__.__name__
|
||||||
|
|
||||||
|
typeEle = self.createElement("type")
|
||||||
|
typeEle.appendChild(self.createTextNode(netType))
|
||||||
|
self.appendChild(typeEle)
|
||||||
|
|
||||||
|
# Gather all endpoints belonging to this network
|
||||||
|
self.endpoints = getEndpoints(netObj)
|
||||||
|
|
||||||
|
# Special case for a network of switches and hubs
|
||||||
|
createAlias = True
|
||||||
|
self.l2devices = []
|
||||||
|
if isinstance(netObj, (nodes.SwitchNode, nodes.HubNode)):
|
||||||
|
createAlias = False
|
||||||
|
self.appendChild(typeEle)
|
||||||
|
self.addL2Devices(netObj)
|
||||||
|
|
||||||
|
if createAlias:
|
||||||
|
a = self.createAlias(Attrib.Alias.ID, "%d" % int(netObj.objid))
|
||||||
|
self.appendChild(a)
|
||||||
|
|
||||||
|
# XXXX TODO: Move this to channel?
|
||||||
|
# key used with tunnel node
|
||||||
|
if hasattr(netObj, 'grekey') and netObj.grekey is not None:
|
||||||
|
a = self.createAlias("COREGREKEY", "%s" % netObj.grekey)
|
||||||
|
self.appendChild(a)
|
||||||
|
|
||||||
|
self.addNetMembers(netObj)
|
||||||
|
self.addChannels(netObj)
|
||||||
|
|
||||||
|
presentationEle = self.createElement("CORE:presentation")
|
||||||
|
addPresentationEle = False
|
||||||
|
if netObj.icon and not netObj.icon.isspace():
|
||||||
|
presentationEle.setAttribute("icon", netObj.icon)
|
||||||
|
addPresentationEle = True
|
||||||
|
if netObj.canvas:
|
||||||
|
presentationEle.setAttribute("canvas", str(netObj.canvas))
|
||||||
|
addPresentationEle = True
|
||||||
|
if addPresentationEle:
|
||||||
|
self.appendChild(presentationEle)
|
||||||
|
|
||||||
|
def getNetworkName(self, scenPlan, netObj):
|
||||||
|
''' Determine the name to use for this network element
|
||||||
|
'''
|
||||||
|
if isinstance(netObj, (nodes.PtpNet, nodes.TunnelNode)):
|
||||||
|
name = "net%s" % scenPlan.lastNetIdx
|
||||||
|
scenPlan.lastNetIdx += 1
|
||||||
|
elif netObj.name:
|
||||||
|
name = str(netObj.name) # could use net.brname for bridges?
|
||||||
|
elif isinstance(netObj, (nodes.SwitchNode, nodes.HubNode)):
|
||||||
|
name = "lan%s" % netObj.objid
|
||||||
|
else:
|
||||||
|
name = ''
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def addL2Devices(self, netObj):
|
||||||
|
''' Add switches and hubs
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Add the netObj as a device
|
||||||
|
self.l2devices.append(DeviceElement(self.scenPlan, self, netObj))
|
||||||
|
|
||||||
|
# Add downstream switches/hubs
|
||||||
|
l2devs = []
|
||||||
|
neweps = []
|
||||||
|
for ep in self.endpoints:
|
||||||
|
if ep.type and ep.net.objid != netObj.objid:
|
||||||
|
l2s, eps = getDowmstreamL2Devices(ep.net)
|
||||||
|
l2devs.extend(l2s)
|
||||||
|
neweps.extend(eps)
|
||||||
|
|
||||||
|
for l2dev in l2devs:
|
||||||
|
self.l2devices.append(DeviceElement(self.scenPlan, self, l2dev))
|
||||||
|
|
||||||
|
self.endpoints.extend(neweps)
|
||||||
|
|
||||||
|
# XXX: Optimize later
|
||||||
|
def addNetMembers(self, netObj):
|
||||||
|
''' Add members to a network XML element.
|
||||||
|
'''
|
||||||
|
|
||||||
|
for ep in self.endpoints:
|
||||||
|
if ep.type:
|
||||||
|
MemberElement(self.scenPlan, self, referencedType=ep.type, referencedId=ep.id)
|
||||||
|
|
||||||
|
if ep.l2devport:
|
||||||
|
MemberElement(self.scenPlan,
|
||||||
|
self,
|
||||||
|
referencedType=Attrib.MembType.INTERFACE,
|
||||||
|
referencedId="%s/%s" % (self.id,ep.l2devport))
|
||||||
|
|
||||||
|
# XXX Revisit this
|
||||||
|
# Create implied members given the network type
|
||||||
|
if isinstance(netObj, nodes.TunnelNode):
|
||||||
|
MemberElement(self.scenPlan,
|
||||||
|
self,
|
||||||
|
referencedType=Attrib.MembType.TUNNEL,
|
||||||
|
referencedId="%s/%s" % (netObj.name, netObj.name))
|
||||||
|
|
||||||
|
# XXX: Optimize later
|
||||||
|
def addChannels(self, netObj):
|
||||||
|
''' Add channels to a network XML element
|
||||||
|
'''
|
||||||
|
|
||||||
|
if isinstance(netObj, (nodes.WlanNode, nodes.EmaneNode)):
|
||||||
|
modelconfigs = netObj.session.mobility.getmodels(netObj)
|
||||||
|
modelconfigs += netObj.session.emane.getmodels(netObj)
|
||||||
|
chan = None
|
||||||
|
for (model, conf) in modelconfigs:
|
||||||
|
# Handle mobility parameters below
|
||||||
|
if model._type == coreapi.CORE_TLV_REG_MOBILITY:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Create the channel
|
||||||
|
if chan is None:
|
||||||
|
name = "wireless"
|
||||||
|
chan = ChannelElement(self.scenPlan, self, netObj,
|
||||||
|
channelType=model._name,
|
||||||
|
channelName=name,
|
||||||
|
channelDomain="CORE")
|
||||||
|
|
||||||
|
# Add wireless model parameters
|
||||||
|
for i, key in enumerate(model.getnames()):
|
||||||
|
value = conf[i]
|
||||||
|
if value is not None:
|
||||||
|
chan.addParameter(key, model.valueof(key, conf))
|
||||||
|
|
||||||
|
for (model, conf) in modelconfigs:
|
||||||
|
if model._type == coreapi.CORE_TLV_REG_MOBILITY:
|
||||||
|
# Add wireless mobility parameters
|
||||||
|
mobility = XmlElement(self.scenPlan, chan, "CORE:mobility")
|
||||||
|
# Add a type child
|
||||||
|
typeEle = self.createElement("type")
|
||||||
|
typeEle.appendChild(self.createTextNode(model._name))
|
||||||
|
mobility.appendChild(typeEle)
|
||||||
|
for i, key in enumerate(model.getnames()):
|
||||||
|
value = conf[i]
|
||||||
|
if value is not None:
|
||||||
|
mobility.addParameter(key, value)
|
||||||
|
|
||||||
|
# Add members to the channel
|
||||||
|
if chan is not None:
|
||||||
|
chan.addChannelMembers(self.endpoints)
|
||||||
|
self.appendChild(chan.baseEle)
|
||||||
|
elif isinstance(netObj, nodes.PtpNet) :
|
||||||
|
if len(self.endpoints) < 2:
|
||||||
|
if len(self.endpoints) == 1:
|
||||||
|
self.coreSession.warn('Pt2Pt network with only 1 endpoint: %s' % self.endpoints[0].id)
|
||||||
|
else:
|
||||||
|
self.coreSession.warn('Pt2Pt network with no endpoints encountered in %s' % netObj.name)
|
||||||
|
return
|
||||||
|
name = "chan%d" % (0)
|
||||||
|
chan = ChannelElement(self.scenPlan, self, netObj,
|
||||||
|
channelType=Attrib.NetType.ETHERNET,
|
||||||
|
channelName=name)
|
||||||
|
|
||||||
|
# Add interface parameters
|
||||||
|
if self.endpoints[0].params != self.endpoints[1].params:
|
||||||
|
self.coreSession.warn('Pt2Pt Endpoint parameters do not match in %s' % netObj.name)
|
||||||
|
for key, value in self.endpoints[0].params:
|
||||||
|
# XXX lifted from original addnetem function. revisit this.
|
||||||
|
# default netem parameters are 0 or None
|
||||||
|
if value is None or value == 0:
|
||||||
|
continue
|
||||||
|
if key == "has_netem" or key == "has_tbf":
|
||||||
|
continue
|
||||||
|
chan.addParameter(key, value)
|
||||||
|
|
||||||
|
# Add members to the channel
|
||||||
|
chan.addChannelMembers(self.endpoints)
|
||||||
|
self.appendChild(chan)
|
||||||
|
|
||||||
|
elif isinstance(netObj, (nodes.SwitchNode,
|
||||||
|
nodes.HubNode, nodes.TunnelNode)):
|
||||||
|
cidx=0
|
||||||
|
channels = []
|
||||||
|
for ep in self.endpoints:
|
||||||
|
# Create one channel member per ep
|
||||||
|
if ep.type:
|
||||||
|
name = "chan%d" % (cidx)
|
||||||
|
chan = ChannelElement(self.scenPlan, self, netObj,
|
||||||
|
channelType=Attrib.NetType.ETHERNET,
|
||||||
|
channelName=name)
|
||||||
|
|
||||||
|
# Add interface parameters
|
||||||
|
for key, value in ep.params:
|
||||||
|
# XXX lifted from original addnetem function. revisit this.
|
||||||
|
# default netem parameters are 0 or None
|
||||||
|
if value is None or value == 0:
|
||||||
|
continue
|
||||||
|
if key == "has_netem" or key == "has_tbf":
|
||||||
|
continue
|
||||||
|
chan.addParameter(key, value)
|
||||||
|
|
||||||
|
# Add members to the channel
|
||||||
|
chan.addChannelMembers(ep)
|
||||||
|
channels.append(chan)
|
||||||
|
cidx += 1
|
||||||
|
|
||||||
|
for chan in channels:
|
||||||
|
self.appendChild(chan)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceElement(NamedXmlElement):
|
||||||
|
''' A device element in the scenario plan.
|
||||||
|
'''
|
||||||
|
def __init__(self, scenPlan, parent, devObj):
|
||||||
|
''' Add a PyCoreNode object as a device element.
|
||||||
|
'''
|
||||||
|
|
||||||
|
devType = None
|
||||||
|
coreDevType = None
|
||||||
|
if hasattr(devObj, "type") and devObj.type:
|
||||||
|
coreDevType = devObj.type
|
||||||
|
if devObj.type == Attrib.NodeType.ROUTER:
|
||||||
|
devType = Attrib.DevType.ROUTER
|
||||||
|
elif devObj.type == Attrib.NodeType.MDR:
|
||||||
|
devType = Attrib.DevType.ROUTER
|
||||||
|
elif devObj.type == Attrib.NodeType.HOST:
|
||||||
|
devType = Attrib.DevType.HOST
|
||||||
|
elif devObj.type == Attrib.NodeType.PC:
|
||||||
|
devType = Attrib.DevType.HOST
|
||||||
|
elif devObj.type == Attrib.NodeType.RJ45:
|
||||||
|
devType = Attrib.DevType.HOST
|
||||||
|
nodeId = "EMULATOR-HOST"
|
||||||
|
else:
|
||||||
|
# Default custom types (defined in ~/.core/nodes.conf) to HOST
|
||||||
|
devType = Attrib.DevType.HOST
|
||||||
|
|
||||||
|
if devType is None:
|
||||||
|
if isinstance(devObj, nodes.HubNode):
|
||||||
|
devType = Attrib.DevType.HUB
|
||||||
|
elif isinstance(devObj, nodes.SwitchNode):
|
||||||
|
devType = Attrib.DevType.SWITCH
|
||||||
|
|
||||||
|
if devType is None:
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
|
NamedXmlElement.__init__(self, scenPlan, parent, devType, devObj.name)
|
||||||
|
|
||||||
|
if coreDevType is not None:
|
||||||
|
typeEle = self.createElement("type")
|
||||||
|
typeEle.setAttribute("domain", "CORE")
|
||||||
|
typeEle.appendChild(self.createTextNode("%s" % coreDevType))
|
||||||
|
self.appendChild(typeEle)
|
||||||
|
|
||||||
|
self.interfaces = []
|
||||||
|
self.addInterfaces(devObj)
|
||||||
|
alias = self.createAlias(Attrib.Alias.ID, "%s" % devObj.objid)
|
||||||
|
self.appendChild(alias)
|
||||||
|
self.addPoint(devObj)
|
||||||
|
self.addServices(devObj)
|
||||||
|
|
||||||
|
|
||||||
|
presentationEle = self.createElement("CORE:presentation")
|
||||||
|
addPresentationEle = False
|
||||||
|
if devObj.icon and not devObj.icon.isspace():
|
||||||
|
presentationEle.setAttribute("icon", devObj.icon)
|
||||||
|
addPresentationEle = True
|
||||||
|
if devObj.canvas:
|
||||||
|
presentationEle.setAttribute("canvas", str(devObj.canvas))
|
||||||
|
addPresentationEle = True
|
||||||
|
if addPresentationEle:
|
||||||
|
self.appendChild(presentationEle)
|
||||||
|
|
||||||
|
def addInterfaces(self, devObj):
|
||||||
|
''' Add interfaces to a device element.
|
||||||
|
'''
|
||||||
|
idx=0
|
||||||
|
for ifcObj in devObj.netifs(sort=True):
|
||||||
|
if ifcObj.net and isinstance(ifcObj.net, nodes.CtrlNet):
|
||||||
|
continue
|
||||||
|
if isinstance(devObj, nodes.PyCoreNode):
|
||||||
|
ifcEle = InterfaceElement(self.scenPlan, self, devObj, ifcObj)
|
||||||
|
else: # isinstance(node, (nodes.HubNode nodes.SwitchNode)):
|
||||||
|
ifcEle = InterfaceElement(self.scenPlan, self, devObj, ifcObj, idx)
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
netmodel = None
|
||||||
|
if ifcObj.net:
|
||||||
|
if hasattr(ifcObj.net, "model"):
|
||||||
|
netmodel = ifcObj.net.model
|
||||||
|
if ifcObj.mtu and ifcObj.mtu != 1500:
|
||||||
|
ifcEle.setAttribute("mtu", "%s" % ifcObj.mtu)
|
||||||
|
|
||||||
|
# The interfaces returned for Switches and Hubs are the interfaces of the nodes connected to them.
|
||||||
|
# The addresses are for those interfaces. Don't include them here.
|
||||||
|
if isinstance(devObj, nodes.PyCoreNode):
|
||||||
|
# could use ifcObj.params, transport_type
|
||||||
|
ifcEle.addAddresses(ifcObj)
|
||||||
|
# per-interface models
|
||||||
|
# XXX Remove???
|
||||||
|
if netmodel and netmodel._name[:6] == "emane_":
|
||||||
|
cfg = self.coreSession.emane.getifcconfig(devObj.objid, netmodel._name,
|
||||||
|
None, ifcObj)
|
||||||
|
if cfg:
|
||||||
|
ifcEle.addModels(((netmodel, cfg),) )
|
||||||
|
|
||||||
|
self.interfaces.append(ifcEle)
|
||||||
|
|
||||||
|
|
||||||
|
def addServices(self, devObj):
|
||||||
|
''' Add services and their customizations to the ServicePlan.
|
||||||
|
'''
|
||||||
|
if not hasattr(devObj, "services") :
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(devObj.services) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
defaults = self.coreSession.services.getdefaultservices(devObj.type)
|
||||||
|
if devObj.services == defaults:
|
||||||
|
return
|
||||||
|
spn = self.createElement("CORE:services")
|
||||||
|
spn.setAttribute("name", devObj.name)
|
||||||
|
self.appendChild(spn)
|
||||||
|
|
||||||
|
for svc in devObj.services:
|
||||||
|
s = self.createElement("service")
|
||||||
|
spn.appendChild(s)
|
||||||
|
s.setAttribute("name", str(svc._name))
|
||||||
|
s.setAttribute("startup_idx", str(svc._startindex))
|
||||||
|
if svc._starttime != "":
|
||||||
|
s.setAttribute("start_time", str(svc._starttime))
|
||||||
|
# only record service names if not a customized service
|
||||||
|
if not svc._custom:
|
||||||
|
continue
|
||||||
|
s.setAttribute("custom", str(svc._custom))
|
||||||
|
addelementsfromlist(self, s, svc._dirs, "directory", "name")
|
||||||
|
|
||||||
|
for fn in svc._configs:
|
||||||
|
if len(fn) == 0:
|
||||||
|
continue
|
||||||
|
f = self.createElement("file")
|
||||||
|
f.setAttribute("name", fn)
|
||||||
|
# all file names are added to determine when a file has been deleted
|
||||||
|
s.appendChild(f)
|
||||||
|
data = self.coreSession.services.getservicefiledata(svc, fn)
|
||||||
|
if data is None:
|
||||||
|
# this includes only customized file contents and skips
|
||||||
|
# the auto-generated files
|
||||||
|
continue
|
||||||
|
txt = self.createTextNode("\n" + data)
|
||||||
|
f.appendChild(txt)
|
||||||
|
|
||||||
|
addtextelementsfromlist(self, s, svc._startup, "command",
|
||||||
|
(("type","start"),))
|
||||||
|
addtextelementsfromlist(self, s, svc._shutdown, "command",
|
||||||
|
(("type","stop"),))
|
||||||
|
addtextelementsfromlist(self, s, svc._validate, "command",
|
||||||
|
(("type","validate"),))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ChannelElement(NamedXmlElement):
|
||||||
|
''' A channel element in the scenario plan
|
||||||
|
'''
|
||||||
|
def __init__(self, scenPlan, parent, netObj, channelType, channelName, channelDomain=None):
|
||||||
|
NamedXmlElement.__init__(self, scenPlan, parent, "channel", channelName)
|
||||||
|
'''
|
||||||
|
Create a channel element and append a member child referencing this channel element
|
||||||
|
in the parent element.
|
||||||
|
'''
|
||||||
|
# Create a member element for this channel in the parent
|
||||||
|
MemberElement(self.scenPlan,
|
||||||
|
parent,
|
||||||
|
referencedType=Attrib.MembType.CHANNEL,
|
||||||
|
referencedId=self.id)
|
||||||
|
|
||||||
|
# Add a type child
|
||||||
|
typeEle = self.createElement("type")
|
||||||
|
if channelDomain is not None:
|
||||||
|
typeEle.setAttribute("domain", "%s" % channelDomain)
|
||||||
|
typeEle.appendChild(self.createTextNode(channelType))
|
||||||
|
self.appendChild(typeEle)
|
||||||
|
|
||||||
|
|
||||||
|
def addChannelMembers(self, endpoints):
|
||||||
|
'''
|
||||||
|
Add network channel members referencing interfaces in the channel
|
||||||
|
'''
|
||||||
|
if isinstance(endpoints, list):
|
||||||
|
# A list of endpoints is given. Create one channel member per endpoint
|
||||||
|
idx = 0
|
||||||
|
for ep in endpoints:
|
||||||
|
self.addChannelMember(ep.type, ep.id, idx)
|
||||||
|
idx += 1
|
||||||
|
else:
|
||||||
|
# A single endpoint is given. Create one channel member for the endpoint,
|
||||||
|
# and if the endpoint is associated with a Layer 2 device port, add the
|
||||||
|
# port as a second member
|
||||||
|
ep = endpoints
|
||||||
|
self.addChannelMember(ep.type, ep.id, 0)
|
||||||
|
if ep.l2devport is not None:
|
||||||
|
memId = "%s/%s" % (self.parent.getAttribute("id"), ep.l2devport)
|
||||||
|
self.addChannelMember(ep.type, memId, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def addChannelMember(self, memIfcType, memIfcId, memIdx):
|
||||||
|
'''
|
||||||
|
add a member to a given channel
|
||||||
|
'''
|
||||||
|
|
||||||
|
m = MemberElement(self.scenPlan,
|
||||||
|
self,
|
||||||
|
referencedType=memIfcType,
|
||||||
|
referencedId=memIfcId,
|
||||||
|
index=memIdx)
|
||||||
|
self.scenPlan.allChannelMembers[memIfcId] = m
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceElement(NamedXmlElement):
|
||||||
|
'''
|
||||||
|
A network interface element
|
||||||
|
'''
|
||||||
|
def __init__(self, scenPlan, parent, devObj, ifcObj, ifcIdx=None):
|
||||||
|
'''
|
||||||
|
Create a network interface element with references to channel that this
|
||||||
|
interface is used.
|
||||||
|
'''
|
||||||
|
elementName=None
|
||||||
|
if ifcIdx is not None:
|
||||||
|
elementName = "e%d" % ifcIdx
|
||||||
|
else:
|
||||||
|
elementName = ifcObj.name
|
||||||
|
NamedXmlElement.__init__(self, scenPlan, parent, "interface", elementName)
|
||||||
|
self.ifcObj = ifcObj
|
||||||
|
self.addChannelReference()
|
||||||
|
|
||||||
|
def addChannelReference(self):
|
||||||
|
'''
|
||||||
|
Add a reference to the channel that uses this interface
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
cm = self.scenPlan.allChannelMembers[self.id]
|
||||||
|
if cm is not None:
|
||||||
|
ch = cm.baseEle.parentNode
|
||||||
|
if ch is not None:
|
||||||
|
net = ch.parentNode
|
||||||
|
if net is not None:
|
||||||
|
MemberElement(self.scenPlan,
|
||||||
|
self,
|
||||||
|
referencedType=Attrib.MembType.CHANNEL,
|
||||||
|
referencedId=ch.getAttribute("id"),
|
||||||
|
index=int(cm.getAttribute("index")))
|
||||||
|
MemberElement(self.scenPlan,
|
||||||
|
self,
|
||||||
|
referencedType=Attrib.MembType.NETWORK,
|
||||||
|
referencedId=net.getAttribute("id"))
|
||||||
|
except KeyError:
|
||||||
|
pass # Not an error. This occurs when an interface belongs to a switch or a hub within a network and the channel is yet to be defined
|
||||||
|
|
||||||
|
|
||||||
|
def addAddresses(self, ifcObj):
|
||||||
|
'''
|
||||||
|
Add MAC and IP addresses to interface XML elements.
|
||||||
|
'''
|
||||||
|
if ifcObj.hwaddr:
|
||||||
|
h = self.createElement("address")
|
||||||
|
self.appendChild(h)
|
||||||
|
h.setAttribute("type", "mac")
|
||||||
|
htxt = self.createTextNode("%s" % ifcObj.hwaddr)
|
||||||
|
h.appendChild(htxt)
|
||||||
|
for addr in ifcObj.addrlist:
|
||||||
|
a = self.createElement("address")
|
||||||
|
self.appendChild(a)
|
||||||
|
(ip, sep, mask) = addr.partition('/')
|
||||||
|
# mask = int(mask) XXX?
|
||||||
|
if isIPv4Address(ip):
|
||||||
|
a.setAttribute("type", "IPv4")
|
||||||
|
else:
|
||||||
|
a.setAttribute("type", "IPv6")
|
||||||
|
|
||||||
|
# a.setAttribute("type", )
|
||||||
|
atxt = self.createTextNode("%s" % addr)
|
||||||
|
a.appendChild(atxt)
|
||||||
|
|
||||||
|
|
||||||
|
# XXX Remove?
|
||||||
|
def addModels(self, configs):
|
||||||
|
'''
|
||||||
|
Add models from a list of model-class, config values tuples.
|
||||||
|
'''
|
||||||
|
for (m, conf) in configs:
|
||||||
|
modelEle = self.createElement("model")
|
||||||
|
modelEle.setAttribute("name", m._name)
|
||||||
|
typeStr = "wireless"
|
||||||
|
if m._type == coreapi.CORE_TLV_REG_MOBILITY:
|
||||||
|
typeStr = "mobility"
|
||||||
|
modelEle.setAttribute("type", typeStr)
|
||||||
|
for i, k in enumerate(m.getnames()):
|
||||||
|
key = self.createElement(k)
|
||||||
|
value = conf[i]
|
||||||
|
if value is None:
|
||||||
|
value = ""
|
||||||
|
key.appendChild(self.createTextNode("%s" % value))
|
||||||
|
modelEle.appendChild(key)
|
||||||
|
self.appendChild(modelEle)
|
||||||
|
|
||||||
|
|
||||||
|
class MemberElement(XmlElement):
|
||||||
|
'''
|
||||||
|
Member elements are references to other elements in the network plan elements of the scenario.
|
||||||
|
They are used in networks to reference channels, in channels to reference interfaces,
|
||||||
|
and in interfaces to reference networks/channels. Member elements provided allow bi-directional
|
||||||
|
traversal of network plan components.
|
||||||
|
'''
|
||||||
|
def __init__(self, scenPlan, parent, referencedType, referencedId, index=None):
|
||||||
|
'''
|
||||||
|
Create a member element
|
||||||
|
'''
|
||||||
|
XmlElement.__init__(self, scenPlan.document, parent, "member")
|
||||||
|
self.setAttribute("type", "%s" % referencedType)
|
||||||
|
# See'Understanding the Network Modeling Framework document'
|
||||||
|
if index is not None:
|
||||||
|
self.setAttribute("index", "%d" % index)
|
||||||
|
self.appendChild(self.createTextNode("%s" % referencedId))
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# =======================================================================================
|
||||||
|
# Helpers
|
||||||
|
# =======================================================================================
|
||||||
|
def getEndpoint(netObj, ifcObj):
|
||||||
|
'''
|
||||||
|
Create an Endpoint object given the network and the interface of interest
|
||||||
|
'''
|
||||||
|
ep = None
|
||||||
|
l2devport=None
|
||||||
|
|
||||||
|
# if ifcObj references an interface of a node and is part of this network
|
||||||
|
if ifcObj.net.objid == netObj.objid and hasattr(ifcObj,'node') and ifcObj.node:
|
||||||
|
params = ifcObj.getparams()
|
||||||
|
if isinstance(ifcObj.net, (nodes.HubNode, nodes.SwitchNode)):
|
||||||
|
l2devport="%s/e%d" % (ifcObj.net.name, ifcObj.net.getifindex(ifcObj))
|
||||||
|
ep = Endpoint(netObj,
|
||||||
|
ifcObj,
|
||||||
|
type = Attrib.MembType.INTERFACE,
|
||||||
|
id="%s/%s" % (ifcObj.node.name, ifcObj.name),
|
||||||
|
l2devport=l2devport,
|
||||||
|
params=params)
|
||||||
|
|
||||||
|
# else if ifcObj references another node and is connected to this network
|
||||||
|
elif hasattr(ifcObj,"othernet"):
|
||||||
|
if ifcObj.othernet.objid == netObj.objid:
|
||||||
|
# #hack used for upstream parameters for link between switches
|
||||||
|
# #(see LxBrNet.linknet())
|
||||||
|
ifcObj.swapparams('_params_up')
|
||||||
|
params = ifcObj.getparams()
|
||||||
|
ifcObj.swapparams('_params_up')
|
||||||
|
owner = ifcObj.net
|
||||||
|
l2devport="%s/e%d" % (ifcObj.othernet.name, ifcObj.othernet.getifindex(ifcObj))
|
||||||
|
|
||||||
|
# Create the endpoint.
|
||||||
|
# XXX the interface index might not match what is shown in the gui. For switches and hubs,
|
||||||
|
# The gui assigns its index but doesn't pass it to the daemon and vice versa.
|
||||||
|
# The gui stores it's index in the IMN file, which it reads and writes without daemon intervention.
|
||||||
|
# Fix this!
|
||||||
|
ep = Endpoint(owner,
|
||||||
|
ifcObj,
|
||||||
|
type = Attrib.MembType.INTERFACE,
|
||||||
|
id="%s/%s/e%d" % (netObj.name, owner.name, owner.getifindex(ifcObj)),
|
||||||
|
l2devport=l2devport,
|
||||||
|
params=params)
|
||||||
|
# else this node has an interface that belongs to another network
|
||||||
|
# i.e. a switch/hub interface connected to another switch/hub and CORE has the other switch/hub
|
||||||
|
# as the containing network
|
||||||
|
else :
|
||||||
|
ep = Endpoint(netObj, ifcObj,type=None, id=None, l2devport=None, params=None)
|
||||||
|
|
||||||
|
|
||||||
|
return ep
|
||||||
|
|
||||||
|
def getEndpoints(netObj):
|
||||||
|
'''
|
||||||
|
Gather all endpoints of the given network
|
||||||
|
'''
|
||||||
|
# Get all endpoints
|
||||||
|
endpoints = []
|
||||||
|
|
||||||
|
# XXX TODO: How to represent physical interfaces.
|
||||||
|
#
|
||||||
|
# NOTE: The following code works except it would be missing physical (rj45) interfaces from Pt2pt links
|
||||||
|
# TODO: Fix data in net.netifs to include Pt2Pt physical interfaces
|
||||||
|
#
|
||||||
|
# Iterate through all the nodes in the scenario, then iterate through all the interface for each node,
|
||||||
|
# and check if the interface is connected to this network.
|
||||||
|
|
||||||
|
for ifcObj in netObj.netifs(sort=True):
|
||||||
|
try:
|
||||||
|
ep = getEndpoint(netObj, ifcObj)
|
||||||
|
if ep is not None:
|
||||||
|
endpoints.append(ep)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return endpoints
|
||||||
|
|
||||||
|
def getDowmstreamL2Devices(netObj):
|
||||||
|
'''
|
||||||
|
Helper function for getting a list of all downstream layer 2 devices from the given netObj
|
||||||
|
'''
|
||||||
|
l2devObjs = [netObj]
|
||||||
|
allendpoints = []
|
||||||
|
myendpoints = getEndpoints(netObj)
|
||||||
|
allendpoints.extend(myendpoints)
|
||||||
|
for ep in myendpoints:
|
||||||
|
if ep.type and ep.net.objid != netObj.objid:
|
||||||
|
l2s, eps = getDowmstreamL2Devices(ep.net)
|
||||||
|
l2devObjs.extend(l2s)
|
||||||
|
allendpoints.extend(eps)
|
||||||
|
|
||||||
|
return l2devObjs, allendpoints
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getAllNetworkInterfaces(session):
|
||||||
|
'''
|
||||||
|
Gather all network interfacecs in the session
|
||||||
|
'''
|
||||||
|
netifs = []
|
||||||
|
for node in session.objs():
|
||||||
|
for netif in node.netifs(sort=True):
|
||||||
|
if netif not in netifs:
|
||||||
|
netifs.append(netif)
|
||||||
|
return netifs
|
||||||
|
|
||||||
|
def inOtherNetwork(netObj):
|
||||||
|
'''
|
||||||
|
Determine if CORE considers a given network object to be part of another network.
|
||||||
|
Note: CORE considers layer 2 devices to be their own networks. However, if a l2 device
|
||||||
|
is connected to another device, it is possible that one of its ports belong to the other
|
||||||
|
l2 device's network (thus, "othernet").
|
||||||
|
'''
|
||||||
|
for netif in netObj.netifs(sort=True):
|
||||||
|
if hasattr(netif,"othernet"):
|
||||||
|
if netif.othernet.objid != netObj.objid:
|
||||||
|
return True
|
||||||
|
return False
|
|
@ -1152,7 +1152,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler):
|
||||||
return self.session.sendobjs()
|
return self.session.sendobjs()
|
||||||
elif eventtype == coreapi.CORE_EVENT_FILE_SAVE:
|
elif eventtype == coreapi.CORE_EVENT_FILE_SAVE:
|
||||||
filename = msg.tlvdata[coreapi.CORE_TLV_EVENT_NAME]
|
filename = msg.tlvdata[coreapi.CORE_TLV_EVENT_NAME]
|
||||||
savesessionxml(self.session, filename)
|
savesessionxml(self.session, filename, self.session.cfg['xmlfilever'])
|
||||||
elif eventtype == coreapi.CORE_EVENT_SCHEDULED:
|
elif eventtype == coreapi.CORE_EVENT_SCHEDULED:
|
||||||
etime = msg.gettlv(coreapi.CORE_TLV_EVENT_TIME)
|
etime = msg.gettlv(coreapi.CORE_TLV_EVENT_TIME)
|
||||||
node = msg.gettlv(coreapi.CORE_TLV_EVENT_NODE)
|
node = msg.gettlv(coreapi.CORE_TLV_EVENT_NODE)
|
||||||
|
@ -1639,6 +1639,7 @@ def getMergedConfig(filename):
|
||||||
'listenaddr' : 'localhost',
|
'listenaddr' : 'localhost',
|
||||||
'pidfile' : '%s/run/core-daemon.pid' % CORE_STATE_DIR,
|
'pidfile' : '%s/run/core-daemon.pid' % CORE_STATE_DIR,
|
||||||
'logfile' : '%s/log/core-daemon.log' % CORE_STATE_DIR,
|
'logfile' : '%s/log/core-daemon.log' % CORE_STATE_DIR,
|
||||||
|
'xmlfilever' : '1.0',
|
||||||
'numthreads' : '1',
|
'numthreads' : '1',
|
||||||
'verbose' : 'False',
|
'verbose' : 'False',
|
||||||
'daemonize' : 'False',
|
'daemonize' : 'False',
|
||||||
|
|
Loading…
Reference in a new issue