First crack at restoring mininet python style, assisted by handy
'unpep8' script, which does most of the work. - topo.py is still in pep8 - not all examples work, but this is due to other issues
This commit is contained in:
+89
-154
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
'''Utility functions for Mininet.'''
|
||||
"Utility functions for Mininet."
|
||||
|
||||
from time import sleep
|
||||
from resource import setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
|
||||
@@ -8,41 +8,32 @@ from subprocess import call, check_call, Popen, PIPE, STDOUT
|
||||
|
||||
from mininet.log import lg
|
||||
|
||||
def run( cmd ):
|
||||
"""Simple interface to subprocess.call()
|
||||
cmd: list of command params"""
|
||||
return call( cmd.split( ' ' ) )
|
||||
|
||||
def run(cmd):
|
||||
'''Simple interface to subprocess.call()
|
||||
def checkRun( cmd ):
|
||||
"""Simple interface to subprocess.check_call()
|
||||
cmd: list of command params"""
|
||||
check_call( cmd.split( ' ' ) )
|
||||
|
||||
@param cmd list of command params
|
||||
'''
|
||||
return call(cmd.split(' '))
|
||||
|
||||
|
||||
def checkRun(cmd):
|
||||
'''Simple interface to subprocess.check_call()
|
||||
|
||||
@param cmd list of command params
|
||||
'''
|
||||
check_call(cmd.split(' '))
|
||||
|
||||
|
||||
def quietRun(cmd):
|
||||
'''Run a command, routing stderr to stdout, and return the output.
|
||||
|
||||
@param cmd list of command params
|
||||
'''
|
||||
if isinstance(cmd, str):
|
||||
cmd = cmd.split(' ')
|
||||
popen = Popen(cmd, stdout=PIPE, stderr=STDOUT)
|
||||
def quietRun( cmd ):
|
||||
"""Run a command, routing stderr to stdout, and return the output.
|
||||
cmd: list of command params"""
|
||||
if isinstance( cmd, str ):
|
||||
cmd = cmd.split( ' ' )
|
||||
popen = Popen( cmd, stdout=PIPE, stderr=STDOUT )
|
||||
# We can't use Popen.communicate() because it uses
|
||||
# select(), which can't handle
|
||||
# high file descriptor numbers! poll() can, however.
|
||||
output = ''
|
||||
readable = select.poll()
|
||||
readable.register(popen.stdout)
|
||||
readable.register( popen.stdout )
|
||||
while True:
|
||||
while readable.poll():
|
||||
data = popen.stdout.read(1024)
|
||||
if len(data) == 0:
|
||||
data = popen.stdout.read( 1024 )
|
||||
if len( data ) == 0:
|
||||
break
|
||||
output += data
|
||||
popen.poll()
|
||||
@@ -50,42 +41,6 @@ def quietRun(cmd):
|
||||
break
|
||||
return output
|
||||
|
||||
|
||||
def make_veth_pair(intf1, intf2):
|
||||
'''Create a veth pair connecting intf1 and intf2.
|
||||
|
||||
@param intf1 string, interface name
|
||||
@param intf2 string, interface name
|
||||
'''
|
||||
# Delete any old interfaces with the same names
|
||||
quietRun('ip link del ' + intf1)
|
||||
quietRun('ip link del ' + intf2)
|
||||
# Create new pair
|
||||
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
|
||||
#lg.info('running command: %s\n' % cmd)
|
||||
return checkRun(cmd)
|
||||
|
||||
|
||||
def move_intf(intf, node):
|
||||
'''Move interface to node.
|
||||
|
||||
@param intf string interface name
|
||||
@param node Node object
|
||||
|
||||
@return success boolean, did operation complete?
|
||||
'''
|
||||
cmd = 'ip link set ' + intf + ' netns ' + repr(node.pid)
|
||||
#lg.info('running command: %s\n' % cmd)
|
||||
quietRun(cmd)
|
||||
#lg.info(' output: %s\n' % output)
|
||||
links = node.cmd('ip link show')
|
||||
if not intf in links:
|
||||
lg.error('*** Error: move_intf: %s not successfully moved to %s:\n' %
|
||||
(intf, node.name))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Interface management
|
||||
#
|
||||
# Interfaces are managed as strings which are simply the
|
||||
@@ -99,116 +54,96 @@ def move_intf(intf, node):
|
||||
# live in the root namespace and thus do not have to be
|
||||
# explicitly moved.
|
||||
|
||||
|
||||
def makeIntfPair(intf1, intf2):
|
||||
'''Make a veth pair.
|
||||
|
||||
@param intf1 string, interface
|
||||
@param intf2 string, interface
|
||||
@return success boolean
|
||||
'''
|
||||
def makeIntfPair( intf1, intf2 ):
|
||||
"""Make a veth pair connecting intf1 and intf2.
|
||||
intf1: string, interface
|
||||
intf2: string, interface
|
||||
returns: success boolean"""
|
||||
# Delete any old interfaces with the same names
|
||||
quietRun('ip link del ' + intf1)
|
||||
quietRun('ip link del ' + intf2)
|
||||
quietRun( 'ip link del ' + intf1 )
|
||||
quietRun( 'ip link del ' + intf2 )
|
||||
# Create new pair
|
||||
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
|
||||
return checkRun(cmd)
|
||||
return checkRun( cmd )
|
||||
|
||||
def retry( retries, delaySecs, fn, *args, **keywords ):
|
||||
"""Try something several times before giving up.
|
||||
n: number of times to retry
|
||||
delaySecs: wait this long between tries
|
||||
fn: function to call
|
||||
args: args to apply to function call"""
|
||||
tries = 0
|
||||
while not fn( *args, **keywords ) and tries < retries:
|
||||
sleep( delaySecs )
|
||||
tries += 1
|
||||
if tries >= retries:
|
||||
lg.error( "*** gave up after %i retries\n" % tries )
|
||||
exit( 1 )
|
||||
|
||||
def moveIntf(intf, node, print_error = False):
|
||||
'''Move interface to node.
|
||||
|
||||
@param intf string, interface
|
||||
@param node Node object
|
||||
@param print_error if true, print error
|
||||
'''
|
||||
cmd = 'ip link set ' + intf + ' netns ' + repr(node.pid)
|
||||
quietRun(cmd)
|
||||
links = node.cmd('ip link show')
|
||||
def moveIntfNoRetry( intf, node, printError=False ):
|
||||
"""Move interface to node, without retrying.
|
||||
intf: string, interface
|
||||
node: Node object
|
||||
printError: if true, print error"""
|
||||
cmd = 'ip link set ' + intf + ' netns ' + repr( node.pid )
|
||||
quietRun( cmd )
|
||||
links = node.cmd( 'ip link show' )
|
||||
if not intf in links:
|
||||
if print_error:
|
||||
lg.error('*** Error: moveIntf: % not successfully moved to %s:\n' %
|
||||
(intf, node.name))
|
||||
if printError:
|
||||
lg.error( '*** Error: moveIntf: ' + intf +
|
||||
' not successfully moved to ' + node.name + '\n' )
|
||||
return False
|
||||
return True
|
||||
|
||||
def moveIntf( intf, node, printError=False, retries=3, delaySecs=0.001 ):
|
||||
"""Move interface to node, retrying on failure.
|
||||
intf: string, interface
|
||||
node: Node object
|
||||
printError: if true, print error"""
|
||||
retry( retries, delaySecs, moveIntf, intf, node, printError )
|
||||
|
||||
def retry(n, retry_delay, fn, *args, **keywords):
|
||||
'''Try something N times before giving up.
|
||||
|
||||
@param n number of times to retry
|
||||
@param retry_delay seconds wait this long between tries
|
||||
@param fn function to call
|
||||
@param args args to apply to function call
|
||||
'''
|
||||
tries = 0
|
||||
while not fn(*args, **keywords) and tries < n:
|
||||
sleep(retry_delay)
|
||||
tries += 1
|
||||
if tries >= n:
|
||||
lg.error("*** gave up after %i retries\n" % tries)
|
||||
exit(1)
|
||||
|
||||
|
||||
# delay between interface move checks in seconds
|
||||
MOVEINTF_DELAY = 0.0001
|
||||
|
||||
CREATE_LINK_RETRIES = 10
|
||||
|
||||
|
||||
def createLink(node1, node2):
|
||||
'''Create a link between nodes, making an interface for each.
|
||||
|
||||
@param node1 Node object
|
||||
@param node2 Node object
|
||||
'''
|
||||
def createLink( node1, node2, retries=10, delaySecs=0.001 ):
|
||||
"""Create a link between nodes, making an interface for each.
|
||||
node1: Node object
|
||||
node2: Node object"""
|
||||
intf1 = node1.newIntf()
|
||||
intf2 = node2.newIntf()
|
||||
makeIntfPair(intf1, intf2)
|
||||
makeIntfPair( intf1, intf2 )
|
||||
if node1.inNamespace:
|
||||
retry(CREATE_LINK_RETRIES, MOVEINTF_DELAY, moveIntf, intf1, node1)
|
||||
retry( retries, delaySecs, moveIntf, intf1, node1 )
|
||||
if node2.inNamespace:
|
||||
retry(CREATE_LINK_RETRIES, MOVEINTF_DELAY, moveIntf, intf2, node2)
|
||||
node1.connection[intf1] = (node2, intf2)
|
||||
node2.connection[intf2] = (node1, intf1)
|
||||
retry( retries, delaySecs, moveIntf, intf2, node2 )
|
||||
node1.connection[ intf1 ] = ( node2, intf2 )
|
||||
node2.connection[ intf2 ] = ( node1, intf1 )
|
||||
return intf1, intf2
|
||||
|
||||
|
||||
def fixLimits():
|
||||
'''Fix ridiculously small resource limits.'''
|
||||
setrlimit(RLIMIT_NPROC, (4096, 8192))
|
||||
setrlimit(RLIMIT_NOFILE, (16384, 32768))
|
||||
"Fix ridiculously small resource limits."
|
||||
setrlimit( RLIMIT_NPROC, ( 4096, 8192 ) )
|
||||
setrlimit( RLIMIT_NOFILE, ( 16384, 32768 ) )
|
||||
|
||||
|
||||
def _colonHex(val, bytes):
|
||||
'''Generate colon-hex string.
|
||||
|
||||
@param val input as unsigned int
|
||||
@param bytes number of bytes to convert
|
||||
@return ch_str colon-hex string
|
||||
'''
|
||||
def _colonHex( val, bytes ):
|
||||
"""Generate colon-hex string.
|
||||
val: input as unsigned int
|
||||
bytes: number of bytes to convert
|
||||
returns: chStr colon-hex string"""
|
||||
pieces = []
|
||||
for i in range(bytes - 1, -1, -1):
|
||||
pieces.append('%02x' % (((0xff << (i * 8)) & val) >> (i * 8)))
|
||||
ch_str = ':'.join(pieces)
|
||||
return ch_str
|
||||
for i in range( bytes - 1, -1, -1 ):
|
||||
piece = ( ( 0xff << ( i * 8 ) ) & val ) >> ( i * 8 )
|
||||
pieces.append( '%02x' % piece )
|
||||
chStr = ':'.join( pieces )
|
||||
return chStr
|
||||
|
||||
def macColonHex( mac ):
|
||||
"""Generate MAC colon-hex string from unsigned int.
|
||||
mac: MAC address as unsigned int
|
||||
returns: macStr MAC colon-hex string"""
|
||||
return _colonHex( mac, 6 )
|
||||
|
||||
def macColonHex(mac):
|
||||
'''Generate MAC colon-hex string from unsigned int.
|
||||
|
||||
@param mac MAC address as unsigned int
|
||||
@return mac_str MAC colon-hex string
|
||||
'''
|
||||
return _colonHex(mac, 6)
|
||||
|
||||
|
||||
def ipStr(ip):
|
||||
'''Generate IP address string
|
||||
|
||||
@return ip addr string
|
||||
'''
|
||||
hi = (ip & 0xff0000) >> 16
|
||||
mid = (ip & 0xff00) >> 8
|
||||
def ipStr( ip ):
|
||||
"""Generate IP address string
|
||||
returns: ip addr string"""
|
||||
hi = ( ip & 0xff0000 ) >> 16
|
||||
mid = ( ip & 0xff00 ) >> 8
|
||||
lo = ip & 0xff
|
||||
return "10.%i.%i.%i" % (hi, mid, lo)
|
||||
return "10.%i.%i.%i" % ( hi, mid, lo )
|
||||
|
||||
Reference in New Issue
Block a user