Fixing pylint errors

This commit is contained in:
Bob Lantz
2014-12-02 23:00:50 -08:00
parent db45b7c644
commit b1ec912db5
11 changed files with 160 additions and 103 deletions
+4 -4
View File
@@ -87,7 +87,7 @@ from signal import signal, SIGINT, SIG_IGN
from subprocess import Popen, PIPE, STDOUT from subprocess import Popen, PIPE, STDOUT
import os import os
from random import randrange from random import randrange
from sys import exit import sys
import re import re
from distutils.version import StrictVersion from distutils.version import StrictVersion
@@ -282,7 +282,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
cls = type( self ) cls = type( self )
if self.server not in cls.OVSVersions: if self.server not in cls.OVSVersions:
vers = self.cmd( 'ovs-vsctl --version' ) vers = self.cmd( 'ovs-vsctl --version' )
cls.OVSVersions[ self.server ] = re.findall( '\d+\.\d+', vers )[ 0 ] cls.OVSVersions[ self.server ] = re.findall( r'\d+\.\d+', vers )[ 0 ]
return ( StrictVersion( cls.OVSVersions[ self.server ] ) < return ( StrictVersion( cls.OVSVersions[ self.server ] ) <
StrictVersion( '1.10' ) ) StrictVersion( '1.10' ) )
@@ -387,7 +387,7 @@ class RemoteLink( Link ):
tunnel.wait() tunnel.wait()
error( ch + tunnel.stdout.read() ) error( ch + tunnel.stdout.read() )
error( tunnel.stderr.read() ) error( tunnel.stderr.read() )
exit( 1 ) sys.exit( 1 )
# 3. Move interfaces if necessary # 3. Move interfaces if necessary
for node in node1, node2: for node in node1, node2:
if node.inNamespace: if node.inNamespace:
@@ -660,7 +660,7 @@ class MininetCluster( Mininet ):
'*** Make sure that the above ssh command works correctly.\n' '*** Make sure that the above ssh command works correctly.\n'
'*** You may also need to run mn -c on all nodes, and/or\n' '*** You may also need to run mn -c on all nodes, and/or\n'
'*** use sudo -E.\n' ) '*** use sudo -E.\n' )
exit( 1 ) sys.exit( 1 )
info( '\n' ) info( '\n' )
def modifiedaddHost( self, *args, **kwargs ): def modifiedaddHost( self, *args, **kwargs ):
+5 -4
View File
@@ -10,7 +10,8 @@ It may also get rid of 'false positives', but hopefully
nothing irreplaceable! nothing irreplaceable!
""" """
from subprocess import Popen, PIPE, check_output as co from subprocess import ( Popen, PIPE, check_output as co,
CalledProcessError )
import time import time
from mininet.log import info from mininet.log import info
@@ -28,11 +29,11 @@ def killprocs( pattern ):
# Make sure they are gone # Make sure they are gone
while True: while True:
try: try:
pids = co( 'pgrep -f %s' % pattern ) pids = co( [ 'pgrep', '-f', pattern ] )
except: except CalledProcessError:
pids = '' pids = ''
if pids: if pids:
sh( 'pkill -f 9 mininet:' ) sh( 'pkill -9 -f %s' % pattern )
time.sleep( .5 ) time.sleep( .5 )
else: else:
break break
+9 -8
View File
@@ -96,7 +96,7 @@ class CLI( Cmd ):
# Disable pylint "Unused argument: 'arg's'" messages, as well as # Disable pylint "Unused argument: 'arg's'" messages, as well as
# "method could be a function" warning, since each CLI function # "method could be a function" warning, since each CLI function
# must have the same interface # must have the same interface
# pylint: disable-msg=R0201 # pylint: disable=R0201
helpStr = ( helpStr = (
'You may also send a command to a node using:\n' 'You may also send a command to a node using:\n'
@@ -128,7 +128,7 @@ class CLI( Cmd ):
nodes = ' '.join( sorted( self.mn ) ) nodes = ' '.join( sorted( self.mn ) )
output( 'available nodes are: \n%s\n' % nodes ) output( 'available nodes are: \n%s\n' % nodes )
def do_ports( self, line ): def do_ports( self, _line ):
"display ports and interfaces for each switch" "display ports and interfaces for each switch"
dumpPorts( self.mn.switches ) dumpPorts( self.mn.switches )
@@ -142,7 +142,7 @@ class CLI( Cmd ):
call( line, shell=True ) call( line, shell=True )
# do_py() and do_px() need to catch any exception during eval()/exec() # do_py() and do_px() need to catch any exception during eval()/exec()
# pylint: disable-msg=W0703 # pylint: disable=W0703
def do_py( self, line ): def do_py( self, line ):
"""Evaluate a Python expression. """Evaluate a Python expression.
@@ -159,7 +159,7 @@ class CLI( Cmd ):
output( str( e ) + '\n' ) output( str( e ) + '\n' )
# We are in fact using the exec() pseudo-function # We are in fact using the exec() pseudo-function
# pylint: disable-msg=W0122 # pylint: disable=W0122
def do_px( self, line ): def do_px( self, line ):
"""Execute a Python statement. """Execute a Python statement.
@@ -169,7 +169,7 @@ class CLI( Cmd ):
except Exception, e: except Exception, e:
output( str( e ) + '\n' ) output( str( e ) + '\n' )
# pylint: enable-msg=W0703,W0122 # pylint: enable=W0703,W0122
def do_pingall( self, line ): def do_pingall( self, line ):
"Ping between all hosts." "Ping between all hosts."
@@ -346,7 +346,7 @@ class CLI( Cmd ):
elapsed = time.time() - start elapsed = time.time() - start
self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed) self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
def do_links( self, line ): def do_links( self, _line ):
"Report on links" "Report on links"
for link in self.mn.links: for link in self.mn.links:
print link, link.status() print link, link.status()
@@ -355,7 +355,8 @@ class CLI( Cmd ):
"Starts or stops a switch" "Starts or stops a switch"
args = line.split() args = line.split()
if len(args) != 2: if len(args) != 2:
error( 'invalid number of args: switch <switch name> {start, stop}\n' ) error( 'invalid number of args: switch <switch name>'
'{start, stop}\n' )
return return
sw = args[ 0 ] sw = args[ 0 ]
command = args[ 1 ] command = args[ 1 ]
@@ -397,7 +398,7 @@ class CLI( Cmd ):
else: else:
error( '*** Unknown command: %s\n' % line ) error( '*** Unknown command: %s\n' % line )
# pylint: enable-msg=R0201 # pylint: enable=R0201
def waitForNode( self, node ): def waitForNode( self, node ):
"Wait for a node to finish, and print its output." "Wait for a node to finish, and print its output."
+9 -4
View File
@@ -33,7 +33,7 @@ class Intf( object ):
"Basic interface object that can configure itself." "Basic interface object that can configure itself."
def __init__( self, name, node=None, port=None, link=None, def __init__( self, name, node=None, port=None, link=None,
mac=None, srcNode=None, **params ): mac=None, **params ):
"""name: interface name (e.g. h1-eth0) """name: interface name (e.g. h1-eth0)
node: owning node (where this intf most likely lives) node: owning node (where this intf most likely lives)
link: parent link if we're part of a link link: parent link if we're part of a link
@@ -71,7 +71,8 @@ class Intf( object ):
return self.ifconfig( ipstr, 'up' ) return self.ifconfig( ipstr, 'up' )
else: else:
if prefixLen is None: if prefixLen is None:
raise Exception( 'No prefix length set for IP address %s' % ( ipstr, ) ) raise Exception( 'No prefix length set for IP address %s'
% ( ipstr, ) )
self.ip, self.prefixLen = ipstr, prefixLen self.ip, self.prefixLen = ipstr, prefixLen
return self.ifconfig( '%s/%s' % ( ipstr, prefixLen ) ) return self.ifconfig( '%s/%s' % ( ipstr, prefixLen ) )
@@ -196,7 +197,7 @@ class Intf( object ):
def status( self ): def status( self ):
"Return intf status as a string" "Return intf status as a string"
links, err_, result_ = self.node.pexec( 'ip link show' ) links, _err, _result = self.node.pexec( 'ip link show' )
if self.name in links: if self.name in links:
return "OK" return "OK"
else: else:
@@ -419,15 +420,19 @@ class Link( object ):
def intfName( self, node, n ): def intfName( self, node, n ):
"Construct a canonical interface name node-ethN for interface n." "Construct a canonical interface name node-ethN for interface n."
# Leave this as an instance method for now
assert self
return node.name + '-eth' + repr( n ) return node.name + '-eth' + repr( n )
@classmethod @classmethod
def makeIntfPair( _cls, intfname1, intfname2, addr1=None, addr2=None ): def makeIntfPair( cls, intfname1, intfname2, addr1=None, addr2=None ):
"""Create pair of interfaces """Create pair of interfaces
intfname1: name of interface 1 intfname1: name of interface 1
intfname2: name of interface 2 intfname2: name of interface 2
(override this method [and possibly delete()] (override this method [and possibly delete()]
to change link type)""" to change link type)"""
# Leave this as a class method for now
assert cls
return makeIntfPair( intfname1, intfname2, addr1, addr2 ) return makeIntfPair( intfname1, intfname2, addr1, addr2 )
def delete( self ): def delete( self ):
+2 -2
View File
@@ -124,7 +124,7 @@ class MininetLogger( Logger, object ):
self.setLevel( level ) self.setLevel( level )
self.handlers[ 0 ].setLevel( level ) self.handlers[ 0 ].setLevel( level )
# pylint: disable-msg=E0202 # pylint: disable=E0202
# "An attribute inherited from mininet.log hide this method" # "An attribute inherited from mininet.log hide this method"
# Not sure why this is occurring - this function definitely gets called. # Not sure why this is occurring - this function definitely gets called.
@@ -142,7 +142,7 @@ class MininetLogger( Logger, object ):
if self.isEnabledFor( OUTPUT ): if self.isEnabledFor( OUTPUT ):
self._log( OUTPUT, msg, args, kwargs ) self._log( OUTPUT, msg, args, kwargs )
# pylint: enable-msg=E0202 # pylint: enable=E0202
lg = MininetLogger() lg = MininetLogger()
+32 -17
View File
@@ -98,7 +98,8 @@ from math import ceil
from mininet.cli import CLI from mininet.cli import CLI
from mininet.log import info, error, debug, output, warn from mininet.log import info, error, debug, output, warn
from mininet.node import Host, OVSKernelSwitch, DefaultController, Controller from mininet.node import ( Node, Host, OVSKernelSwitch, DefaultController,
Controller )
from mininet.nodelib import NAT from mininet.nodelib import NAT
from mininet.link import Link, Intf from mininet.link import Link, Intf
from mininet.util import quietRun, fixLimits, numCores, ensureRoot from mininet.util import quietRun, fixLimits, numCores, ensureRoot
@@ -264,14 +265,24 @@ class Mininet( object ):
self.nameToNode[ name ] = controller_new self.nameToNode[ name ] = controller_new
return controller_new return controller_new
def addNAT( self, name='nat0', connect=True, inNamespace=False, **params ): def addNAT( self, name='nat0', connect=True, inNamespace=False,
**params):
"""Add a NAT to the Mininet network
name: name of NAT node
connect: switch to connect to | True (s1) | None
inNamespace: create in a network namespace
params: other NAT node params, notably:
ip: used as default gateway address"""
nat = self.addHost( name, cls=NAT, inNamespace=inNamespace, nat = self.addHost( name, cls=NAT, inNamespace=inNamespace,
subnet=self.ipBase, **params ) subnet=self.ipBase, **params )
# find first switch and create link # find first switch and create link
if connect: if connect:
# connect the nat to the first switch if not isinstance( connect, Node ):
# Use first switch if not specified
connect = self.switches[ 0 ]
# Connect the nat to the switch
self.addLink( nat, self.switches[ 0 ] ) self.addLink( nat, self.switches[ 0 ] )
# set the default route on hosts # Set the default route on hosts
natIP = nat.params[ 'ip' ].split('/')[ 0 ] natIP = nat.params[ 'ip' ].split('/')[ 0 ]
for host in self.hosts: for host in self.hosts:
if host.inNamespace: if host.inNamespace:
@@ -486,7 +497,8 @@ class Mininet( object ):
info( '*** Stopping %i terms\n' % len( self.terms ) ) info( '*** Stopping %i terms\n' % len( self.terms ) )
self.stopXterms() self.stopXterms()
info( '*** Stopping %i switches\n' % len( self.switches ) ) info( '*** Stopping %i switches\n' % len( self.switches ) )
for swclass, switches in groupby( sorted( self.switches, key=type ), type ): for swclass, switches in groupby(
sorted( self.switches, key=type ), type ):
if hasattr( swclass, 'batchShutdown' ): if hasattr( swclass, 'batchShutdown' ):
swclass.batchShutdown( switches ) swclass.batchShutdown( switches )
for switch in self.switches: for switch in self.switches:
@@ -521,13 +533,13 @@ class Mininet( object ):
if hosts is None: if hosts is None:
hosts = self.hosts hosts = self.hosts
poller = select.poll() poller = select.poll()
Node = hosts[ 0 ] # so we can call class method fdToNode h1 = hosts[ 0 ] # so we can call class method fdToNode
for host in hosts: for host in hosts:
poller.register( host.stdout ) poller.register( host.stdout )
while True: while True:
ready = poller.poll( timeoutms ) ready = poller.poll( timeoutms )
for fd, event in ready: for fd, event in ready:
host = Node.fdToNode( fd ) host = h1.fdToNode( fd )
if event & select.POLLIN: if event & select.POLLIN:
line = host.readline() line = host.readline()
if line is not None: if line is not None:
@@ -574,7 +586,8 @@ class Mininet( object ):
if timeout: if timeout:
opts = '-W %s' % timeout opts = '-W %s' % timeout
if dest.intfs: if dest.intfs:
result = node.cmd( 'ping -c1 %s %s' % (opts, dest.IP()) ) result = node.cmd( 'ping -c1 %s %s' %
(opts, dest.IP()) )
sent, received = self._parsePing( result ) sent, received = self._parsePing( result )
else: else:
sent, received = 0, 0 sent, received = 0, 0
@@ -699,13 +712,13 @@ class Mininet( object ):
# XXX This should be cleaned up # XXX This should be cleaned up
def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', format=None, def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', fmt=None,
seconds=5): seconds=5):
"""Run iperf between two hosts. """Run iperf between two hosts.
hosts: list of hosts; if None, uses opposite hosts hosts: list of hosts; if None, uses first and last hosts
l4Type: string, one of [ TCP, UDP ] l4Type: string, one of [ TCP, UDP ]
udpBw: bandwidth target for UDP test udpBw: bandwidth target for UDP test
format: iperf format argument if any fmt: iperf format argument if any
seconds: iperf time to transmit seconds: iperf time to transmit
returns: two-element array of [ server, client ] speeds returns: two-element array of [ server, client ] speeds
note: send() is buffered, so client rate can be much higher than note: send() is buffered, so client rate can be much higher than
@@ -729,8 +742,8 @@ class Mininet( object ):
bwArgs = '-b ' + udpBw + ' ' bwArgs = '-b ' + udpBw + ' '
elif l4Type != 'TCP': elif l4Type != 'TCP':
raise Exception( 'Unexpected l4 type: %s' % l4Type ) raise Exception( 'Unexpected l4 type: %s' % l4Type )
if format: if fmt:
iperfArgs += '-f %s ' %format iperfArgs += '-f %s ' % fmt
server.sendCmd( iperfArgs + '-s', printPid=True ) server.sendCmd( iperfArgs + '-s', printPid=True )
servout = '' servout = ''
while server.lastPid is None: while server.lastPid is None:
@@ -755,7 +768,7 @@ class Mininet( object ):
def runCpuLimitTest( self, cpu, duration=5 ): def runCpuLimitTest( self, cpu, duration=5 ):
"""run CPU limit test with 'while true' processes. """run CPU limit test with 'while true' processes.
cpu: desired CPU fraction of each host cpu: desired CPU fraction of each host
duration: test duration in seconds duration: test duration in seconds (integer)
returns a single list of measured CPU fractions as floats. returns a single list of measured CPU fractions as floats.
""" """
cores = int( quietRun( 'nproc' ) ) cores = int( quietRun( 'nproc' ) )
@@ -776,12 +789,14 @@ class Mininet( object ):
# get the initial cpu time for each host # get the initial cpu time for each host
for host in hosts: for host in hosts:
outputs[ host ] = [] outputs[ host ] = []
with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host, 'r' ) as f: with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' %
host, 'r' ) as f:
time[ host ] = float( f.read() ) time[ host ] = float( f.read() )
for _ in range( 5 ): for _ in range( duration ):
sleep( 1 ) sleep( 1 )
for host in hosts: for host in hosts:
with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host, 'r' ) as f: with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' %
host, 'r' ) as f:
readTime = float( f.read() ) readTime = float( f.read() )
outputs[ host ].append( ( ( readTime - time[ host ] ) outputs[ host ].append( ( ( readTime - time[ host ] )
/ 1000000000 ) / cores * 100 ) / 1000000000 ) / cores * 100 )
+43 -24
View File
@@ -189,6 +189,8 @@ class Node( object ):
"""Internal method: spawn and return a process """Internal method: spawn and return a process
cmd: command to run (list) cmd: command to run (list)
params: parameters to Popen()""" params: parameters to Popen()"""
# Leave this is as an instance method for now
assert self
return Popen( cmd, **params ) return Popen( cmd, **params )
def cleanup( self ): def cleanup( self ):
@@ -240,8 +242,11 @@ class Node( object ):
os.killpg( self.shell.pid, signal.SIGHUP ) os.killpg( self.shell.pid, signal.SIGHUP )
self.cleanup() self.cleanup()
def stop( self ): def stop( self, deleteIntfs=False ):
"Stop node." """Stop node.
deleteIntfs: delete interfaces? (False)"""
if deleteIntfs:
self.deleteIntfs()
self.terminate() self.terminate()
def waitReadable( self, timeoutms=None ): def waitReadable( self, timeoutms=None ):
@@ -324,7 +329,7 @@ class Node( object ):
log = info if verbose else debug log = info if verbose else debug
output = '' output = ''
while self.waiting: while self.waiting:
data = self.monitor() data = self.monitor( findPid=findPid )
output += data output += data
log( data ) log( data )
return output return output
@@ -421,7 +426,7 @@ class Node( object ):
warn( '*** defaultIntf: warning:', self.name, warn( '*** defaultIntf: warning:', self.name,
'has no interfaces\n' ) 'has no interfaces\n' )
def intf( self, intf='' ): def intf( self, intf=None ):
"""Return our interface object with given string name, """Return our interface object with given string name,
default intf if name is falsy (None, empty string, etc). default intf if name is falsy (None, empty string, etc).
or the input intf arg. or the input intf arg.
@@ -682,8 +687,8 @@ class CPULimitedHost( Host ):
if int( self.cgroupGet( 'rt_runtime_us', 'cpu' ) ) <= 0: if int( self.cgroupGet( 'rt_runtime_us', 'cpu' ) ) <= 0:
mncmd += [ '-r', str( self.rtprio ) ] mncmd += [ '-r', str( self.rtprio ) ]
else: else:
debug( '*** error: not enough cpu time available for %s.' % self.name, debug( '*** error: not enough cpu time available for %s.' %
'Using cfs scheduler for subprocess\n' ) self.name, 'Using cfs scheduler for subprocess\n' )
return Host.popen( self, *args, mncmd=mncmd, **kwargs ) return Host.popen( self, *args, mncmd=mncmd, **kwargs )
def cleanup( self ): def cleanup( self ):
@@ -698,9 +703,11 @@ class CPULimitedHost( Host ):
"Check (Ubuntu,Debian) kernel config for CONFIG_RT_GROUP_SCHED for RT" "Check (Ubuntu,Debian) kernel config for CONFIG_RT_GROUP_SCHED for RT"
if not cls._rtGroupSched: if not cls._rtGroupSched:
release = quietRun( 'uname -r' ).strip('\r\n') release = quietRun( 'uname -r' ).strip('\r\n')
output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s' % release ) output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s' %
release )
if output == '# CONFIG_RT_GROUP_SCHED is not set\n': if output == '# CONFIG_RT_GROUP_SCHED is not set\n':
error( '\n*** error: please enable RT_GROUP_SCHED in your kernel\n' ) error( '\n*** error: please enable RT_GROUP_SCHED'
'in your kernel\n' )
exit( 1 ) exit( 1 )
cls._rtGroupSched = True cls._rtGroupSched = True
@@ -755,8 +762,8 @@ class CPULimitedHost( Host ):
sched = self.sched sched = self.sched
if sched == 'rt': if sched == 'rt':
if not f or f < 0: if not f or f < 0:
raise Exception( 'Please set a positive CPU fraction for sched=rt\n' ) raise Exception( 'Please set a positive CPU fraction'
return ' for sched=rt\n' )
pstr, qstr, period, quota = self.rtInfo( f ) pstr, qstr, period, quota = self.rtInfo( f )
elif sched == 'cfs': elif sched == 'cfs':
pstr, qstr, period, quota = self.cfsInfo( f ) pstr, qstr, period, quota = self.cfsInfo( f )
@@ -881,7 +888,8 @@ class Switch( Node ):
def connected( self ): def connected( self ):
"Is the switch connected to a controller? (override this method)" "Is the switch connected to a controller? (override this method)"
return False and self # satisfy pylint raise NotImplementedError( "connected() needs to be implemented in"
" Switch subclass %s" % self.__class__ )
def __repr__( self ): def __repr__( self ):
"More informative string representation" "More informative string representation"
@@ -890,6 +898,7 @@ class Switch( Node ):
return '<%s %s: %s pid=%s> ' % ( return '<%s %s: %s pid=%s> ' % (
self.__class__.__name__, self.name, intfs, self.pid ) self.__class__.__name__, self.name, intfs, self.pid )
class UserSwitch( Switch ): class UserSwitch( Switch ):
"User-space switch." "User-space switch."
@@ -982,7 +991,8 @@ class UserSwitch( Switch ):
self.TCReapply( intf ) self.TCReapply( intf )
def stop( self, deleteIntfs=True ): def stop( self, deleteIntfs=True ):
"Stop OpenFlow reference user datapath." """Stop OpenFlow reference user datapath.
deleteIntfs: delete interfaces? (True)"""
self.cmd( 'kill %ofdatapath' ) self.cmd( 'kill %ofdatapath' )
self.cmd( 'kill %ofprotocol' ) self.cmd( 'kill %ofprotocol' )
if deleteIntfs: if deleteIntfs:
@@ -1033,7 +1043,8 @@ class OVSLegacyKernelSwitch( Switch ):
self.execed = False self.execed = False
def stop( self, deleteIntfs=True ): def stop( self, deleteIntfs=True ):
"Terminate kernel datapath." """Terminate kernel datapath."
deleteIntfs: delete interfaces? (True)"""
quietRun( 'ovs-dpctl del-dp ' + self.dp ) quietRun( 'ovs-dpctl del-dp ' + self.dp )
self.cmd( 'kill %ovs-openflowd' ) self.cmd( 'kill %ovs-openflowd' )
if deleteIntfs: if deleteIntfs:
@@ -1075,11 +1086,12 @@ class OVSSwitch( Switch ):
'You may wish to try ' 'You may wish to try '
'"service openvswitch-switch start".\n' ) '"service openvswitch-switch start".\n' )
exit( 1 ) exit( 1 )
info = quietRun( 'ovs-vsctl --version' ) version = quietRun( 'ovs-vsctl --version' )
cls.OVSVersion = findall( '\d+\.\d+', info )[ 0 ] cls.OVSVersion = findall( r'\d+\.\d+', version )[ 0 ]
@classmethod @classmethod
def isOldOVS( cls ): def isOldOVS( cls ):
"Is OVS ersion < 1.10?"
return ( StrictVersion( cls.OVSVersion ) < return ( StrictVersion( cls.OVSVersion ) <
StrictVersion( '1.10' ) ) StrictVersion( '1.10' ) )
@@ -1186,7 +1198,8 @@ class OVSSwitch( Switch ):
def stop( self, deleteIntfs=True ): def stop( self, deleteIntfs=True ):
"Terminate OVS switch." """Terminate OVS switch.
deleteIntfs: delete interfaces? (True)"""
self.cmd( 'ovs-vsctl del-br', self ) self.cmd( 'ovs-vsctl del-br', self )
if self.datapath == 'user': if self.datapath == 'user':
self.cmd( 'ip link del', self ) self.cmd( 'ip link del', self )
@@ -1255,7 +1268,8 @@ class IVSSwitch( Switch ):
self.cmd( ' '.join(args) + ' >' + logfile + ' 2>&1 </dev/null &' ) self.cmd( ' '.join(args) + ' >' + logfile + ' 2>&1 </dev/null &' )
def stop( self, deleteIntfs=True ): def stop( self, deleteIntfs=True ):
"Terminate IVS switch." """Terminate IVS switch.
deleteIntfs: delete interfaces? (True)"""
self.cmd( 'kill %ivs' ) self.cmd( 'kill %ivs' )
self.cmd( 'wait' ) self.cmd( 'wait' )
if deleteIntfs: if deleteIntfs:
@@ -1276,6 +1290,10 @@ class IVSSwitch( Switch ):
return self.cmd( 'ovs-ofctl ' + ' '.join( args ) + return self.cmd( 'ovs-ofctl ' + ' '.join( args ) +
' tcp:127.0.0.1:%i' % self.listenPort ) ' tcp:127.0.0.1:%i' % self.listenPort )
def connected( self ):
"For now, return True since we can't tell if we're connected"
return True
class Controller( Node ): class Controller( Node ):
"""A Controller is a Node that is running (or has execed?) an """A Controller is a Node that is running (or has execed?) an
@@ -1323,11 +1341,11 @@ class Controller( Node ):
' 1>' + cout + ' 2>' + cout + ' &' ) ' 1>' + cout + ' 2>' + cout + ' &' )
self.execed = False self.execed = False
def stop( self ): def stop( self, *args, **kwargs ):
"Stop controller." "Stop controller."
self.cmd( 'kill %' + self.command ) self.cmd( 'kill %' + self.command )
self.cmd( 'wait %' + self.command ) self.cmd( 'wait %' + self.command )
self.terminate() super( Controller, self ).stop( *args, **kwargs )
def IP( self, intf=None ): def IP( self, intf=None ):
"Return IP address of the Controller" "Return IP address of the Controller"
@@ -1343,7 +1361,8 @@ class Controller( Node ):
self.__class__.__name__, self.name, self.__class__.__name__, self.name,
self.IP(), self.port, self.pid ) self.IP(), self.port, self.pid )
@classmethod @classmethod
def isAvailable( self ): def isAvailable( cls ):
"Is controller available?"
return quietRun( 'which controller' ) return quietRun( 'which controller' )
class OVSController( Controller ): class OVSController( Controller ):
@@ -1353,8 +1372,9 @@ class OVSController( Controller ):
command = 'test-controller' command = 'test-controller'
Controller.__init__( self, name, command=command, **kwargs ) Controller.__init__( self, name, command=command, **kwargs )
@classmethod @classmethod
def isAvailable( self ): def isAvailable( cls ):
return quietRun( 'which ovs-controller' ) or quietRun( 'which test-controller' ) return ( quietRun( 'which ovs-controller' ) or
quietRun( 'which test-controller' ) )
class NOX( Controller ): class NOX( Controller ):
"Controller to run a NOX application." "Controller to run a NOX application."
@@ -1432,7 +1452,7 @@ class RemoteController( Controller ):
" at %s:%d\n" % ( self.ip, self.port ) ) " at %s:%d\n" % ( self.ip, self.port ) )
DefaultControllers = [ Controller, OVSController ] DefaultControllers = ( Controller, OVSController )
def findController( controllers=DefaultControllers ): def findController( controllers=DefaultControllers ):
"Return first available controller from list, if any" "Return first available controller from list, if any"
@@ -1446,4 +1466,3 @@ def DefaultController( name, controllers=DefaultControllers, **kwargs ):
if not controller: if not controller:
raise Exception( 'Could not find a default OpenFlow controller' ) raise Exception( 'Could not find a default OpenFlow controller' )
return controller( name, **kwargs ) return controller( name, **kwargs )
+22 -15
View File
@@ -33,7 +33,7 @@ class LinuxBridge( Switch ):
else: else:
return True return True
def start( self, controllers ): def start( self, _controllers ):
"Start Linux bridge" "Start Linux bridge"
self.cmd( 'ifconfig', self, 'down' ) self.cmd( 'ifconfig', self, 'down' )
self.cmd( 'brctl delbr', self ) self.cmd( 'brctl delbr', self )
@@ -62,21 +62,22 @@ class LinuxBridge( Switch ):
class NAT( Node ): class NAT( Node ):
"""NAT: Provides connectivity to external network""" "NAT: Provides connectivity to external network"
def __init__( self, name, inetIntf=None, subnet='10.0/8', localIntf=None, **params):
super( NAT, self ).__init__( name, **params )
def __init__( self, name, inetIntf=None, subnet='10.0/8',
localIntf=None, **params):
"""Start NAT/forwarding between Mininet and external network """Start NAT/forwarding between Mininet and external network
inetIntf: interface for internet access inetIntf: interface for internet access
subnet: Mininet subnet (default 10.0/8)=""" subnet: Mininet subnet (default 10.0/8)="""
super( NAT, self ).__init__( name, **params )
self.inetIntf = inetIntf if inetIntf else self.getGatewayIntf() self.inetIntf = inetIntf if inetIntf else self.getGatewayIntf()
self.subnet = subnet self.subnet = subnet
self.localIntf = localIntf self.localIntf = localIntf
def config( self, **params ): def config( self, **params ):
super( NAT, self).config( **params )
"""Configure the NAT and iptables""" """Configure the NAT and iptables"""
super( NAT, self).config( **params )
if not self.localIntf: if not self.localIntf:
self.localIntf = self.defaultIntf() self.localIntf = self.defaultIntf()
@@ -94,10 +95,14 @@ class NAT( Node ):
self.cmd( 'iptables -P FORWARD DROP' ) self.cmd( 'iptables -P FORWARD DROP' )
# Configure NAT # Configure NAT
self.cmd( 'iptables -I FORWARD -i', self.localIntf, '-d', self.subnet, '-j DROP' ) self.cmd( 'iptables -I FORWARD',
self.cmd( 'iptables -A FORWARD -i', self.localIntf, '-s', self.subnet, '-j ACCEPT' ) '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
self.cmd( 'iptables -A FORWARD -i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' ) self.cmd( 'iptables -A FORWARD',
self.cmd( 'iptables -t nat -A POSTROUTING -o ', self.inetIntf, '-s', self.subnet, '-j MASQUERADE' ) '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
self.cmd( 'iptables -A FORWARD',
'-i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' )
self.cmd( 'iptables -t nat -A POSTROUTING',
'-o', self.inetIntf, '-s', self.subnet, '-j MASQUERADE' )
# Instruct the kernel to perform forwarding # Instruct the kernel to perform forwarding
self.cmd( 'sysctl net.ipv4.ip_forward=1' ) self.cmd( 'sysctl net.ipv4.ip_forward=1' )
@@ -116,14 +121,17 @@ class NAT( Node ):
# hopefully this won't disconnect you # hopefully this won't disconnect you
self.cmd( 'service network-manager restart' ) self.cmd( 'service network-manager restart' )
def getGatewayIntf( self ): def getGatewayIntf( self, fallback='eth0' ):
"""Return gateway interface name
fallback: default device to fall back to"""
routes = self.cmd( 'ip route show' ) routes = self.cmd( 'ip route show' )
match = re.search('default via \S+ dev (\S+)', routes ) match = re.search( r'default via \S+ dev (\S+)', routes )
if match: if match:
return match.group( 1 ) return match.group( 1 )
else: else:
warn( 'There is no default route set. Using eth0 as gateway interface...\n' ) warn( 'There is no default route set.',
return 'eth0' 'Using', fallback, 'as gateway interface...\n' )
return fallback
def terminate( self ): def terminate( self ):
"""Stop NAT/forwarding between Mininet and external network""" """Stop NAT/forwarding between Mininet and external network"""
@@ -136,4 +144,3 @@ class NAT( Node ):
self.cmd( 'sysctl net.ipv4.ip_forward=0' ) self.cmd( 'sysctl net.ipv4.ip_forward=0' )
super( NAT, self ).terminate() super( NAT, self ).terminate()
+11 -5
View File
@@ -111,7 +111,8 @@ class Topo( object ):
self.hopts = params.pop( 'hopts', {} ) self.hopts = params.pop( 'hopts', {} )
self.sopts = params.pop( 'sopts', {} ) self.sopts = params.pop( 'sopts', {} )
self.lopts = params.pop( 'lopts', {} ) self.lopts = params.pop( 'lopts', {} )
self.ports = {} # ports[src][dst][sport] is port on dst that connects to src # ports[src][dst][sport] is port on dst that connects to src
self.ports = {}
self.build( *args, **params ) self.build( *args, **params )
def build( self, *args, **params ): def build( self, *args, **params ):
@@ -187,7 +188,7 @@ class Topo( object ):
withKeys: return link keys withKeys: return link keys
withInfo: return link info withInfo: return link info
returns: list of ( src, dst [,key, info ] )""" returns: list of ( src, dst [,key, info ] )"""
for src, dst, key, info in self.g.edges_iter( data=True, keys=True ): for _src, _dst, key, info in self.g.edges_iter( data=True, keys=True ):
node1, node2 = info[ 'node1' ], info[ 'node2' ] node1, node2 = info[ 'node1' ], info[ 'node2' ]
if withKeys: if withKeys:
if withInfo: if withInfo:
@@ -207,7 +208,7 @@ class Topo( object ):
withInfo: return link info withInfo: return link info
returns: list of ( src, dst [,key, info ] )""" returns: list of ( src, dst [,key, info ] )"""
links = list( self.iterLinks( withKeys, withInfo ) ) links = list( self.iterLinks( withKeys, withInfo ) )
if not sorted: if not sort:
return links return links
# Ignore info when sorting # Ignore info when sorting
tupleSize = 3 if withKeys else 2 tupleSize = 3 if withKeys else 2
@@ -287,10 +288,13 @@ class Topo( object ):
return sorted( items, key=natural ) return sorted( items, key=natural )
# Our idiom defines additional parameters in build(param...)
# pylint: disable=arguments-differ, attribute-defined-outside-init
class SingleSwitchTopo( Topo ): class SingleSwitchTopo( Topo ):
"Single switch connected to k hosts." "Single switch connected to k hosts."
def build( self, k=2, **opts ): def build( self, k=2, **_opts ):
"k: number of hosts" "k: number of hosts"
self.k = k self.k = k
switch = self.addSwitch( 's1' ) switch = self.addSwitch( 's1' )
@@ -317,7 +321,7 @@ class SingleSwitchReversedTopo( Topo ):
class LinearTopo( Topo ): class LinearTopo( Topo ):
"Linear topology of k switches, with n hosts per switch." "Linear topology of k switches, with n hosts per switch."
def build( self, k=2, n=1, **opts): def build( self, k=2, n=1, **_opts):
"""k: number of switches """k: number of switches
n: number of hosts per switch""" n: number of hosts per switch"""
self.k = k self.k = k
@@ -340,3 +344,5 @@ class LinearTopo( Topo ):
if lastSwitch: if lastSwitch:
self.addLink( switch, lastSwitch ) self.addLink( switch, lastSwitch )
lastSwitch = switch lastSwitch = switch
# pylint: enable=arguments-differ, attribute-defined-outside-init
+6 -3
View File
@@ -3,6 +3,9 @@
from mininet.topo import Topo from mininet.topo import Topo
from mininet.net import Mininet from mininet.net import Mininet
# The build() method is expected to do both of these things:
# pylint: disable=attribute-defined-outside-init, arguments-differ
class TreeTopo( Topo ): class TreeTopo( Topo ):
"Topology for a tree network with a given depth and fanout." "Topology for a tree network with a given depth and fanout."
@@ -53,7 +56,8 @@ class TorusTopo( Topo ):
loc = '%dx%d' % ( i + 1, j + 1 ) loc = '%dx%d' % ( i + 1, j + 1 )
# dpid cannot be zero for OVS # dpid cannot be zero for OVS
dpid = ( i + 1 ) * 256 + ( j + 1 ) dpid = ( i + 1 ) * 256 + ( j + 1 )
switch = switches[ i, j ] = self.addSwitch( 's' + loc, dpid='%016x' % dpid ) switch = switches[ i, j ] = self.addSwitch(
's' + loc, dpid='%016x' % dpid )
host = hosts[ i, j ] = self.addHost( 'h' + loc ) host = hosts[ i, j ] = self.addHost( 'h' + loc )
self.addLink( host, switch ) self.addLink( host, switch )
# Connect switches # Connect switches
@@ -65,5 +69,4 @@ class TorusTopo( Topo ):
self.addLink( sw1, sw2 ) self.addLink( sw1, sw2 )
self.addLink( sw1, sw3 ) self.addLink( sw1, sw3 )
# pylint: enable=attribute-defined-outside-init, arguments-differ
+14 -14
View File
@@ -25,7 +25,7 @@ def checkRun( cmd ):
return check_call( cmd.split( ' ' ) ) return check_call( cmd.split( ' ' ) )
# pylint doesn't understand explicit type checking # pylint doesn't understand explicit type checking
# pylint: disable-msg=E1103 # pylint: disable=E1103
def oldQuietRun( *cmd ): def oldQuietRun( *cmd ):
"""Run a command, routing stderr to stdout, and return the output. """Run a command, routing stderr to stdout, and return the output.
@@ -119,8 +119,8 @@ def quietRun( cmd, **kwargs ):
"Run a command and return merged stdout and stderr" "Run a command and return merged stdout and stderr"
return errRun( cmd, stderr=STDOUT, **kwargs )[ 0 ] return errRun( cmd, stderr=STDOUT, **kwargs )[ 0 ]
# pylint: enable-msg=E1103 # pylint: enable=E1103
# pylint: disable-msg=E1101 # pylint: disable=E1101
def isShellBuiltin( cmd ): def isShellBuiltin( cmd ):
"Return True if cmd is a bash builtin." "Return True if cmd is a bash builtin."
@@ -133,7 +133,7 @@ def isShellBuiltin( cmd ):
isShellBuiltin.builtIns = None isShellBuiltin.builtIns = None
# pylint: enable-msg=E1101 # pylint: enable=E1101
# Interface management # Interface management
# #
@@ -148,22 +148,22 @@ isShellBuiltin.builtIns = None
# live in the root namespace and thus do not have to be # live in the root namespace and thus do not have to be
# explicitly moved. # explicitly moved.
def makeIntfPair( intf1, intf2, addr1=None, addr2=None, run=quietRun ): def makeIntfPair( intf1, intf2, addr1=None, addr2=None, runCmd=quietRun ):
"""Make a veth pair connecting intf1 and intf2. """Make a veth pair connecting intf1 and intf2.
intf1: string, interface intf1: string, interface
intf2: string, interface intf2: string, interface
node: node to run on or None (default) runCmd: function to run shell commands (quietRun)
returns: ip link add result""" returns: ip link add result"""
# Delete any old interfaces with the same names # Delete any old interfaces with the same names
run( 'ip link del ' + intf1 ) runCmd( 'ip link del ' + intf1 )
run( 'ip link del ' + intf2 ) runCmd( 'ip link del ' + intf2 )
# Create new pair # Create new pair
if addr1 is None and addr2 is None: if addr1 is None and addr2 is None:
cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2 cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
else: else:
cmd = ( 'ip link add name ' + intf1 + ' address ' + addr1 + cmd = ( 'ip link add name ' + intf1 + ' address ' + addr1 +
' type veth peer name ' + intf2 + ' address ' + addr2 ) ' type veth peer name ' + intf2 + ' address ' + addr2 )
cmdOutput = run( cmd ) cmdOutput = runCmd( cmd )
if cmdOutput == '': if cmdOutput == '':
return True return True
else: else:
@@ -202,7 +202,7 @@ def moveIntfNoRetry( intf, dstNode, printError=False ):
return False return False
return True return True
def moveIntf( intf, dstNode, srcNode=None, printError=True, def moveIntf( intf, dstNode, printError=True,
retries=3, delaySecs=0.001 ): retries=3, delaySecs=0.001 ):
"""Move interface to node, retrying on failure. """Move interface to node, retrying on failure.
intf: string, interface intf: string, interface
@@ -296,7 +296,7 @@ def ipAdd( i, prefixLen=8, ipBaseNum=0x0a000000 ):
def ipParse( ip ): def ipParse( ip ):
"Parse an IP address and return an unsigned int." "Parse an IP address and return an unsigned int."
args = [ int( arg ) for arg in ip.split( '.' ) ] args = [ int( arg ) for arg in ip.split( '.' ) ]
while ( len(args) < 4 ): while len(args) < 4:
args.append( 0 ) args.append( 0 )
return ipNum( *args ) return ipNum( *args )
@@ -427,7 +427,7 @@ def fixLimits():
sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 ) sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 )
#Increase number of PTYs for nodes #Increase number of PTYs for nodes
sysctlTestAndSet( 'kernel.pty.max', 20000 ) sysctlTestAndSet( 'kernel.pty.max', 20000 )
except: except Exception:
warn( "*** Error setting resource limits. " warn( "*** Error setting resource limits. "
"Mininet's performance may be affected.\n" ) "Mininet's performance may be affected.\n" )
@@ -545,9 +545,9 @@ def ensureRoot():
def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ): def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ):
"""Wait until server is listening on port. """Wait until server is listening on port.
returns True if server is listening""" returns True if server is listening"""
run = ( client.cmd if client else runCmd = ( client.cmd if client else
partial( quietRun, shell=True ) ) partial( quietRun, shell=True ) )
if not run( 'which telnet' ): if not runCmd( 'which telnet' ):
raise Exception('Could not find telnet' ) raise Exception('Could not find telnet' )
serverIP = server if isinstance( server, basestring ) else server.IP() serverIP = server if isinstance( server, basestring ) else server.IP()
cmd = ( 'sh -c "echo A | telnet -e A %s %s"' % cmd = ( 'sh -c "echo A | telnet -e A %s %s"' %