initial commit after bringing over cleaned up code and testing some examples
This commit is contained in:
parent
c4858e6e0d
commit
00f4ebf5a9
93 changed files with 15189 additions and 13083 deletions
|
@ -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])
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue