quick pass for small cleanup within bsd nodes
This commit is contained in:
parent
1f9a8879c1
commit
78ff7f2189
4 changed files with 146 additions and 116 deletions
|
@ -16,58 +16,82 @@ import subprocess
|
||||||
from core import constants
|
from core import constants
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
|
|
||||||
utils.checkexec([constants.NGCTL_BIN])
|
utils.check_executables([constants.NGCTL_BIN])
|
||||||
|
|
||||||
|
|
||||||
def createngnode(type, hookstr, name=None):
|
def createngnode(node_type, hookstr, name=None):
|
||||||
"""
|
"""
|
||||||
Create a new Netgraph node of type and optionally assign name. The
|
Create a new Netgraph node of type and optionally assign name. The
|
||||||
hook string hookstr should contain two names. This is a string so
|
hook string hookstr should contain two names. This is a string so
|
||||||
other commands may be inserted after the two names.
|
other commands may be inserted after the two names.
|
||||||
Return the name and netgraph ID of the new node.
|
Return the name and netgraph ID of the new node.
|
||||||
|
|
||||||
|
:param node_type: node type to create
|
||||||
|
:param hookstr: hook string
|
||||||
|
:param name: name
|
||||||
|
:return: name and id
|
||||||
|
:rtype: tuple
|
||||||
"""
|
"""
|
||||||
hook1 = hookstr.split()[0]
|
hook1 = hookstr.split()[0]
|
||||||
ngcmd = "mkpeer %s %s \n show .%s" % (type, hookstr, hook1)
|
ngcmd = "mkpeer %s %s \n show .%s" % (node_type, hookstr, hook1)
|
||||||
cmd = [constants.NGCTL_BIN, "-f", "-"]
|
cmd = [constants.NGCTL_BIN, "-f", "-"]
|
||||||
cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.STDOUT)
|
|
||||||
# err will always be None
|
# err will always be None
|
||||||
result, err = cmdid.communicate(input=ngcmd)
|
result, err = cmdid.communicate(input=ngcmd)
|
||||||
status = cmdid.wait()
|
status = cmdid.wait()
|
||||||
if status > 0:
|
if status > 0:
|
||||||
raise Exception("error creating Netgraph node %s (%s): %s" % (type, ngcmd, result))
|
raise Exception("error creating Netgraph node %s (%s): %s" % (node_type, ngcmd, result))
|
||||||
results = result.split()
|
results = result.split()
|
||||||
ngname = results[1]
|
ngname = results[1]
|
||||||
ngid = results[5]
|
ngid = results[5]
|
||||||
if name:
|
if name:
|
||||||
utils.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name])
|
subprocess.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name])
|
||||||
return ngname, ngid
|
return ngname, ngid
|
||||||
|
|
||||||
|
|
||||||
def destroyngnode(name):
|
def destroyngnode(name):
|
||||||
""" Shutdown a Netgraph node having the given name.
|
|
||||||
"""
|
"""
|
||||||
utils.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name])
|
Shutdown a Netgraph node having the given name.
|
||||||
|
|
||||||
|
:param str name: node name
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
subprocess.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name])
|
||||||
|
|
||||||
|
|
||||||
def connectngnodes(name1, name2, hook1, hook2):
|
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.
|
||||||
|
|
||||||
|
:param str name1: name one
|
||||||
|
:param str name2: name two
|
||||||
|
:param str hook1: hook one
|
||||||
|
:param str hook2: hook two
|
||||||
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
node1 = "%s:" % name1
|
node1 = "%s:" % name1
|
||||||
node2 = "%s:" % name2
|
node2 = "%s:" % name2
|
||||||
utils.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2])
|
subprocess.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2])
|
||||||
|
|
||||||
|
|
||||||
def ngmessage(name, msg):
|
def ngmessage(name, msg):
|
||||||
""" Send a Netgraph message to the node named name.
|
"""
|
||||||
|
Send a Netgraph message to the node named name.
|
||||||
|
|
||||||
|
:param str name: node name
|
||||||
|
:param list msg: message
|
||||||
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg
|
cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg
|
||||||
utils.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
def ngloadkernelmodule(name):
|
def ngloadkernelmodule(name):
|
||||||
""" Load a kernel module by invoking kldstat. This is needed for the
|
"""
|
||||||
ng_ether module which automatically creates Netgraph nodes when loaded.
|
Load a kernel module by invoking kldstat. This is needed for the
|
||||||
|
ng_ether module which automatically creates Netgraph nodes when loaded.
|
||||||
|
|
||||||
|
:param str name: module name
|
||||||
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
utils.mutecall(["kldload", name])
|
utils.mutecall(["kldload", name])
|
||||||
|
|
|
@ -12,6 +12,7 @@ from the CoreNode, implementing specific node types.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from core import constants
|
from core import constants
|
||||||
from core.api import coreapi
|
from core.api import coreapi
|
||||||
|
@ -25,9 +26,12 @@ from core.enumerations import LinkTypes
|
||||||
from core.enumerations import NodeTypes
|
from core.enumerations import NodeTypes
|
||||||
from core.enumerations import RegisterTlvs
|
from core.enumerations import RegisterTlvs
|
||||||
from core.misc import ipaddress
|
from core.misc import ipaddress
|
||||||
|
from core.misc import log
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
|
|
||||||
utils.checkexec([constants.IFCONFIG_BIN])
|
logger = log.get_logger(__name__)
|
||||||
|
|
||||||
|
utils.check_executables([constants.IFCONFIG_BIN])
|
||||||
|
|
||||||
|
|
||||||
class CoreNode(JailNode):
|
class CoreNode(JailNode):
|
||||||
|
@ -36,14 +40,16 @@ class CoreNode(JailNode):
|
||||||
|
|
||||||
class PtpNet(NetgraphPipeNet):
|
class PtpNet(NetgraphPipeNet):
|
||||||
def tonodemsg(self, flags):
|
def tonodemsg(self, flags):
|
||||||
""" Do not generate a Node Message for point-to-point links. They are
|
"""
|
||||||
built using a link message instead.
|
Do not generate a Node Message for point-to-point links. They are
|
||||||
|
built using a link message instead.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def tolinkmsgs(self, flags):
|
def tolinkmsgs(self, flags):
|
||||||
""" Build CORE API TLVs for a point-to-point link. One Link message
|
"""
|
||||||
describes this network.
|
Build CORE API TLVs for a point-to-point link. One Link message
|
||||||
|
describes this network.
|
||||||
"""
|
"""
|
||||||
tlvdata = ""
|
tlvdata = ""
|
||||||
if len(self._netif) != 2:
|
if len(self._netif) != 2:
|
||||||
|
@ -74,7 +80,7 @@ class PtpNet(NetgraphPipeNet):
|
||||||
if if1.hwaddr:
|
if if1.hwaddr:
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr)
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr)
|
||||||
for addr in if1.addrlist:
|
for addr in if1.addrlist:
|
||||||
(ip, sep, mask) = addr.partition("/")
|
ip, sep, mask = addr.partition("/")
|
||||||
mask = int(mask)
|
mask = int(mask)
|
||||||
if ipaddress.is_ipv4_address(ip):
|
if ipaddress.is_ipv4_address(ip):
|
||||||
family = socket.AF_INET
|
family = socket.AF_INET
|
||||||
|
@ -92,7 +98,7 @@ class PtpNet(NetgraphPipeNet):
|
||||||
if if2.hwaddr:
|
if if2.hwaddr:
|
||||||
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr)
|
tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr)
|
||||||
for addr in if2.addrlist:
|
for addr in if2.addrlist:
|
||||||
(ip, sep, mask) = addr.partition("/")
|
ip, sep, mask = addr.partition("/")
|
||||||
mask = int(mask)
|
mask = int(mask)
|
||||||
if ipaddress.is_ipv4_address(ip):
|
if ipaddress.is_ipv4_address(ip):
|
||||||
family = socket.AF_INET
|
family = socket.AF_INET
|
||||||
|
@ -131,9 +137,8 @@ class WlanNode(NetgraphNet):
|
||||||
linktype = LinkTypes.WIRELESS.value
|
linktype = LinkTypes.WIRELESS.value
|
||||||
policy = "DROP"
|
policy = "DROP"
|
||||||
|
|
||||||
def __init__(self, session, objid=None, name=None, verbose=False,
|
def __init__(self, session, objid=None, name=None, start=True, policy=None):
|
||||||
start=True, policy=None):
|
NetgraphNet.__init__(self, session, objid, name, start, policy)
|
||||||
NetgraphNet.__init__(self, session, objid, name, verbose, start, policy)
|
|
||||||
# wireless model such as basic range
|
# wireless model such as basic range
|
||||||
self.model = None
|
self.model = None
|
||||||
# mobility model such as scripted
|
# mobility model such as scripted
|
||||||
|
@ -142,40 +147,42 @@ class WlanNode(NetgraphNet):
|
||||||
def attach(self, netif):
|
def attach(self, netif):
|
||||||
NetgraphNet.attach(self, netif)
|
NetgraphNet.attach(self, netif)
|
||||||
if self.model:
|
if self.model:
|
||||||
netif.poshook = self.model._positioncallback
|
netif.poshook = self.model.position_callback
|
||||||
if netif.node is None:
|
if netif.node is None:
|
||||||
return
|
return
|
||||||
x, y, z = netif.node.position.get()
|
x, y, z = netif.node.position.get()
|
||||||
netif.poshook(netif, x, y, z)
|
netif.poshook(netif, x, y, z)
|
||||||
|
|
||||||
def setmodel(self, model, config):
|
def setmodel(self, model, config):
|
||||||
""" Mobility and wireless model.
|
|
||||||
"""
|
"""
|
||||||
if self.verbose:
|
Mobility and wireless model.
|
||||||
self.info("adding model %s" % model._name)
|
|
||||||
if model._type == RegisterTlvs.WIRELESS.value:
|
:param core.mobility.WirelessModel.cls model: model to set
|
||||||
self.model = model(session=self.session, objid=self.objid,
|
:param dict config: configuration for model
|
||||||
verbose=self.verbose, values=config)
|
:return:
|
||||||
if self.model._positioncallback:
|
"""
|
||||||
|
logger.info("adding model %s" % model.name)
|
||||||
|
if model.config_type == RegisterTlvs.WIRELESS.value:
|
||||||
|
self.model = model(session=self.session, objid=self.objid, values=config)
|
||||||
|
if self.model.position_callback:
|
||||||
for netif in self.netifs():
|
for netif in self.netifs():
|
||||||
netif.poshook = self.model._positioncallback
|
netif.poshook = self.model.position_callback
|
||||||
if netif.node is not None:
|
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)
|
netif.poshook(netif, x, y, z)
|
||||||
self.model.setlinkparams()
|
self.model.setlinkparams()
|
||||||
elif model._type == RegisterTlvs.MOBILITY.value:
|
elif model.config_type == RegisterTlvs.MOBILITY.value:
|
||||||
self.mobility = model(session=self.session, objid=self.objid,
|
self.mobility = model(session=self.session, objid=self.objid, values=config)
|
||||||
verbose=self.verbose, values=config)
|
|
||||||
|
|
||||||
|
|
||||||
class RJ45Node(NetgraphPipeNet):
|
class RJ45Node(NetgraphPipeNet):
|
||||||
apitype = NodeTypes.RJ45.value
|
apitype = NodeTypes.RJ45.value
|
||||||
policy = "ACCEPT"
|
policy = "ACCEPT"
|
||||||
|
|
||||||
def __init__(self, session, objid, name, verbose, start=True):
|
def __init__(self, session, objid, name, start=True):
|
||||||
if start:
|
if start:
|
||||||
ngloadkernelmodule("ng_ether")
|
ngloadkernelmodule("ng_ether")
|
||||||
NetgraphPipeNet.__init__(self, session, objid, name, verbose, start)
|
NetgraphPipeNet.__init__(self, session, objid, name, start)
|
||||||
if start:
|
if start:
|
||||||
self.setpromisc(True)
|
self.setpromisc(True)
|
||||||
|
|
||||||
|
@ -187,12 +194,11 @@ class RJ45Node(NetgraphPipeNet):
|
||||||
p = "promisc"
|
p = "promisc"
|
||||||
if not promisc:
|
if not promisc:
|
||||||
p = "-" + p
|
p = "-" + p
|
||||||
utils.check_call([constants.IFCONFIG_BIN, self.name, "up", p])
|
subprocess.check_call([constants.IFCONFIG_BIN, self.name, "up", p])
|
||||||
|
|
||||||
def attach(self, netif):
|
def attach(self, netif):
|
||||||
if len(self._netif) > 0:
|
if len(self._netif) > 0:
|
||||||
raise ValueError, \
|
raise ValueError("RJ45 networks support at most 1 network interface")
|
||||||
"RJ45 networks support at most 1 network interface"
|
|
||||||
NetgraphPipeNet.attach(self, netif)
|
NetgraphPipeNet.attach(self, netif)
|
||||||
connectngnodes(self.ngname, self.name, self.gethook(), "lower")
|
connectngnodes(self.ngname, self.name, self.gethook(), "lower")
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,16 @@ from core.bsd.netgraph import createngnode
|
||||||
from core.bsd.netgraph import destroyngnode
|
from core.bsd.netgraph import destroyngnode
|
||||||
from core.bsd.netgraph import ngmessage
|
from core.bsd.netgraph import ngmessage
|
||||||
from core.coreobj import PyCoreNet
|
from core.coreobj import PyCoreNet
|
||||||
|
from core.misc import log
|
||||||
|
|
||||||
|
logger = log.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NetgraphNet(PyCoreNet):
|
class NetgraphNet(PyCoreNet):
|
||||||
ngtype = None
|
ngtype = None
|
||||||
nghooks = ()
|
nghooks = ()
|
||||||
|
|
||||||
def __init__(self, session, objid=None, name=None, verbose=False,
|
def __init__(self, session, objid=None, name=None, start=True, policy=None):
|
||||||
start=True, policy=None):
|
|
||||||
PyCoreNet.__init__(self, session, objid, name)
|
PyCoreNet.__init__(self, session, objid, name)
|
||||||
if name is None:
|
if name is None:
|
||||||
name = str(self.objid)
|
name = str(self.objid)
|
||||||
|
@ -32,7 +34,6 @@ class NetgraphNet(PyCoreNet):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.ngname = "n_%s_%s" % (str(self.objid), self.session.session_id)
|
self.ngname = "n_%s_%s" % (str(self.objid), self.session.session_id)
|
||||||
self.ngid = None
|
self.ngid = None
|
||||||
self.verbose = verbose
|
|
||||||
self._netif = {}
|
self._netif = {}
|
||||||
self._linked = {}
|
self._linked = {}
|
||||||
self.up = False
|
self.up = False
|
||||||
|
@ -40,7 +41,7 @@ class NetgraphNet(PyCoreNet):
|
||||||
self.startup()
|
self.startup()
|
||||||
|
|
||||||
def startup(self):
|
def startup(self):
|
||||||
tmp, self.ngid = createngnode(type=self.ngtype, hookstr=self.nghooks, name=self.ngname)
|
tmp, self.ngid = createngnode(node_type=self.ngtype, hookstr=self.nghooks, name=self.ngname)
|
||||||
self.up = True
|
self.up = True
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
|
@ -61,12 +62,13 @@ class NetgraphNet(PyCoreNet):
|
||||||
destroyngnode(self.ngname)
|
destroyngnode(self.ngname)
|
||||||
|
|
||||||
def attach(self, netif):
|
def attach(self, netif):
|
||||||
""" Attach an interface to this netgraph node. Create a pipe between
|
"""
|
||||||
the interface and the hub/switch/wlan node.
|
Attach an interface to this netgraph node. Create a pipe between
|
||||||
(Note that the PtpNet subclass overrides this method.)
|
the interface and the hub/switch/wlan node.
|
||||||
|
(Note that the PtpNet subclass overrides this method.)
|
||||||
"""
|
"""
|
||||||
if self.up:
|
if self.up:
|
||||||
pipe = self.session.addobj(cls=NetgraphPipeNet, verbose=self.verbose, start=True)
|
pipe = self.session.addobj(cls=NetgraphPipeNet, start=True)
|
||||||
pipe.attach(netif)
|
pipe.attach(netif)
|
||||||
hook = "link%d" % len(self._netif)
|
hook = "link%d" % len(self._netif)
|
||||||
pipe.attachnet(self, hook)
|
pipe.attachnet(self, hook)
|
||||||
|
@ -107,17 +109,19 @@ class NetgraphNet(PyCoreNet):
|
||||||
self._linked[netif1][netif2] = True
|
self._linked[netif1][netif2] = True
|
||||||
|
|
||||||
def linknet(self, net):
|
def linknet(self, net):
|
||||||
""" Link this bridge with another by creating a veth pair and installing
|
"""
|
||||||
each device into each bridge.
|
Link this bridge with another by creating a veth pair and installing
|
||||||
|
each device into each bridge.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def linkconfig(self, netif, bw=None, delay=None,
|
def linkconfig(self, netif, bw=None, delay=None,
|
||||||
loss=None, duplicate=None, jitter=None, netif2=None):
|
loss=None, duplicate=None, jitter=None, netif2=None):
|
||||||
""" Set link effects by modifying the pipe connected to an interface.
|
"""
|
||||||
|
Set link effects by modifying the pipe connected to an interface.
|
||||||
"""
|
"""
|
||||||
if not netif.pipe:
|
if not netif.pipe:
|
||||||
self.warn("linkconfig for %s but interface %s has no pipe" % (self.name, netif.name))
|
logger.warn("linkconfig for %s but interface %s has no pipe", self.name, netif.name)
|
||||||
return
|
return
|
||||||
return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2)
|
return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2)
|
||||||
|
|
||||||
|
@ -126,41 +130,40 @@ class NetgraphPipeNet(NetgraphNet):
|
||||||
ngtype = "pipe"
|
ngtype = "pipe"
|
||||||
nghooks = "upper lower"
|
nghooks = "upper lower"
|
||||||
|
|
||||||
def __init__(self, session, objid=None, name=None, verbose=False,
|
def __init__(self, session, objid=None, name=None, start=True, policy=None):
|
||||||
start=True, policy=None):
|
NetgraphNet.__init__(self, session, objid, name, start, policy)
|
||||||
NetgraphNet.__init__(self, session, objid, name, verbose, start, policy)
|
|
||||||
if start:
|
if start:
|
||||||
# account for Ethernet header
|
# account for Ethernet header
|
||||||
ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"])
|
ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"])
|
||||||
|
|
||||||
def attach(self, netif):
|
def attach(self, netif):
|
||||||
""" Attach an interface to this pipe node.
|
"""
|
||||||
The first interface is connected to the "upper" hook, the second
|
Attach an interface to this pipe node.
|
||||||
connected to the "lower" hook.
|
The first interface is connected to the "upper" hook, the second
|
||||||
|
connected to the "lower" hook.
|
||||||
"""
|
"""
|
||||||
if len(self._netif) > 1:
|
if len(self._netif) > 1:
|
||||||
raise ValueError, \
|
raise ValueError("Netgraph pipes support at most 2 network interfaces")
|
||||||
"Netgraph pipes support at most 2 network interfaces"
|
|
||||||
if self.up:
|
if self.up:
|
||||||
hook = self.gethook()
|
hook = self.gethook()
|
||||||
connectngnodes(self.ngname, netif.localname, hook, netif.hook)
|
connectngnodes(self.ngname, netif.localname, hook, netif.hook)
|
||||||
if netif.pipe:
|
if netif.pipe:
|
||||||
raise ValueError, \
|
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
|
netif.pipe = self
|
||||||
self._netif[netif] = netif
|
self._netif[netif] = netif
|
||||||
self._linked[netif] = {}
|
self._linked[netif] = {}
|
||||||
|
|
||||||
def attachnet(self, net, hook):
|
def attachnet(self, net, hook):
|
||||||
""" Attach another NetgraphNet to this pipe node.
|
"""
|
||||||
|
Attach another NetgraphNet to this pipe node.
|
||||||
"""
|
"""
|
||||||
localhook = self.gethook()
|
localhook = self.gethook()
|
||||||
connectngnodes(self.ngname, net.ngname, localhook, hook)
|
connectngnodes(self.ngname, net.ngname, localhook, hook)
|
||||||
|
|
||||||
def gethook(self):
|
def gethook(self):
|
||||||
""" Returns the first hook (e.g. "upper") then the second hook
|
"""
|
||||||
(e.g. "lower") based on the number of connections.
|
Returns the first hook (e.g. "upper") then the second hook
|
||||||
|
(e.g. "lower") based on the number of connections.
|
||||||
"""
|
"""
|
||||||
hooks = self.nghooks.split()
|
hooks = self.nghooks.split()
|
||||||
if len(self._netif) == 0:
|
if len(self._netif) == 0:
|
||||||
|
@ -170,7 +173,8 @@ class NetgraphPipeNet(NetgraphNet):
|
||||||
|
|
||||||
def linkconfig(self, netif, bw=None, delay=None,
|
def linkconfig(self, netif, bw=None, delay=None,
|
||||||
loss=None, duplicate=None, jitter=None, netif2=None):
|
loss=None, duplicate=None, jitter=None, netif2=None):
|
||||||
""" Set link effects by sending a Netgraph setcfg message to the pipe.
|
"""
|
||||||
|
Set link effects by sending a Netgraph setcfg message to the pipe.
|
||||||
"""
|
"""
|
||||||
netif.setparam("bw", bw)
|
netif.setparam("bw", bw)
|
||||||
netif.setparam("delay", delay)
|
netif.setparam("delay", delay)
|
||||||
|
@ -201,7 +205,7 @@ class NetgraphPipeNet(NetgraphNet):
|
||||||
upstream += ["duplicate=%s" % duplicate, ]
|
upstream += ["duplicate=%s" % duplicate, ]
|
||||||
downstream += ["duplicate=%s" % duplicate, ]
|
downstream += ["duplicate=%s" % duplicate, ]
|
||||||
if jitter:
|
if jitter:
|
||||||
self.warn("jitter parameter ignored for link %s" % self.name)
|
logger.warn("jitter parameter ignored for link %s", self.name)
|
||||||
if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0:
|
if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0:
|
||||||
setcfg = ["setcfg", "{", ] + params
|
setcfg = ["setcfg", "{", ] + params
|
||||||
if len(upstream) > 0:
|
if len(upstream) > 0:
|
||||||
|
|
|
@ -20,9 +20,12 @@ from core.bsd.netgraph import createngnode
|
||||||
from core.bsd.netgraph import destroyngnode
|
from core.bsd.netgraph import destroyngnode
|
||||||
from core.coreobj import PyCoreNetIf
|
from core.coreobj import PyCoreNetIf
|
||||||
from core.coreobj import PyCoreNode
|
from core.coreobj import PyCoreNode
|
||||||
|
from core.misc import log
|
||||||
from core.misc import utils
|
from core.misc import utils
|
||||||
|
|
||||||
utils.checkexec([constants.IFCONFIG_BIN, constants.VIMAGE_BIN])
|
logger = log.get_logger(__name__)
|
||||||
|
|
||||||
|
utils.check_executables([constants.IFCONFIG_BIN, constants.VIMAGE_BIN])
|
||||||
|
|
||||||
|
|
||||||
class VEth(PyCoreNetIf):
|
class VEth(PyCoreNetIf):
|
||||||
|
@ -46,11 +49,10 @@ class VEth(PyCoreNetIf):
|
||||||
|
|
||||||
def startup(self):
|
def startup(self):
|
||||||
hookstr = "%s %s" % (self.hook, self.hook)
|
hookstr = "%s %s" % (self.hook, self.hook)
|
||||||
ngname, ngid = createngnode(type="eiface", hookstr=hookstr,
|
ngname, ngid = createngnode(node_type="eiface", hookstr=hookstr, name=self.localname)
|
||||||
name=self.localname)
|
|
||||||
self.name = ngname
|
self.name = ngname
|
||||||
self.ngid = ngid
|
self.ngid = ngid
|
||||||
utils.check_call([constants.IFCONFIG_BIN, ngname, "up"])
|
subprocess.check_call([constants.IFCONFIG_BIN, ngname, "up"])
|
||||||
self.up = True
|
self.up = True
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
|
@ -81,19 +83,18 @@ class VEth(PyCoreNetIf):
|
||||||
|
|
||||||
|
|
||||||
class TunTap(PyCoreNetIf):
|
class TunTap(PyCoreNetIf):
|
||||||
"""TUN/TAP virtual device in TAP mode"""
|
"""
|
||||||
|
TUN/TAP virtual device in TAP mode
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, node, name, localname, mtu=None, net=None,
|
def __init__(self, node, name, localname, mtu=None, net=None, start=True):
|
||||||
start=True):
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class SimpleJailNode(PyCoreNode):
|
class SimpleJailNode(PyCoreNode):
|
||||||
def __init__(self, session, objid=None, name=None, nodedir=None,
|
def __init__(self, session, objid=None, name=None, nodedir=None):
|
||||||
verbose=False):
|
|
||||||
PyCoreNode.__init__(self, session, objid, name)
|
PyCoreNode.__init__(self, session, objid, name)
|
||||||
self.nodedir = nodedir
|
self.nodedir = nodedir
|
||||||
self.verbose = verbose
|
|
||||||
self.pid = None
|
self.pid = None
|
||||||
self.up = False
|
self.up = False
|
||||||
self.lock = threading.RLock()
|
self.lock = threading.RLock()
|
||||||
|
@ -101,16 +102,15 @@ class SimpleJailNode(PyCoreNode):
|
||||||
|
|
||||||
def startup(self):
|
def startup(self):
|
||||||
if self.up:
|
if self.up:
|
||||||
raise Exception, "already up"
|
raise Exception("already up")
|
||||||
vimg = [constants.VIMAGE_BIN, "-c", self.name]
|
vimg = [constants.VIMAGE_BIN, "-c", self.name]
|
||||||
try:
|
try:
|
||||||
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
|
os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg)
|
||||||
except OSError:
|
except OSError:
|
||||||
raise Exception, ("vimage command not found while running: %s" % \
|
raise Exception("vimage command not found while running: %s" % vimg)
|
||||||
vimg)
|
logger.info("bringing up loopback interface")
|
||||||
self.info("bringing up loopback interface")
|
|
||||||
self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"])
|
self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"])
|
||||||
self.info("setting hostname: %s" % self.name)
|
logger.info("setting hostname: %s", self.name)
|
||||||
self.cmd(["hostname", self.name])
|
self.cmd(["hostname", self.name])
|
||||||
self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"])
|
self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"])
|
||||||
self.up = True
|
self.up = True
|
||||||
|
@ -134,11 +134,11 @@ class SimpleJailNode(PyCoreNode):
|
||||||
mode = os.P_WAIT
|
mode = os.P_WAIT
|
||||||
else:
|
else:
|
||||||
mode = os.P_NOWAIT
|
mode = os.P_NOWAIT
|
||||||
tmp = utils.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir)
|
tmp = subprocess.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir)
|
||||||
if not wait:
|
if not wait:
|
||||||
tmp = None
|
tmp = None
|
||||||
if tmp:
|
if tmp:
|
||||||
self.warn("cmd exited with status %s: %s" % (tmp, str(args)))
|
logger.warn("cmd exited with status %s: %s", tmp, str(args))
|
||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
def cmdresult(self, args, wait=True):
|
def cmdresult(self, args, wait=True):
|
||||||
|
@ -170,8 +170,9 @@ class SimpleJailNode(PyCoreNode):
|
||||||
"-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh)
|
"-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh)
|
||||||
|
|
||||||
def termcmdstring(self, sh="/bin/sh"):
|
def termcmdstring(self, sh="/bin/sh"):
|
||||||
""" We add "sudo" to the command string because the GUI runs as a
|
"""
|
||||||
normal user.
|
We add "sudo" to the command string because the GUI runs as a
|
||||||
|
normal user.
|
||||||
"""
|
"""
|
||||||
return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh)
|
return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh)
|
||||||
|
|
||||||
|
@ -183,11 +184,11 @@ class SimpleJailNode(PyCoreNode):
|
||||||
|
|
||||||
def mount(self, source, target):
|
def mount(self, source, target):
|
||||||
source = os.path.abspath(source)
|
source = os.path.abspath(source)
|
||||||
self.info("mounting %s at %s" % (source, target))
|
logger.info("mounting %s at %s", source, target)
|
||||||
self.addsymlink(path=target, file=None)
|
self.addsymlink(path=target, file=None)
|
||||||
|
|
||||||
def umount(self, target):
|
def umount(self, target):
|
||||||
self.info("unmounting %s" % target)
|
logger.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()
|
self.lock.acquire()
|
||||||
|
@ -204,7 +205,7 @@ class SimpleJailNode(PyCoreNode):
|
||||||
mtu=1500, net=net, start=self.up)
|
mtu=1500, net=net, start=self.up)
|
||||||
if self.up:
|
if self.up:
|
||||||
# install into jail
|
# install into jail
|
||||||
utils.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name])
|
subprocess.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name])
|
||||||
|
|
||||||
# rename from "ngeth0" to "eth0"
|
# rename from "ngeth0" to "eth0"
|
||||||
self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname])
|
self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname])
|
||||||
|
@ -223,8 +224,7 @@ class SimpleJailNode(PyCoreNode):
|
||||||
def sethwaddr(self, ifindex, addr):
|
def sethwaddr(self, ifindex, addr):
|
||||||
self._netif[ifindex].sethwaddr(addr)
|
self._netif[ifindex].sethwaddr(addr)
|
||||||
if self.up:
|
if self.up:
|
||||||
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link",
|
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link", str(addr)])
|
||||||
str(addr)])
|
|
||||||
|
|
||||||
def addaddr(self, ifindex, addr):
|
def addaddr(self, ifindex, addr):
|
||||||
if self.up:
|
if self.up:
|
||||||
|
@ -232,15 +232,14 @@ class SimpleJailNode(PyCoreNode):
|
||||||
family = "inet6"
|
family = "inet6"
|
||||||
else:
|
else:
|
||||||
family = "inet"
|
family = "inet"
|
||||||
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias",
|
self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias", str(addr)])
|
||||||
str(addr)])
|
|
||||||
self._netif[ifindex].addaddr(addr)
|
self._netif[ifindex].addaddr(addr)
|
||||||
|
|
||||||
def deladdr(self, ifindex, addr):
|
def deladdr(self, ifindex, addr):
|
||||||
try:
|
try:
|
||||||
self._netif[ifindex].deladdr(addr)
|
self._netif[ifindex].deladdr(addr)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.warn("trying to delete unknown address: %s" % addr)
|
logger.warn("trying to delete unknown address: %s", addr)
|
||||||
if self.up:
|
if self.up:
|
||||||
if ":" in addr:
|
if ":" in addr:
|
||||||
family = "inet6"
|
family = "inet6"
|
||||||
|
@ -255,8 +254,7 @@ class SimpleJailNode(PyCoreNode):
|
||||||
addr = self.getaddr(self.ifname(ifindex), rescan=True)
|
addr = self.getaddr(self.ifname(ifindex), rescan=True)
|
||||||
for t in addrtypes:
|
for t in addrtypes:
|
||||||
if t not in self.valid_deladdrtype:
|
if t not in self.valid_deladdrtype:
|
||||||
raise ValueError, "addr type must be in: " + \
|
raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype))
|
||||||
" ".join(self.valid_deladdrtype)
|
|
||||||
for a in addr[t]:
|
for a in addr[t]:
|
||||||
self.deladdr(ifindex, a)
|
self.deladdr(ifindex, a)
|
||||||
# update cached information
|
# update cached information
|
||||||
|
@ -297,8 +295,9 @@ class SimpleJailNode(PyCoreNode):
|
||||||
# return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
|
# return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan)
|
||||||
|
|
||||||
def addsymlink(self, path, file):
|
def addsymlink(self, path, file):
|
||||||
""" Create a symbolic link from /path/name/file ->
|
"""
|
||||||
/tmp/pycore.nnnnn/@.conf/path.name/file
|
Create a symbolic link from /path/name/file ->
|
||||||
|
/tmp/pycore.nnnnn/@.conf/path.name/file
|
||||||
"""
|
"""
|
||||||
dirname = path
|
dirname = path
|
||||||
if dirname and dirname[0] == "/":
|
if dirname and dirname[0] == "/":
|
||||||
|
@ -318,20 +317,15 @@ class SimpleJailNode(PyCoreNode):
|
||||||
os.unlink(pathname)
|
os.unlink(pathname)
|
||||||
else:
|
else:
|
||||||
if os.path.exists(pathname):
|
if os.path.exists(pathname):
|
||||||
self.warn("did not create symlink for %s since path " \
|
logger.warn("did not create symlink for %s since path exists on host", pathname)
|
||||||
"exists on host" % pathname)
|
|
||||||
return
|
return
|
||||||
self.info("creating symlink %s -> %s" % (pathname, sym))
|
logger.info("creating symlink %s -> %s", pathname, sym)
|
||||||
os.symlink(sym, pathname)
|
os.symlink(sym, pathname)
|
||||||
|
|
||||||
|
|
||||||
class JailNode(SimpleJailNode):
|
class JailNode(SimpleJailNode):
|
||||||
def __init__(self, session, objid=None, name=None,
|
def __init__(self, session, objid=None, name=None, nodedir=None, bootsh="boot.sh", start=True):
|
||||||
nodedir=None, bootsh="boot.sh", verbose=False,
|
super(JailNode, self).__init__(session=session, objid=objid, name=name, nodedir=nodedir)
|
||||||
start=True):
|
|
||||||
super(JailNode, self).__init__(session=session, objid=objid,
|
|
||||||
name=name, nodedir=nodedir,
|
|
||||||
verbose=verbose)
|
|
||||||
self.bootsh = bootsh
|
self.bootsh = bootsh
|
||||||
if not start:
|
if not start:
|
||||||
return
|
return
|
||||||
|
@ -369,8 +363,10 @@ class JailNode(SimpleJailNode):
|
||||||
def privatedir(self, path):
|
def privatedir(self, path):
|
||||||
if path[0] != "/":
|
if path[0] != "/":
|
||||||
raise ValueError, "path not fully qualified: " + path
|
raise ValueError, "path not fully qualified: " + path
|
||||||
hostpath = os.path.join(self.nodedir,
|
hostpath = os.path.join(
|
||||||
os.path.normpath(path).strip("/").replace("/", "."))
|
self.nodedir,
|
||||||
|
os.path.normpath(path).strip("/").replace("/", ".")
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
os.mkdir(hostpath)
|
os.mkdir(hostpath)
|
||||||
except OSError:
|
except OSError:
|
||||||
|
@ -383,7 +379,7 @@ class JailNode(SimpleJailNode):
|
||||||
dirname, basename = os.path.split(filename)
|
dirname, basename = os.path.split(filename)
|
||||||
# self.addsymlink(path=dirname, file=basename)
|
# self.addsymlink(path=dirname, file=basename)
|
||||||
if not basename:
|
if not basename:
|
||||||
raise ValueError, "no basename for filename: " + filename
|
raise ValueError("no basename for filename: %s" % filename)
|
||||||
if dirname and dirname[0] == "/":
|
if dirname and dirname[0] == "/":
|
||||||
dirname = dirname[1:]
|
dirname = dirname[1:]
|
||||||
dirname = dirname.replace("/", ".")
|
dirname = dirname.replace("/", ".")
|
||||||
|
@ -398,4 +394,4 @@ class JailNode(SimpleJailNode):
|
||||||
f.write(contents)
|
f.write(contents)
|
||||||
os.chmod(f.name, mode)
|
os.chmod(f.name, mode)
|
||||||
f.close()
|
f.close()
|
||||||
self.info("created nodefile: %s; mode: 0%o" % (f.name, mode))
|
logger.info("created nodefile: %s; mode: 0%o", f.name, mode)
|
||||||
|
|
Loading…
Reference in a new issue