initial import (Boeing r1752, NRL r878)
This commit is contained in:
commit
f8f46d28be
394 changed files with 99738 additions and 0 deletions
445
daemon/core/coreobj.py
Normal file
445
daemon/core/coreobj.py
Normal file
|
@ -0,0 +1,445 @@
|
|||
#
|
||||
# CORE
|
||||
# Copyright (c)2010-2013 the Boeing Company.
|
||||
# See the LICENSE file included in this distribution.
|
||||
#
|
||||
# authors: Tom Goff <thomas.goff@boeing.com>
|
||||
# Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
#
|
||||
'''
|
||||
coreobj.py: defines the basic objects for emulation: the PyCoreObj base class,
|
||||
along with PyCoreNode, PyCoreNet, and PyCoreNetIf
|
||||
'''
|
||||
import sys, threading, os, shutil
|
||||
|
||||
from core.api import coreapi
|
||||
from core.misc.ipaddr import *
|
||||
|
||||
class Position(object):
|
||||
''' Helper class for Cartesian coordinate position
|
||||
'''
|
||||
def __init__(self, x = None, y = None, z = None):
|
||||
self.x = None
|
||||
self.y = None
|
||||
self.z = None
|
||||
self.set(x, y, z)
|
||||
|
||||
def set(self, x = None, y = None, z = None):
|
||||
''' Returns True if the position has actually changed.
|
||||
'''
|
||||
if self.x == x and self.y == y and self.z == z:
|
||||
return False
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
return True
|
||||
|
||||
def get(self):
|
||||
''' Fetch the (x,y,z) position tuple.
|
||||
'''
|
||||
return (self.x, self.y, self.z)
|
||||
|
||||
class PyCoreObj(object):
|
||||
''' Base class for pycore objects (nodes and nets)
|
||||
'''
|
||||
apitype = None
|
||||
|
||||
def __init__(self, session, objid = None, name = None, verbose = False,
|
||||
start = True):
|
||||
self.session = session
|
||||
if objid is None:
|
||||
objid = session.getobjid()
|
||||
self.objid = objid
|
||||
if name is None:
|
||||
name = "o%s" % self.objid
|
||||
self.name = name
|
||||
# ifindex is key, PyCoreNetIf instance is value
|
||||
self._netif = {}
|
||||
self.ifindex = 0
|
||||
self.canvas = None
|
||||
self.icon = None
|
||||
self.opaque = None
|
||||
self.verbose = verbose
|
||||
self.position = Position()
|
||||
|
||||
def startup(self):
|
||||
''' Each object implements its own startup method.
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def shutdown(self):
|
||||
''' Each object implements its own shutdown method.
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def setposition(self, x = None, y = None, z = None):
|
||||
''' Set the (x,y,z) position of the object.
|
||||
'''
|
||||
return self.position.set(x = x, y = y, z = z)
|
||||
|
||||
def getposition(self):
|
||||
''' Return an (x,y,z) tuple representing this object's position.
|
||||
'''
|
||||
return self.position.get()
|
||||
|
||||
def ifname(self, ifindex):
|
||||
return self.netif(ifindex).name
|
||||
|
||||
def netifs(self, sort=False):
|
||||
''' Iterate over attached network interfaces.
|
||||
'''
|
||||
if sort:
|
||||
return map(lambda k: self._netif[k], sorted(self._netif.keys()))
|
||||
else:
|
||||
return self._netif.itervalues()
|
||||
|
||||
def numnetif(self):
|
||||
''' Return the attached interface count.
|
||||
'''
|
||||
return len(self._netif)
|
||||
|
||||
def getifindex(self, netif):
|
||||
for ifindex in self._netif:
|
||||
if self._netif[ifindex] is netif:
|
||||
return ifindex
|
||||
return -1
|
||||
|
||||
def newifindex(self):
|
||||
while self.ifindex in self._netif:
|
||||
self.ifindex += 1
|
||||
ifindex = self.ifindex
|
||||
self.ifindex += 1
|
||||
return ifindex
|
||||
|
||||
def tonodemsg(self, flags):
|
||||
''' Build a CORE API Node Message for this object. Both nodes and
|
||||
networks can be represented by a Node Message.
|
||||
'''
|
||||
if self.apitype is None:
|
||||
return None
|
||||
tlvdata = ""
|
||||
(x, y, z) = self.getposition()
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NUMBER,
|
||||
self.objid)
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_TYPE,
|
||||
self.apitype)
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_NAME,
|
||||
self.name)
|
||||
if hasattr(self, "type") and self.type is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_MODEL,
|
||||
self.type)
|
||||
|
||||
if x is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_XPOS, x)
|
||||
if y is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_YPOS, y)
|
||||
if self.canvas is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_CANVAS,
|
||||
self.canvas)
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_EMUID,
|
||||
self.objid)
|
||||
if self.icon is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_ICON,
|
||||
self.icon)
|
||||
if self.opaque is not None:
|
||||
tlvdata += coreapi.CoreNodeTlv.pack(coreapi.CORE_TLV_NODE_OPAQUE,
|
||||
self.opaque)
|
||||
msg = coreapi.CoreNodeMessage.pack(flags, tlvdata)
|
||||
return msg
|
||||
|
||||
def tolinkmsgs(self, flags):
|
||||
''' Build CORE API Link Messages for this object. There is no default
|
||||
method for PyCoreObjs as PyCoreNodes do not implement this but
|
||||
PyCoreNets do.
|
||||
'''
|
||||
return []
|
||||
|
||||
def info(self, msg):
|
||||
''' Utility method for printing informational messages when verbose
|
||||
is turned on.
|
||||
'''
|
||||
if self.verbose:
|
||||
print "%s: %s" % (self.name, msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
def warn(self, msg):
|
||||
''' Utility method for printing warning/error messages
|
||||
'''
|
||||
print >> sys.stderr, "%s: %s" % (self.name, msg)
|
||||
sys.stderr.flush()
|
||||
|
||||
def exception(self, level, source, text):
|
||||
''' Generate an Exception Message for this session, providing this
|
||||
object number.
|
||||
'''
|
||||
if self.session:
|
||||
id = None
|
||||
if isinstance(self.objid, int):
|
||||
id = self.objid
|
||||
elif isinstance(self.objid, str) and self.objid.isdigit():
|
||||
id = int(self.objid)
|
||||
self.session.exception(level, source, id, text)
|
||||
|
||||
|
||||
class PyCoreNode(PyCoreObj):
|
||||
''' Base class for nodes
|
||||
'''
|
||||
def __init__(self, session, objid = None, name = None, verbose = False,
|
||||
start = True):
|
||||
''' Initialization for node objects.
|
||||
'''
|
||||
PyCoreObj.__init__(self, session, objid, name, verbose=verbose,
|
||||
start=start)
|
||||
self.services = []
|
||||
self.type = None
|
||||
self.nodedir = None
|
||||
|
||||
def nodeid(self):
|
||||
return self.objid
|
||||
|
||||
def addservice(self, service):
|
||||
if service is not None:
|
||||
self.services.append(service)
|
||||
|
||||
def makenodedir(self):
|
||||
if self.nodedir is None:
|
||||
self.nodedir = \
|
||||
os.path.join(self.session.sessiondir, self.name + ".conf")
|
||||
os.makedirs(self.nodedir)
|
||||
self.tmpnodedir = True
|
||||
else:
|
||||
self.tmpnodedir = False
|
||||
|
||||
def rmnodedir(self):
|
||||
if hasattr(self.session.options, 'preservedir'):
|
||||
if self.session.options.preservedir == '1':
|
||||
return
|
||||
if self.tmpnodedir:
|
||||
shutil.rmtree(self.nodedir, ignore_errors = True)
|
||||
|
||||
def addnetif(self, netif, ifindex):
|
||||
if ifindex in self._netif:
|
||||
raise ValueError, "ifindex %s already exists" % ifindex
|
||||
self._netif[ifindex] = netif
|
||||
|
||||
def delnetif(self, ifindex):
|
||||
if ifindex not in self._netif:
|
||||
raise ValueError, "ifindex %s does not exist" % ifindex
|
||||
netif = self._netif.pop(ifindex)
|
||||
netif.shutdown()
|
||||
del netif
|
||||
|
||||
def netif(self, ifindex, net = None):
|
||||
if ifindex in self._netif:
|
||||
return self._netif[ifindex]
|
||||
else:
|
||||
return None
|
||||
|
||||
def attachnet(self, ifindex, net):
|
||||
if ifindex not in self._netif:
|
||||
raise ValueError, "ifindex %s does not exist" % ifindex
|
||||
self._netif[ifindex].attachnet(net)
|
||||
|
||||
def detachnet(self, ifindex):
|
||||
if ifindex not in self._netif:
|
||||
raise ValueError, "ifindex %s does not exist" % ifindex
|
||||
self._netif[ifindex].detachnet()
|
||||
|
||||
def setposition(self, x = None, y = None, z = None):
|
||||
changed = PyCoreObj.setposition(self, x = x, y = y, z = z)
|
||||
if not changed:
|
||||
# save extra interface range calculations
|
||||
return
|
||||
for netif in self.netifs(sort=True):
|
||||
netif.setposition(x, y, z)
|
||||
|
||||
def commonnets(self, obj, want_ctrl=False):
|
||||
''' Given another node or net object, return common networks between
|
||||
this node and that object. A list of tuples is returned, with each tuple
|
||||
consisting of (network, interface1, interface2).
|
||||
'''
|
||||
r = []
|
||||
for netif1 in self.netifs():
|
||||
if not want_ctrl and hasattr(netif1, 'control'):
|
||||
continue
|
||||
for netif2 in obj.netifs():
|
||||
if netif1.net == netif2.net:
|
||||
r += (netif1.net, netif1, netif2),
|
||||
return r
|
||||
|
||||
|
||||
|
||||
class PyCoreNet(PyCoreObj):
|
||||
''' Base class for networks
|
||||
'''
|
||||
linktype = coreapi.CORE_LINK_WIRED
|
||||
|
||||
def __init__(self, session, objid, name, verbose = False, start = True):
|
||||
''' Initialization for network objects.
|
||||
'''
|
||||
PyCoreObj.__init__(self, session, objid, name, verbose=verbose,
|
||||
start=start)
|
||||
self._linked = {}
|
||||
self._linked_lock = threading.Lock()
|
||||
|
||||
def attach(self, netif):
|
||||
i = self.newifindex()
|
||||
self._netif[i] = netif
|
||||
netif.netifi = i
|
||||
with self._linked_lock:
|
||||
self._linked[netif] = {}
|
||||
|
||||
def detach(self, netif):
|
||||
del self._netif[netif.netifi]
|
||||
netif.netifi = None
|
||||
with self._linked_lock:
|
||||
del self._linked[netif]
|
||||
|
||||
def tolinkmsgs(self, flags):
|
||||
''' Build CORE API Link Messages for this network. Each link message
|
||||
describes a link between this network and a node.
|
||||
'''
|
||||
msgs = []
|
||||
# build a link message from this network node to each node having a
|
||||
# connected interface
|
||||
for netif in self.netifs(sort=True):
|
||||
if not hasattr(netif, "node"):
|
||||
continue
|
||||
otherobj = netif.node
|
||||
if otherobj is None:
|
||||
# two layer-2 switches/hubs linked together via linknet()
|
||||
if not hasattr(netif, "othernet"):
|
||||
continue
|
||||
otherobj = netif.othernet
|
||||
if otherobj.objid == self.objid:
|
||||
continue
|
||||
|
||||
tlvdata = ""
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N1NUMBER,
|
||||
self.objid)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
|
||||
otherobj.objid)
|
||||
delay = netif.getparam('delay')
|
||||
bw = netif.getparam('bw')
|
||||
loss = netif.getparam('loss')
|
||||
duplicate = netif.getparam('duplicate')
|
||||
jitter = netif.getparam('jitter')
|
||||
if delay is not None:
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DELAY,
|
||||
delay)
|
||||
if bw is not None:
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_BW,
|
||||
bw)
|
||||
if loss is not None:
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_PER,
|
||||
str(loss))
|
||||
if duplicate is not None:
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DUP,
|
||||
str(duplicate))
|
||||
if jitter is not None:
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_JITTER,
|
||||
jitter)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_TYPE,
|
||||
self.linktype)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM,
|
||||
otherobj.getifindex(netif))
|
||||
for addr in netif.addrlist:
|
||||
(ip, sep, mask) = addr.partition('/')
|
||||
mask = int(mask)
|
||||
if isIPv4Address(ip):
|
||||
family = AF_INET
|
||||
tlvtypeip = coreapi.CORE_TLV_LINK_IF2IP4
|
||||
tlvtypemask = coreapi.CORE_TLV_LINK_IF2IP4MASK
|
||||
else:
|
||||
family = AF_INET6
|
||||
tlvtypeip = coreapi.CORE_TLV_LINK_IF2IP6
|
||||
tlvtypemask = coreapi.CORE_TLV_LINK_IF2IP6MASK
|
||||
ipl = socket.inet_pton(family, ip)
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, \
|
||||
IPAddr(af=family, addr=ipl))
|
||||
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
|
||||
|
||||
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
|
||||
msgs.append(msg)
|
||||
return msgs
|
||||
|
||||
class PyCoreNetIf(object):
|
||||
''' Base class for interfaces.
|
||||
'''
|
||||
def __init__(self, node, name, mtu):
|
||||
self.node = node
|
||||
self.name = name
|
||||
if not isinstance(mtu, (int, long)):
|
||||
raise ValueError
|
||||
self.mtu = mtu
|
||||
self.net = None
|
||||
self._params = {}
|
||||
self.addrlist = []
|
||||
self.hwaddr = None
|
||||
self.poshook = None
|
||||
# used with EMANE
|
||||
self.transport_type = None
|
||||
# interface index on the network
|
||||
self.netindex = None
|
||||
|
||||
def startup(self):
|
||||
pass
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def attachnet(self, net):
|
||||
if self.net:
|
||||
self.detachnet()
|
||||
self.net = None
|
||||
net.attach(self)
|
||||
self.net = net
|
||||
|
||||
def detachnet(self):
|
||||
if self.net is not None:
|
||||
self.net.detach(self)
|
||||
|
||||
def addaddr(self, addr):
|
||||
self.addrlist.append(addr)
|
||||
|
||||
def deladdr(self, addr):
|
||||
self.addrlist.remove(addr)
|
||||
|
||||
def sethwaddr(self, addr):
|
||||
self.hwaddr = addr
|
||||
|
||||
def getparam(self, key):
|
||||
''' Retrieve a parameter from the _params dict,
|
||||
or None if the parameter does not exist.
|
||||
'''
|
||||
if key not in self._params:
|
||||
return None
|
||||
return self._params[key]
|
||||
|
||||
def getparams(self):
|
||||
''' Return (key, value) pairs from the _params dict.
|
||||
'''
|
||||
r = []
|
||||
for k in sorted(self._params.keys()):
|
||||
r.append((k, self._params[k]))
|
||||
return r
|
||||
|
||||
def setparam(self, key, value):
|
||||
''' Set a parameter in the _params dict.
|
||||
Returns True if the parameter has changed.
|
||||
'''
|
||||
if key in self._params:
|
||||
if self._params[key] == value:
|
||||
return False
|
||||
elif self._params[key] <= 0 and value <= 0:
|
||||
# treat None and 0 as unchanged values
|
||||
return False
|
||||
self._params[key] = value
|
||||
return True
|
||||
|
||||
def setposition(self, x, y, z):
|
||||
''' Dispatch to any position hook (self.poshook) handler.
|
||||
'''
|
||||
if self.poshook is not None:
|
||||
self.poshook(self, x, y, z)
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue