Commit 06a7d24d authored by Martín Ferrari's avatar Martín Ferrari

Organize things a little

parent c713490e
# vim:ts=4:sw=4:et:ai:sts=4
import os
__all__ = ["ip_path", "tc_path", "brctl_path", "hz"]
def _find_bin(name):
for pref in ("/", "/usr/", "/usr/local/"):
for d in ("bin/", "sbin/"):
try:
os.stat(pref + d + name)
return pref + d + name
except OSError, e:
if e.errno != os.errno.ENOENT:
raise
raise RuntimeError("Cannot find `%s' command, impossible to continue." %
name)
ip_path = _find_bin("ip")
tc_path = _find_bin("tc")
brctl_path = _find_bin("brctl")
sysctl_path = _find_bin("sysctl")
# Seems this is completely bogus. At least, we can assume that the internal HZ
# is bigger than this.
hz = os.sysconf("SC_CLK_TCK")
try:
os.stat("/sys/class/net")
except:
raise RuntimeError("Sysfs does not seem to be mounted, impossible to " +
"continue.")
...@@ -50,7 +50,8 @@ class NSInterface(Interface): ...@@ -50,7 +50,8 @@ class NSInterface(Interface):
# Disable auto-configuration # Disable auto-configuration
# you wish: need to take into account the nonetns mode; plus not # you wish: need to take into account the nonetns mode; plus not
# touching some pre-existing ifaces # touching some pre-existing ifaces
#node.system(['/sbin/sysctl', '-w', 'net.ipv6.conf.%s.autoconf=0' % self.name]) #node.system([sysctl_path, '-w', 'net.ipv6.conf.%s.autoconf=0' %
#self.name])
node._add_interface(self) node._add_interface(self)
# some black magic to automatically get/set interface attributes # some black magic to automatically get/set interface attributes
......
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import copy, os, re, socket, subprocess, sys import copy, os, re, socket, subprocess, sys
from netns.environ import *
def _find_bin(name):
for pref in ("/", "/usr/", "/usr/local/"):
for d in ("bin/", "sbin/"):
try:
os.stat(pref + d + name)
return pref + d + name
except OSError, e:
if e.errno != os.errno.ENOENT:
raise
raise RuntimeError("Cannot find `%s' command, impossible to continue." %
name)
_ip = _find_bin("ip")
_tc = _find_bin("tc")
_brctl = _find_bin("brctl")
# Seems this is completely bogus. At least, we can assume that the internal HZ
# is bigger than this.
_hz = os.sysconf("SC_CLK_TCK")
try:
os.stat("/sys/class/net")
except:
raise RuntimeError("Sysfs does not seem to be mounted, impossible to " +
"continue.")
# helpers # helpers
def _any_to_bool(any): def _any_to_bool(any):
...@@ -311,7 +287,7 @@ def get_if_data(): ...@@ -311,7 +287,7 @@ def get_if_data():
In each dictionary, values are interface objects. In each dictionary, values are interface objects.
""" """
ipcmd = subprocess.Popen([_ip, "-o", "link", "list"], ipcmd = subprocess.Popen([ip_path, "-o", "link", "list"],
stdout = subprocess.PIPE) stdout = subprocess.PIPE)
ipdata = ipcmd.communicate()[0] ipdata = ipcmd.communicate()[0]
assert ipcmd.wait() == 0 assert ipcmd.wait() == 0
...@@ -363,7 +339,7 @@ def create_if_pair(if1, if2): ...@@ -363,7 +339,7 @@ def create_if_pair(if1, if2):
if iface[i].mtu: if iface[i].mtu:
cmd[i] += ["mtu", str(iface[i].mtu)] cmd[i] += ["mtu", str(iface[i].mtu)]
cmd = [_ip, "link", "add"] + cmd[0] + ["type", "veth", "peer"] + cmd[1] cmd = [ip_path, "link", "add"] + cmd[0] + ["type", "veth", "peer"] + cmd[1]
_execute(cmd) _execute(cmd)
try: try:
set_if(if1) set_if(if1)
...@@ -381,7 +357,7 @@ def create_if_pair(if1, if2): ...@@ -381,7 +357,7 @@ def create_if_pair(if1, if2):
def del_if(iface): def del_if(iface):
ifname = _get_if_name(iface) ifname = _get_if_name(iface)
_execute([_ip, "link", "del", ifname]) _execute([ip_path, "link", "del", ifname])
def set_if(iface, recover = True): def set_if(iface, recover = True):
def do_cmds(cmds, orig_iface): def do_cmds(cmds, orig_iface):
...@@ -398,7 +374,7 @@ def set_if(iface, recover = True): ...@@ -398,7 +374,7 @@ def set_if(iface, recover = True):
# Name goes first # Name goes first
if diff.name: if diff.name:
_ils = [_ip, "link", "set", "dev"] _ils = [ip_path, "link", "set", "dev"]
cmds = [_ils + [orig_iface.name, "name", diff.name]] cmds = [_ils + [orig_iface.name, "name", diff.name]]
if orig_iface.up: if orig_iface.up:
# iface needs to be down # iface needs to be down
...@@ -407,7 +383,7 @@ def set_if(iface, recover = True): ...@@ -407,7 +383,7 @@ def set_if(iface, recover = True):
do_cmds(cmds, orig_iface) do_cmds(cmds, orig_iface)
# I need to use the new name after a name change, duh! # I need to use the new name after a name change, duh!
_ils = [_ip, "link", "set", "dev", diff.name or orig_iface.name] _ils = [ip_path, "link", "set", "dev", diff.name or orig_iface.name]
cmds = [] cmds = []
if diff.lladdr: if diff.lladdr:
if orig_iface.up: if orig_iface.up:
...@@ -432,12 +408,12 @@ def set_if(iface, recover = True): ...@@ -432,12 +408,12 @@ def set_if(iface, recover = True):
def change_netns(iface, netns): def change_netns(iface, netns):
ifname = _get_if_name(iface) ifname = _get_if_name(iface)
_execute([_ip, "link", "set", "dev", ifname, "netns", str(netns)]) _execute([ip_path, "link", "set", "dev", ifname, "netns", str(netns)])
# Address handling # Address handling
def get_addr_data(): def get_addr_data():
ipcmd = subprocess.Popen([_ip, "-o", "addr", "list"], ipcmd = subprocess.Popen([ip_path, "-o", "addr", "list"],
stdout = subprocess.PIPE) stdout = subprocess.PIPE)
ipdata = ipcmd.communicate()[0] ipdata = ipcmd.communicate()[0]
assert ipcmd.wait() == 0 assert ipcmd.wait() == 0
...@@ -479,7 +455,7 @@ def add_addr(iface, address): ...@@ -479,7 +455,7 @@ def add_addr(iface, address):
addresses = get_addr_data()[1][ifname] addresses = get_addr_data()[1][ifname]
assert address not in addresses assert address not in addresses
cmd = [_ip, "addr", "add", "dev", ifname, "local", cmd = [ip_path, "addr", "add", "dev", ifname, "local",
"%s/%d" % (address.address, int(address.prefix_len))] "%s/%d" % (address.address, int(address.prefix_len))]
if hasattr(address, "broadcast"): if hasattr(address, "broadcast"):
cmd += ["broadcast", address.broadcast if address.broadcast else "+"] cmd += ["broadcast", address.broadcast if address.broadcast else "+"]
...@@ -490,7 +466,7 @@ def del_addr(iface, address): ...@@ -490,7 +466,7 @@ def del_addr(iface, address):
addresses = get_addr_data()[1][ifname] addresses = get_addr_data()[1][ifname]
assert address in addresses assert address in addresses
cmd = [_ip, "addr", "del", "dev", ifname, "local", cmd = [ip_path, "addr", "del", "dev", ifname, "local",
"%s/%d" % (address.address, int(address.prefix_len))] "%s/%d" % (address.address, int(address.prefix_len))]
_execute(cmd) _execute(cmd)
...@@ -564,7 +540,7 @@ def create_bridge(br): ...@@ -564,7 +540,7 @@ def create_bridge(br):
if isinstance(br, str): if isinstance(br, str):
br = interface(name = br) br = interface(name = br)
assert br.name assert br.name
_execute([_brctl, "addbr", br.name]) _execute([brctl_path, "addbr", br.name])
try: try:
set_if(br) set_if(br)
except: except:
...@@ -578,7 +554,7 @@ def create_bridge(br): ...@@ -578,7 +554,7 @@ def create_bridge(br):
def del_bridge(br): def del_bridge(br):
brname = _get_if_name(br) brname = _get_if_name(br)
_execute([_brctl, "delbr", brname]) _execute([brctl_path, "delbr", brname])
def set_bridge(br, recover = True): def set_bridge(br, recover = True):
def saveval(fname, val): def saveval(fname, val):
...@@ -617,20 +593,20 @@ def set_bridge(br, recover = True): ...@@ -617,20 +593,20 @@ def set_bridge(br, recover = True):
def add_bridge_port(br, iface): def add_bridge_port(br, iface):
ifname = _get_if_name(iface) ifname = _get_if_name(iface)
brname = _get_if_name(br) brname = _get_if_name(br)
_execute([_brctl, "addif", brname, ifname]) _execute([brctl_path, "addif", brname, ifname])
def del_bridge_port(br, iface): def del_bridge_port(br, iface):
ifname = _get_if_name(iface) ifname = _get_if_name(iface)
brname = _get_if_name(br) brname = _get_if_name(br)
_execute([_brctl, "delif", brname, ifname]) _execute([brctl_path, "delif", brname, ifname])
def get_all_route_data(): def get_all_route_data():
#ipcmd = subprocess.Popen([_ip, "-o", "route", "list", "table", "all"], #ipcmd = subprocess.Popen([ip_path, "-o", "route", "list", "table", "all"],
ipcmd = subprocess.Popen([_ip, "-o", "route", "list"], ipcmd = subprocess.Popen([ip_path, "-o", "route", "list"],
stdout = subprocess.PIPE) stdout = subprocess.PIPE)
ipdata = ipcmd.communicate()[0] ipdata = ipcmd.communicate()[0]
assert ipcmd.wait() == 0 assert ipcmd.wait() == 0
ipcmd = subprocess.Popen([_ip, "-o", "-f", "inet6", "route", "list"], ipcmd = subprocess.Popen([ip_path, "-o", "-f", "inet6", "route", "list"],
stdout = subprocess.PIPE) stdout = subprocess.PIPE)
ipdata += ipcmd.communicate()[0] ipdata += ipcmd.communicate()[0]
assert ipcmd.wait() == 0 assert ipcmd.wait() == 0
...@@ -678,7 +654,7 @@ def del_route(route): ...@@ -678,7 +654,7 @@ def del_route(route):
_add_del_route("del", route) _add_del_route("del", route)
def _add_del_route(action, route): def _add_del_route(action, route):
cmd = [_ip, "route", action] cmd = [ip_path, "route", action]
if route.tipe != "unicast": if route.tipe != "unicast":
cmd += [route.tipe] cmd += [route.tipe]
if route.prefix: if route.prefix:
...@@ -694,7 +670,8 @@ def _add_del_route(action, route): ...@@ -694,7 +670,8 @@ def _add_del_route(action, route):
# TC stuff # TC stuff
def get_tc_tree(): def get_tc_tree():
tccmd = subprocess.Popen([_tc, "qdisc", "show"], stdout = subprocess.PIPE) tccmd = subprocess.Popen([tc_path, "qdisc", "show"],
stdout = subprocess.PIPE)
tcdata = tccmd.communicate()[0] tcdata = tccmd.communicate()[0]
assert tccmd.wait() == 0 assert tccmd.wait() == 0
...@@ -852,7 +829,7 @@ def clear_tc(iface): ...@@ -852,7 +829,7 @@ def clear_tc(iface):
if tcdata[iface.index] == None: if tcdata[iface.index] == None:
return return
# Any other case, we clean # Any other case, we clean
_execute([_tc, "qdisc", "del", "dev", iface.name, "root"]) _execute([tc_path, "qdisc", "del", "dev", iface.name, "root"])
def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None, def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None,
delay_correlation = None, delay_distribution = None, delay_correlation = None, delay_distribution = None,
...@@ -868,7 +845,7 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None, ...@@ -868,7 +845,7 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None,
commands = [] commands = []
if tcdata[iface.index] == 'foreign': if tcdata[iface.index] == 'foreign':
# Avoid the overhead of calling tc+ip again # Avoid the overhead of calling tc+ip again
commands.append([_tc, "qdisc", "del", "dev", iface.name, "root"]) commands.append([tc_path, "qdisc", "del", "dev", iface.name, "root"])
tcdata[iface.index] = {'qdiscs': []} tcdata[iface.index] = {'qdiscs': []}
has_netem = 'netem' in tcdata[iface.index]['qdiscs'] has_netem = 'netem' in tcdata[iface.index]['qdiscs']
...@@ -884,18 +861,19 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None, ...@@ -884,18 +861,19 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None,
else: else:
# Too much work to do better :) # Too much work to do better :)
if has_netem or has_tbf: if has_netem or has_tbf:
commands.append([_tc, "qdisc", "del", "dev", iface.name, "root"]) commands.append([tc_path, "qdisc", "del", "dev", iface.name,
"root"])
cmd = "add" cmd = "add"
if bandwidth: if bandwidth:
rate = "%dbit" % int(bandwidth) rate = "%dbit" % int(bandwidth)
mtu = ifdata[iface.index].mtu mtu = ifdata[iface.index].mtu
burst = max(mtu, int(bandwidth) / _hz) burst = max(mtu, int(bandwidth) / hz)
limit = burst * 2 # FIXME? limit = burst * 2 # FIXME?
handle = "1:" handle = "1:"
if cmd == "change": if cmd == "change":
handle = "%d:" % int(tcdata[iface.index]["qdiscs"]["tbf"]) handle = "%d:" % int(tcdata[iface.index]["qdiscs"]["tbf"])
command = [_tc, "qdisc", cmd, "dev", iface.name, "root", "handle", command = [tc_path, "qdisc", cmd, "dev", iface.name, "root", "handle",
handle, "tbf", "rate", rate, "limit", str(limit), "burst", handle, "tbf", "rate", rate, "limit", str(limit), "burst",
str(burst)] str(burst)]
commands.append(command) commands.append(command)
...@@ -904,7 +882,7 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None, ...@@ -904,7 +882,7 @@ def set_tc(iface, bandwidth = None, delay = None, delay_jitter = None,
handle = "2:" handle = "2:"
if cmd == "change": if cmd == "change":
handle = "%d:" % int(tcdata[iface.index]["qdiscs"]["netem"]) handle = "%d:" % int(tcdata[iface.index]["qdiscs"]["netem"])
command = [_tc, "qdisc", cmd, "dev", iface.name, "handle", handle] command = [tc_path, "qdisc", cmd, "dev", iface.name, "handle", handle]
if bandwidth: if bandwidth:
parent = "1:" parent = "1:"
if cmd == "change": if cmd == "change":
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import os, socket, sys, traceback, unshare, weakref import os, socket, sys, traceback, unshare, weakref
import netns.protocol, netns.subprocess_ import netns.environ, netns.protocol, netns.subprocess_
__all__ = ['Node', 'get_nodes'] __all__ = ['Node', 'get_nodes']
...@@ -161,8 +161,9 @@ def _start_child(debug, nonetns): ...@@ -161,8 +161,9 @@ def _start_child(debug, nonetns):
# create new name space # create new name space
unshare.unshare(unshare.CLONE_NEWNET) unshare.unshare(unshare.CLONE_NEWNET)
# Enable packet forwarding # Enable packet forwarding
netns.iproute._execute(['sysctl', '-w', 'net.ipv4.ip_forward=1']) netns.iproute._execute([netns.environ.sysctl_path, '-w',
netns.iproute._execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])
netns.iproute._execute([netns.environ.sysctl_path, '-w',
'net.ipv6.conf.default.forwarding=1']) 'net.ipv6.conf.default.forwarding=1'])
srv.run() srv.run()
except BaseException, e: except BaseException, e:
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
from test_util import get_devs, get_devs_netns from test_util import get_devs, get_devs_netns
from netns.environ import *
import netns, test_util import netns, test_util
import os import os, unittest
import unittest
class TestUtils(unittest.TestCase): class TestUtils(unittest.TestCase):
def test_utils(self): def test_utils(self):
...@@ -80,7 +80,7 @@ class TestInterfaces(unittest.TestCase): ...@@ -80,7 +80,7 @@ class TestInterfaces(unittest.TestCase):
self.assertTrue(devs[if0.name]['up']) self.assertTrue(devs[if0.name]['up'])
# Verify that data is actually read from the kernel # Verify that data is actually read from the kernel
r = node0.system(["ip", "link", "set", if0.name, "mtu", "1500"]) r = node0.system([ip_path, "link", "set", if0.name, "mtu", "1500"])
self.assertEquals(r, 0) self.assertEquals(r, 0)
devs = get_devs_netns(node0) devs = get_devs_netns(node0)
self.assertEquals(devs[if0.name]['mtu'], 1500) self.assertEquals(devs[if0.name]['mtu'], 1500)
...@@ -126,8 +126,8 @@ class TestWithDummy(unittest.TestCase): ...@@ -126,8 +126,8 @@ class TestWithDummy(unittest.TestCase):
def test_interface_migration(self): def test_interface_migration(self):
node = netns.Node() node = netns.Node()
self.dummyname = "dummy%d" % os.getpid() self.dummyname = "dummy%d" % os.getpid()
self.assertEquals( self.assertEquals(os.system("%s link add name %s type dummy" %
os.system("ip link add name %s type dummy" % self.dummyname), 0) (ip_path, self.dummyname)), 0)
devs = get_devs() devs = get_devs()
self.assertTrue(self.dummyname in devs) self.assertTrue(self.dummyname in devs)
dummyidx = devs[self.dummyname]['idx'] dummyidx = devs[self.dummyname]['idx']
...@@ -152,7 +152,7 @@ class TestWithDummy(unittest.TestCase): ...@@ -152,7 +152,7 @@ class TestWithDummy(unittest.TestCase):
def tearDown(self): def tearDown(self):
# oops here # oops here
if hasattr(self, 'dummyname'): if hasattr(self, 'dummyname'):
os.system("ip link del %s" % self.dummyname) os.system("%s link del %s" % (ip_path, self.dummyname))
# FIXME: Links # FIXME: Links
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import os, unittest import os, unittest
import netns, test_util import netns, test_util, netns.environ
class TestLink(unittest.TestCase): class TestLink(unittest.TestCase):
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
...@@ -46,7 +46,7 @@ class TestLink(unittest.TestCase): ...@@ -46,7 +46,7 @@ class TestLink(unittest.TestCase):
# Test strange rules handling # Test strange rules handling
os.system(("%s qd add dev %s root prio bands 3 " + os.system(("%s qd add dev %s root prio bands 3 " +
"priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1") % "priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1") %
(netns.iproute._tc, i1.control.name)) (netns.environ.tc_path, i1.control.name))
tcdata = netns.iproute.get_tc_data()[0] tcdata = netns.iproute.get_tc_data()[0]
self.assertEquals(tcdata[i1.control.index], "foreign") self.assertEquals(tcdata[i1.control.index], "foreign")
l.set_parameters(bandwidth = 13107200) # 100 mbits l.set_parameters(bandwidth = 13107200) # 100 mbits
......
#!/usr/bin/env python #!/usr/bin/env python
# vim:ts=4:sw=4:et:ai:sts=4 # vim:ts=4:sw=4:et:ai:sts=4
import netns, test_util import netns, netns.environ, test_util
import os, signal, subprocess, sys, time import os, signal, subprocess, sys, time
import unittest import unittest
class TestNode(unittest.TestCase): class TestNode(unittest.TestCase):
# def setUp(self):
# pass
@test_util.skipUnless(os.getuid() == 0, "Test requires root privileges") @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
def test_node(self): def test_node(self):
node = netns.Node() node = netns.Node()
...@@ -41,8 +39,8 @@ class TestNode(unittest.TestCase): ...@@ -41,8 +39,8 @@ class TestNode(unittest.TestCase):
link.connect(ifa) link.connect(ifa)
link.connect(ifb) link.connect(ifb)
def get_devs(): def get_devs():
ipcmd = subprocess.Popen(["ip", "-o", "link", "list"], ipcmd = subprocess.Popen([netns.environ.ip_path, "-o", "link",
stdout = subprocess.PIPE) "list"], stdout = subprocess.PIPE)
(outdata, errdata) = ipcmd.communicate() (outdata, errdata) = ipcmd.communicate()
ipcmd.wait() ipcmd.wait()
return outdata.split("\n") return outdata.split("\n")
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import os, re, subprocess, sys import os, re, subprocess, sys
import netns.subprocess_ import netns.subprocess_
from netns.environ import *
def process_ipcmd(str): def process_ipcmd(str):
cur = None cur = None
...@@ -53,13 +54,13 @@ def process_ipcmd(str): ...@@ -53,13 +54,13 @@ def process_ipcmd(str):
return out return out
def get_devs(): def get_devs():
ipcmd = subprocess.Popen(["ip", "addr", "list"], ipcmd = subprocess.Popen([ip_path, "addr", "list"],
stdout = subprocess.PIPE) stdout = subprocess.PIPE)
(outdata, errdata) = ipcmd.communicate() (outdata, errdata) = ipcmd.communicate()
return process_ipcmd(outdata) return process_ipcmd(outdata)
def get_devs_netns(node): def get_devs_netns(node):
out = netns.subprocess_.backticks_raise(node, ["ip", "addr", "list"]) out = netns.subprocess_.backticks_raise(node, [ip_path, "addr", "list"])
return process_ipcmd(out) return process_ipcmd(out)
def make_linux_ver(string): def make_linux_ver(string):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment