initial commit after bringing over cleaned up code and testing some examples

This commit is contained in:
Blake J. Harnden 2017-04-25 08:45:34 -07:00
parent c4858e6e0d
commit 00f4ebf5a9
93 changed files with 15189 additions and 13083 deletions

View file

@ -3,63 +3,71 @@
# Copyright (c)2010-2012 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# authors: core-dev@pf.itd.nrl.navy.mil
# authors: core-dev@pf.itd.nrl.navy.mil
#
'''
"""
netgraph.py: Netgraph helper functions; for now these are wrappers around
ngctl commands.
'''
"""
import subprocess
from core.misc.utils import *
from core.constants import *
checkexec([NGCTL_BIN])
from core import constants
from core.misc import utils
utils.checkexec([constants.NGCTL_BIN])
def createngnode(type, hookstr, name=None):
''' Create a new Netgraph node of type and optionally assign name. The
hook string hookstr should contain two names. This is a string so
other commands may be inserted after the two names.
Return the name and netgraph ID of the new node.
'''
"""
Create a new Netgraph node of type and optionally assign name. The
hook string hookstr should contain two names. This is a string so
other commands may be inserted after the two names.
Return the name and netgraph ID of the new node.
"""
hook1 = hookstr.split()[0]
ngcmd = "mkpeer %s %s \n show .%s" % (type, hookstr, hook1)
cmd = [NGCTL_BIN, "-f", "-"]
cmdid = subprocess.Popen(cmd, stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.STDOUT)
result, err = cmdid.communicate(input = ngcmd) # err will always be None
cmd = [constants.NGCTL_BIN, "-f", "-"]
cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
# err will always be None
result, err = cmdid.communicate(input=ngcmd)
status = cmdid.wait()
if status > 0:
raise Exception, "error creating Netgraph node %s (%s): %s" % \
(type, ngcmd, result)
raise Exception("error creating Netgraph node %s (%s): %s" % (type, ngcmd, result))
results = result.split()
ngname = results[1]
ngid = results[5]
if name:
check_call([NGCTL_BIN, "name", "[0x%s]:" % ngid, name])
return (ngname, ngid)
utils.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name])
return ngname, ngid
def destroyngnode(name):
''' Shutdown a Netgraph node having the given name.
'''
check_call([NGCTL_BIN, "shutdown", "%s:" % name])
""" Shutdown a Netgraph node having the given name.
"""
utils.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name])
def connectngnodes(name1, name2, hook1, hook2):
''' Connect two hooks of two Netgraph nodes given by their names.
'''
""" Connect two hooks of two Netgraph nodes given by their names.
"""
node1 = "%s:" % name1
node2 = "%s:" % name2
check_call([NGCTL_BIN, "connect", node1, node2, hook1, hook2])
utils.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2])
def ngmessage(name, msg):
''' Send a Netgraph message to the node named name.
'''
cmd = [NGCTL_BIN, "msg", "%s:" % name] + msg
check_call(cmd)
""" Send a Netgraph message to the node named name.
"""
cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg
utils.check_call(cmd)
def ngloadkernelmodule(name):
''' Load a kernel module by invoking kldstat. This is needed for the
""" Load a kernel module by invoking kldstat. This is needed for the
ng_ether module which automatically creates Netgraph nodes when loaded.
'''
mutecall(["kldload", name])
"""
utils.mutecall(["kldload", name])

View file

@ -6,172 +6,173 @@
# author: core-dev@pf.itd.nrl.navy.mil
#
'''
"""
nodes.py: definition of CoreNode classes and other node classes that inherit
from the CoreNode, implementing specific node types.
'''
"""
from vnode import *
from vnet import *
from core.constants import *
from core.misc.ipaddr import *
import socket
from core import constants
from core.api import coreapi
from core.bsd.netgraph import connectngnodes
from core.bsd.netgraph import ngloadkernelmodule
from core.bsd.vnet import NetgraphNet
from core.bsd.vnet import NetgraphPipeNet
from core.bsd.vnode import JailNode
from core.enumerations import LinkTlvs
from core.enumerations import LinkTypes
from core.enumerations import NodeTypes
from core.enumerations import RegisterTlvs
from core.misc import ipaddress
from core.misc import utils
utils.checkexec([constants.IFCONFIG_BIN])
checkexec([IFCONFIG_BIN])
class CoreNode(JailNode):
apitype = coreapi.CORE_NODE_DEF
apitype = NodeTypes.DEFAULT.value
class PtpNet(NetgraphPipeNet):
def tonodemsg(self, flags):
''' Do not generate a Node Message for point-to-point links. They are
""" Do not generate a Node Message for point-to-point links. They are
built using a link message instead.
'''
"""
pass
def tolinkmsgs(self, flags):
''' Build CORE API TLVs for a point-to-point link. One Link message
""" Build CORE API TLVs for a point-to-point link. One Link message
describes this network.
'''
"""
tlvdata = ""
if len(self._netif) != 2:
return tlvdata
(if1, if2) = self._netif.items()
if1 = if1[1]
if2 = if2[1]
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N1NUMBER,
if1.node.objid)
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_N2NUMBER,
if2.node.objid)
delay = if1.getparam('delay')
bw = if1.getparam('bw')
loss = if1.getparam('loss')
duplicate = if1.getparam('duplicate')
jitter = if1.getparam('jitter')
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, if1.node.objid)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, if2.node.objid)
delay = if1.getparam("delay")
bw = if1.getparam("bw")
loss = if1.getparam("loss")
duplicate = if1.getparam("duplicate")
jitter = if1.getparam("jitter")
if delay is not None:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DELAY,
delay)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DELAY.value, delay)
if bw is not None:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_BW, bw)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.BANDWIDTH.value, bw)
if loss is not None:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_PER,
str(loss))
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.PER.value, str(loss))
if duplicate is not None:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_DUP,
str(duplicate))
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DUP.value, 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(LinkTlvs.JITTER.value, jitter)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, self.linktype)
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1NUM, \
if1.node.getifindex(if1))
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_NUMBER.value, if1.node.getifindex(if1))
if if1.hwaddr:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF1MAC,
if1.hwaddr)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr)
for addr in if1.addrlist:
(ip, sep, mask) = addr.partition('/')
(ip, sep, mask) = addr.partition("/")
mask = int(mask)
if isIPv4Address(ip):
family = AF_INET
tlvtypeip = coreapi.CORE_TLV_LINK_IF1IP4
tlvtypemask = coreapi.CORE_TLV_LINK_IF1IP4MASK
if ipaddress.is_ipv4_address(ip):
family = socket.AF_INET
tlvtypeip = LinkTlvs.INTERFACE1_IP4.value
tlvtypemask = LinkTlvs.INTERFACE1_IP4_MASK
else:
family = AF_INET6
tlvtypeip = coreapi.CORE_TLV_LINK_IF1IP6
tlvtypemask = coreapi.CORE_TLV_LINK_IF1IP6MASK
family = socket.AF_INET6
tlvtypeip = LinkTlvs.INTERFACE1_IP6.value
tlvtypemask = LinkTlvs.INTERFACE1_IP6_MASK.value
ipl = socket.inet_pton(family, ip)
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip,
IPAddr(af=family, addr=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2NUM, \
if2.node.getifindex(if2))
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, if2.node.getifindex(if2))
if if2.hwaddr:
tlvdata += coreapi.CoreLinkTlv.pack(coreapi.CORE_TLV_LINK_IF2MAC,
if2.hwaddr)
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr)
for addr in if2.addrlist:
(ip, sep, mask) = addr.partition('/')
(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
if ipaddress.is_ipv4_address(ip):
family = socket.AF_INET
tlvtypeip = LinkTlvs.INTERFACE2_IP4.value
tlvtypemask = LinkTlvs.INTERFACE2_IP4_MASK
else:
family = AF_INET6
tlvtypeip = coreapi.CORE_TLV_LINK_IF2IP6
tlvtypemask = coreapi.CORE_TLV_LINK_IF2IP6MASK
family = socket.AF_INET6
tlvtypeip = LinkTlvs.INTERFACE2_IP6.value
tlvtypemask = LinkTlvs.INTERFACE2_IP6_MASK.value
ipl = socket.inet_pton(family, ip)
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip,
IPAddr(af=family, addr=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl))
tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask)
msg = coreapi.CoreLinkMessage.pack(flags, tlvdata)
return [msg,]
return [msg, ]
class SwitchNode(NetgraphNet):
ngtype = "bridge"
nghooks = "link0 link0\nmsg .link0 setpersistent"
apitype = coreapi.CORE_NODE_SWITCH
apitype = NodeTypes.SWITCH.value
policy = "ACCEPT"
class HubNode(NetgraphNet):
ngtype = "hub"
nghooks = "link0 link0\nmsg .link0 setpersistent"
apitype = coreapi.CORE_NODE_HUB
apitype = NodeTypes.HUB.value
policy = "ACCEPT"
class WlanNode(NetgraphNet):
ngtype = "wlan"
nghooks = "anchor anchor"
apitype = coreapi.CORE_NODE_WLAN
linktype = coreapi.CORE_LINK_WIRELESS
apitype = NodeTypes.WIRELESS_LAN.value
linktype = LinkTypes.WIRELESS.value
policy = "DROP"
def __init__(self, session, objid = None, name = None, verbose = False,
start = True, policy = None):
def __init__(self, session, objid=None, name=None, verbose=False,
start=True, policy=None):
NetgraphNet.__init__(self, session, objid, name, verbose, start, policy)
# wireless model such as basic range
self.model = None
# mobility model such as scripted
self.mobility = None
def attach(self, netif):
NetgraphNet.attach(self, netif)
if self.model:
netif.poshook = self.model._positioncallback
if netif.node is None:
return
(x,y,z) = netif.node.position.get()
x, y, z = netif.node.position.get()
netif.poshook(netif, x, y, z)
def setmodel(self, model, config):
''' Mobility and wireless model.
'''
if (self.verbose):
""" Mobility and wireless model.
"""
if self.verbose:
self.info("adding model %s" % model._name)
if model._type == coreapi.CORE_TLV_REG_WIRELESS:
if model._type == RegisterTlvs.WIRELESS.value:
self.model = model(session=self.session, objid=self.objid,
verbose=self.verbose, values=config)
if self.model._positioncallback:
for netif in self.netifs():
netif.poshook = self.model._positioncallback
if netif.node is not None:
(x,y,z) = netif.node.position.get()
(x, y, z) = netif.node.position.get()
netif.poshook(netif, x, y, z)
self.model.setlinkparams()
elif model._type == coreapi.CORE_TLV_REG_MOBILITY:
elif model._type == RegisterTlvs.MOBILITY.value:
self.mobility = model(session=self.session, objid=self.objid,
verbose=self.verbose, values=config)
class RJ45Node(NetgraphPipeNet):
apitype = coreapi.CORE_NODE_RJ45
apitype = NodeTypes.RJ45.value
policy = "ACCEPT"
def __init__(self, session, objid, name, verbose, start = True):
def __init__(self, session, objid, name, verbose, start=True):
if start:
ngloadkernelmodule("ng_ether")
NetgraphPipeNet.__init__(self, session, objid, name, verbose, start)
@ -186,18 +187,18 @@ class RJ45Node(NetgraphPipeNet):
p = "promisc"
if not promisc:
p = "-" + p
check_call([IFCONFIG_BIN, self.name, "up", p])
utils.check_call([constants.IFCONFIG_BIN, self.name, "up", p])
def attach(self, netif):
if len(self._netif) > 0:
raise ValueError, \
"RJ45 networks support at most 1 network interface"
"RJ45 networks support at most 1 network interface"
NetgraphPipeNet.attach(self, netif)
connectngnodes(self.ngname, self.name, self.gethook(), "lower")
class TunnelNode(NetgraphNet):
ngtype = "pipe"
nghooks = "upper lower"
apitype = coreapi.CORE_NODE_TUNNEL
apitype = NodeTypes.TUNNEL.value
policy = "ACCEPT"

View file

@ -5,25 +5,25 @@
#
# authors: core-dev@pf.itd.nrl.navy.mil
#
'''
"""
vnet.py: NetgraphNet and NetgraphPipeNet classes that implement virtual networks
using the FreeBSD Netgraph subsystem.
'''
"""
import sys, threading
from core.bsd.netgraph import connectngnodes
from core.bsd.netgraph import createngnode
from core.bsd.netgraph import destroyngnode
from core.bsd.netgraph import ngmessage
from core.coreobj import PyCoreNet
from core.misc.utils import *
from core.constants import *
from core.coreobj import PyCoreNet, PyCoreObj
from core.bsd.netgraph import *
from core.bsd.vnode import VEth
class NetgraphNet(PyCoreNet):
ngtype = None
nghooks = ()
def __init__(self, session, objid = None, name = None, verbose = False,
start = True, policy = None):
def __init__(self, session, objid=None, name=None, verbose=False,
start=True, policy=None):
PyCoreNet.__init__(self, session, objid, name)
if name is None:
name = str(self.objid)
@ -40,8 +40,7 @@ class NetgraphNet(PyCoreNet):
self.startup()
def startup(self):
tmp, self.ngid = createngnode(type=self.ngtype, hookstr=self.nghooks,
name=self.ngname)
tmp, self.ngid = createngnode(type=self.ngtype, hookstr=self.nghooks, name=self.ngname)
self.up = True
def shutdown(self):
@ -62,13 +61,12 @@ class NetgraphNet(PyCoreNet):
destroyngnode(self.ngname)
def attach(self, netif):
''' Attach an interface to this netgraph node. Create a pipe between
""" Attach an interface to this netgraph node. Create a pipe between
the interface and the hub/switch/wlan node.
(Note that the PtpNet subclass overrides this method.)
'''
"""
if self.up:
pipe = self.session.addobj(cls = NetgraphPipeNet,
verbose = self.verbose, start = True)
pipe = self.session.addobj(cls=NetgraphPipeNet, verbose=self.verbose, start=True)
pipe.attach(netif)
hook = "link%d" % len(self._netif)
pipe.attachnet(self, hook)
@ -82,14 +80,16 @@ class NetgraphNet(PyCoreNet):
def linked(self, netif1, netif2):
# check if the network interfaces are attached to this network
if self._netif[netif1] != netif1:
raise ValueError, "inconsistency for netif %s" % netif1.name
raise ValueError("inconsistency for netif %s" % netif1.name)
if self._netif[netif2] != netif2:
raise ValueError, "inconsistency for netif %s" % netif2.name
raise ValueError("inconsistency for netif %s" % netif2.name)
try:
linked = self._linked[netif1][netif2]
except KeyError:
linked = False
self._linked[netif1][netif2] = linked
return linked
def unlink(self, netif1, netif2):
@ -109,108 +109,106 @@ class NetgraphNet(PyCoreNet):
self._linked[netif1][netif2] = True
def linknet(self, net):
''' Link this bridge with another by creating a veth pair and installing
""" Link this bridge with another by creating a veth pair and installing
each device into each bridge.
'''
"""
raise NotImplementedError
def linkconfig(self, netif, bw = None, delay = None,
loss = None, duplicate = None, jitter = None, netif2=None):
''' Set link effects by modifying the pipe connected to an interface.
'''
def linkconfig(self, netif, bw=None, delay=None,
loss=None, duplicate=None, jitter=None, netif2=None):
""" Set link effects by modifying the pipe connected to an interface.
"""
if not netif.pipe:
self.warn("linkconfig for %s but interface %s has no pipe" % \
(self.name, netif.name))
self.warn("linkconfig for %s but interface %s has no pipe" % (self.name, netif.name))
return
return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter,
netif2)
return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2)
class NetgraphPipeNet(NetgraphNet):
ngtype = "pipe"
nghooks = "upper lower"
def __init__(self, session, objid = None, name = None, verbose = False,
start = True, policy = None):
def __init__(self, session, objid=None, name=None, verbose=False,
start=True, policy=None):
NetgraphNet.__init__(self, session, objid, name, verbose, start, policy)
if start:
# account for Ethernet header
ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"])
def attach(self, netif):
''' Attach an interface to this pipe node.
""" Attach an interface to this pipe node.
The first interface is connected to the "upper" hook, the second
connected to the "lower" hook.
'''
"""
if len(self._netif) > 1:
raise ValueError, \
"Netgraph pipes support at most 2 network interfaces"
"Netgraph pipes support at most 2 network interfaces"
if self.up:
hook = self.gethook()
connectngnodes(self.ngname, netif.localname, hook, netif.hook)
if netif.pipe:
raise ValueError, \
"Interface %s already attached to pipe %s" % \
(netif.name, netif.pipe.name)
"Interface %s already attached to pipe %s" % \
(netif.name, netif.pipe.name)
netif.pipe = self
self._netif[netif] = netif
self._linked[netif] = {}
def attachnet(self, net, hook):
''' Attach another NetgraphNet to this pipe node.
'''
""" Attach another NetgraphNet to this pipe node.
"""
localhook = self.gethook()
connectngnodes(self.ngname, net.ngname, localhook, hook)
def gethook(self):
''' Returns the first hook (e.g. "upper") then the second hook
""" Returns the first hook (e.g. "upper") then the second hook
(e.g. "lower") based on the number of connections.
'''
"""
hooks = self.nghooks.split()
if len(self._netif) == 0:
return hooks[0]
else:
return hooks[1]
def linkconfig(self, netif, bw = None, delay = None,
loss = None, duplicate = None, jitter = None, netif2 = None):
''' Set link effects by sending a Netgraph setcfg message to the pipe.
'''
netif.setparam('bw', bw)
netif.setparam('delay', delay)
netif.setparam('loss', loss)
netif.setparam('duplicate', duplicate)
netif.setparam('jitter', jitter)
def linkconfig(self, netif, bw=None, delay=None,
loss=None, duplicate=None, jitter=None, netif2=None):
""" Set link effects by sending a Netgraph setcfg message to the pipe.
"""
netif.setparam("bw", bw)
netif.setparam("delay", delay)
netif.setparam("loss", loss)
netif.setparam("duplicate", duplicate)
netif.setparam("jitter", jitter)
if not self.up:
return
params = []
upstream = []
downstream = []
if bw is not None:
if str(bw)=="0":
bw="-1"
params += ["bandwidth=%s" % bw,]
if str(bw) == "0":
bw = "-1"
params += ["bandwidth=%s" % bw, ]
if delay is not None:
if str(delay)=="0":
delay="-1"
params += ["delay=%s" % delay,]
if str(delay) == "0":
delay = "-1"
params += ["delay=%s" % delay, ]
if loss is not None:
if str(loss)=="0":
loss="-1"
upstream += ["BER=%s" % loss,]
downstream += ["BER=%s" % loss,]
if str(loss) == "0":
loss = "-1"
upstream += ["BER=%s" % loss, ]
downstream += ["BER=%s" % loss, ]
if duplicate is not None:
if str(duplicate)=="0":
duplicate="-1"
upstream += ["duplicate=%s" % duplicate,]
downstream += ["duplicate=%s" % duplicate,]
if str(duplicate) == "0":
duplicate = "-1"
upstream += ["duplicate=%s" % duplicate, ]
downstream += ["duplicate=%s" % duplicate, ]
if jitter:
self.warn("jitter parameter ignored for link %s" % self.name)
if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0:
setcfg = ["setcfg", "{",] + params
setcfg = ["setcfg", "{", ] + params
if len(upstream) > 0:
setcfg += ["upstream={",] + upstream + ["}",]
setcfg += ["upstream={", ] + upstream + ["}", ]
if len(downstream) > 0:
setcfg += ["downstream={",] + downstream + ["}",]
setcfg += ["}",]
setcfg += ["downstream={", ] + downstream + ["}", ]
setcfg += ["}", ]
ngmessage(self.ngname, setcfg)

View file

@ -3,27 +3,32 @@
# Copyright (c)2010-2012 the Boeing Company.
# See the LICENSE file included in this distribution.
#
# authors: core-dev@pf.itd.nrl.navy.mil
# authors: core-dev@pf.itd.nrl.navy.mil
#
'''
"""
vnode.py: SimpleJailNode and JailNode classes that implement the FreeBSD
jail-based virtual node.
'''
"""
import os, signal, sys, subprocess, threading, string
import random, time
from core.misc.utils import *
from core.constants import *
from core.coreobj import PyCoreObj, PyCoreNode, PyCoreNetIf, Position
from core.emane.nodes import EmaneNode
from core.bsd.netgraph import *
import os
import subprocess
import threading
from core import constants
from core.bsd.netgraph import createngnode
from core.bsd.netgraph import destroyngnode
from core.coreobj import PyCoreNetIf
from core.coreobj import PyCoreNode
from core.misc import utils
utils.checkexec([constants.IFCONFIG_BIN, constants.VIMAGE_BIN])
checkexec([IFCONFIG_BIN, VIMAGE_BIN])
class VEth(PyCoreNetIf):
def __init__(self, node, name, localname, mtu = 1500, net = None,
start = True):
PyCoreNetIf.__init__(self, node = node, name = name, mtu = mtu)
def __init__(self, node, name, localname, mtu=1500, net=None,
start=True):
PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu)
# name is the device name (e.g. ngeth0, ngeth1, etc.) before it is
# installed in a node; the Netgraph name is renamed to localname
# e.g. before install: name = ngeth0 localname = n0_0_123
@ -45,7 +50,7 @@ class VEth(PyCoreNetIf):
name=self.localname)
self.name = ngname
self.ngid = ngid
check_call([IFCONFIG_BIN, ngname, "up"])
utils.check_call([constants.IFCONFIG_BIN, ngname, "up"])
self.up = True
def shutdown(self):
@ -74,15 +79,18 @@ class VEth(PyCoreNetIf):
def sethwaddr(self, addr):
self.hwaddr = addr
class TunTap(PyCoreNetIf):
'''TUN/TAP virtual device in TAP mode'''
def __init__(self, node, name, localname, mtu = None, net = None,
start = True):
"""TUN/TAP virtual device in TAP mode"""
def __init__(self, node, name, localname, mtu=None, net=None,
start=True):
raise NotImplementedError
class SimpleJailNode(PyCoreNode):
def __init__(self, session, objid = None, name = None, nodedir = None,
verbose = False):
def __init__(self, session, objid=None, name=None, nodedir=None,
verbose=False):
PyCoreNode.__init__(self, session, objid, name)
self.nodedir = nodedir
self.verbose = verbose
@ -94,17 +102,17 @@ class SimpleJailNode(PyCoreNode):
def startup(self):
if self.up:
raise Exception, "already up"
vimg = [VIMAGE_BIN, "-c", self.name]
vimg = [constants.VIMAGE_BIN, "-c", self.name]
try:
os.spawnlp(os.P_WAIT, VIMAGE_BIN, *vimg)
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
except OSError:
raise Exception, ("vimage command not found while running: %s" % \
vimg)
vimg)
self.info("bringing up loopback interface")
self.cmd([IFCONFIG_BIN, "lo0", "127.0.0.1"])
self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"])
self.info("setting hostname: %s" % self.name)
self.cmd(["hostname", self.name])
self.cmd([SYSCTL_BIN, "vfs.morphing_symlinks=1"])
self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"])
self.up = True
def shutdown(self):
@ -114,27 +122,26 @@ class SimpleJailNode(PyCoreNode):
netif.shutdown()
self._netif.clear()
del self.session
vimg = [VIMAGE_BIN, "-d", self.name]
vimg = [constants.VIMAGE_BIN, "-d", self.name]
try:
os.spawnlp(os.P_WAIT, VIMAGE_BIN, *vimg)
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
except OSError:
raise Exception, ("vimage command not found while running: %s" % \
vimg)
raise Exception("vimage command not found while running: %s" % vimg)
self.up = False
def cmd(self, args, wait = True):
def cmd(self, args, wait=True):
if wait:
mode = os.P_WAIT
else:
mode = os.P_NOWAIT
tmp = call([VIMAGE_BIN, self.name] + args, cwd=self.nodedir)
tmp = utils.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir)
if not wait:
tmp = None
if tmp:
self.warn("cmd exited with status %s: %s" % (tmp, str(args)))
return tmp
def cmdresult(self, args, wait = True):
def cmdresult(self, args, wait=True):
cmdid, cmdin, cmdout, cmderr = self.popen(args)
result = cmdout.read()
result += cmderr.read()
@ -145,30 +152,30 @@ class SimpleJailNode(PyCoreNode):
status = cmdid.wait()
else:
status = 0
return (status, result)
return status, result
def popen(self, args):
cmd = [VIMAGE_BIN, self.name]
cmd = [constants.VIMAGE_BIN, self.name]
cmd.extend(args)
tmp = subprocess.Popen(cmd, stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE, cwd=self.nodedir)
tmp = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, cwd=self.nodedir)
return tmp, tmp.stdin, tmp.stdout, tmp.stderr
def icmd(self, args):
return os.spawnlp(os.P_WAIT, VIMAGE_BIN, VIMAGE_BIN, self.name, *args)
return os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, constants.VIMAGE_BIN, self.name, *args)
def term(self, sh = "/bin/sh"):
return os.spawnlp(os.P_WAIT, "xterm", "xterm", "-ut",
"-title", self.name, "-e", VIMAGE_BIN, self.name, sh)
def term(self, sh="/bin/sh"):
return os.spawnlp(os.P_WAIT, "xterm", "xterm", "-ut",
"-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh)
def termcmdstring(self, sh = "/bin/sh"):
''' We add 'sudo' to the command string because the GUI runs as a
def termcmdstring(self, sh="/bin/sh"):
""" We add "sudo" to the command string because the GUI runs as a
normal user.
'''
return "cd %s && sudo %s %s %s" % (self.nodedir, VIMAGE_BIN, self.name, sh)
"""
return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh)
def shcmd(self, cmdstr, sh = "/bin/sh"):
def shcmd(self, cmdstr, sh="/bin/sh"):
return self.cmd([sh, "-c", cmdstr])
def boot(self):
@ -180,9 +187,9 @@ class SimpleJailNode(PyCoreNode):
self.addsymlink(path=target, file=None)
def umount(self, target):
self.info("unmounting '%s'" % target)
self.info("unmounting %s" % target)
def newveth(self, ifindex = None, ifname = None, net = None):
def newveth(self, ifindex=None, ifname=None, net=None):
self.lock.acquire()
try:
if ifindex is None:
@ -191,15 +198,17 @@ class SimpleJailNode(PyCoreNode):
ifname = "eth%d" % ifindex
sessionid = self.session.shortsessionid()
name = "n%s_%s_%s" % (self.objid, ifindex, sessionid)
localname = name
localname = name
ifclass = VEth
veth = ifclass(node = self, name = name, localname = localname,
mtu = 1500, net = net, start = self.up)
veth = ifclass(node=self, name=name, localname=localname,
mtu=1500, net=net, start=self.up)
if self.up:
# install into jail
check_call([IFCONFIG_BIN, veth.name, "vnet", self.name])
utils.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name])
# rename from "ngeth0" to "eth0"
self.cmd([IFCONFIG_BIN, veth.name, "name", ifname])
self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname])
veth.name = ifname
try:
self.addnetif(veth, ifindex)
@ -214,17 +223,17 @@ class SimpleJailNode(PyCoreNode):
def sethwaddr(self, ifindex, addr):
self._netif[ifindex].sethwaddr(addr)
if self.up:
self.cmd([IFCONFIG_BIN, self.ifname(ifindex), "link",
str(addr)])
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link",
str(addr)])
def addaddr(self, ifindex, addr):
if self.up:
if ':' in addr:
if ":" in addr:
family = "inet6"
else:
family = "inet"
self.cmd([IFCONFIG_BIN, self.ifname(ifindex), family, "alias",
str(addr)])
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias",
str(addr)])
self._netif[ifindex].addaddr(addr)
def deladdr(self, ifindex, addr):
@ -233,40 +242,40 @@ class SimpleJailNode(PyCoreNode):
except ValueError:
self.warn("trying to delete unknown address: %s" % addr)
if self.up:
if ':' in addr:
if ":" in addr:
family = "inet6"
else:
family = "inet"
self.cmd([IFCONFIG_BIN, self.ifname(ifindex), family, "-alias",
str(addr)])
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "-alias",
str(addr)])
valid_deladdrtype = ("inet", "inet6", "inet6link")
def delalladdr(self, ifindex, addrtypes = valid_deladdrtype):
addr = self.getaddr(self.ifname(ifindex), rescan = True)
def delalladdr(self, ifindex, addrtypes=valid_deladdrtype):
addr = self.getaddr(self.ifname(ifindex), rescan=True)
for t in addrtypes:
if t not in self.valid_deladdrtype:
raise ValueError, "addr type must be in: " + \
" ".join(self.valid_deladdrtype)
" ".join(self.valid_deladdrtype)
for a in addr[t]:
self.deladdr(ifindex, a)
# update cached information
self.getaddr(self.ifname(ifindex), rescan = True)
self.getaddr(self.ifname(ifindex), rescan=True)
def ifup(self, ifindex):
if self.up:
self.cmd([IFCONFIG_BIN, self.ifname(ifindex), "up"])
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "up"])
def newnetif(self, net = None, addrlist = [], hwaddr = None,
ifindex = None, ifname = None):
def newnetif(self, net=None, addrlist=[], hwaddr=None,
ifindex=None, ifname=None):
self.lock.acquire()
try:
ifindex = self.newveth(ifindex = ifindex, ifname = ifname,
net = net)
ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net)
if net is not None:
self.attachnet(ifindex, net)
if hwaddr:
self.sethwaddr(ifindex, hwaddr)
for addr in maketuple(addrlist):
for addr in utils.maketuple(addrlist):
self.addaddr(ifindex, addr)
self.ifup(ifindex)
return ifindex
@ -280,18 +289,17 @@ class SimpleJailNode(PyCoreNode):
self._netif[ifindex].detachnet()
def addfile(self, srcname, filename):
shcmd = "mkdir -p $(dirname '%s') && mv '%s' '%s' && sync" % \
(filename, srcname, filename)
shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename)
self.shcmd(shcmd)
def getaddr(self, ifname, rescan = False):
def getaddr(self, ifname, rescan=False):
return None
#return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
# return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
def addsymlink(self, path, file):
''' Create a symbolic link from /path/name/file ->
""" Create a symbolic link from /path/name/file ->
/tmp/pycore.nnnnn/@.conf/path.name/file
'''
"""
dirname = path
if dirname and dirname[0] == "/":
dirname = dirname[1:]
@ -316,14 +324,14 @@ class SimpleJailNode(PyCoreNode):
self.info("creating symlink %s -> %s" % (pathname, sym))
os.symlink(sym, pathname)
class JailNode(SimpleJailNode):
def __init__(self, session, objid = None, name = None,
nodedir = None, bootsh = "boot.sh", verbose = False,
start = True):
super(JailNode, self).__init__(session = session, objid = objid,
name = name, nodedir = nodedir,
verbose = verbose)
class JailNode(SimpleJailNode):
def __init__(self, session, objid=None, name=None,
nodedir=None, bootsh="boot.sh", verbose=False,
start=True):
super(JailNode, self).__init__(session=session, objid=objid,
name=name, nodedir=nodedir,
verbose=verbose)
self.bootsh = bootsh
if not start:
return
@ -341,8 +349,8 @@ class JailNode(SimpleJailNode):
self.lock.acquire()
try:
super(JailNode, self).startup()
#self.privatedir("/var/run")
#self.privatedir("/var/log")
# self.privatedir("/var/run")
# self.privatedir("/var/log")
finally:
self.lock.release()
@ -351,7 +359,7 @@ class JailNode(SimpleJailNode):
return
self.lock.acquire()
# services are instead stopped when session enters datacollect state
#self.session.services.stopnodeservices(self)
# self.session.services.stopnodeservices(self)
try:
super(JailNode, self).shutdown()
finally:
@ -362,7 +370,7 @@ class JailNode(SimpleJailNode):
if path[0] != "/":
raise ValueError, "path not fully qualified: " + path
hostpath = os.path.join(self.nodedir,
os.path.normpath(path).strip('/').replace('/', '.'))
os.path.normpath(path).strip("/").replace("/", "."))
try:
os.mkdir(hostpath)
except OSError:
@ -371,9 +379,9 @@ class JailNode(SimpleJailNode):
raise Exception, e
self.mount(hostpath, path)
def opennodefile(self, filename, mode = "w"):
def opennodefile(self, filename, mode="w"):
dirname, basename = os.path.split(filename)
#self.addsymlink(path=dirname, file=basename)
# self.addsymlink(path=dirname, file=basename)
if not basename:
raise ValueError, "no basename for filename: " + filename
if dirname and dirname[0] == "/":
@ -381,14 +389,13 @@ class JailNode(SimpleJailNode):
dirname = dirname.replace("/", ".")
dirname = os.path.join(self.nodedir, dirname)
if not os.path.isdir(dirname):
os.makedirs(dirname, mode = 0755)
os.makedirs(dirname, mode=0755)
hostfilename = os.path.join(dirname, basename)
return open(hostfilename, mode)
def nodefile(self, filename, contents, mode = 0644):
def nodefile(self, filename, contents, mode=0644):
f = self.opennodefile(filename, "w")
f.write(contents)
os.chmod(f.name, mode)
f.close()
self.info("created nodefile: '%s'; mode: 0%o" % (f.name, mode))
self.info("created nodefile: %s; mode: 0%o" % (f.name, mode))