Pass code check with pylint=2.4.4 (#1012)

This commit is contained in:
lantz
2021-01-25 14:00:53 -08:00
committed by GitHub
parent 77938e0a85
commit dad451bf8f
56 changed files with 330 additions and 182 deletions
+22
View File
@@ -0,0 +1,22 @@
name: code-check
on: [push, pull_request]
jobs:
code-check:
name: Mininet Code Check
runs-on: ubuntu-latest
steps:
- name: Set up Python 3.x
uses: actions/setup-python@v2
with:
python-version: 3.x
- name: Check out Mininet source
uses: actions/checkout@v2
- name: Install Mininet code check dependencies
run: |
PYTHON=`which python` util/install.sh -n
python -m pip install pylint==2.4.4
- name: Run code check
run: make codecheck
-3
View File
@@ -24,9 +24,6 @@ jobs:
# This seems too slow unfortunately: # This seems too slow unfortunately:
# sudo apt-get upgrade -y -qq # sudo apt-get upgrade -y -qq
PYTHON=`which python` util/install.sh -nv PYTHON=`which python` util/install.sh -nv
- name: Run code check (skipping for now)
run: |
bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi"
- name: Sanity test - name: Sanity test
run: | run: |
export sudo="sudo env PATH=$PATH" export sudo="sudo env PATH=$PATH"
+8 -2
View File
@@ -41,10 +41,16 @@ load-plugins=
# can either give multiple identifier separated by comma (,) or put this option # can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where # multiple time (only on the command line, not in the configuration file where
# it should appear only once). # it should appear only once).
#
# Note: we may want to re-enable some of these at some point, but many of them
# are just style issues rather than errors.
#
disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args, disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args,
too-many-instance-attributes, too-few-public-methods, too-many-arguments, too-many-instance-attributes, too-few-public-methods,
too-many-locals, too-many-public-methods, duplicate-code, bad-whitespace, too-many-locals, too-many-public-methods, duplicate-code, bad-whitespace,
locally-disabled, locally-enabled locally-disabled, locally-enabled, bad-continuation,
useless-object-inheritance, unnecessary-pass, no-else-return,
no-else-raise, no-else-continue, super-with-arguments
# bad-continuation, wrong-import-order # bad-continuation, wrong-import-order
+4 -7
View File
@@ -3,20 +3,17 @@ sudo: required
matrix: matrix:
include: include:
- dist: trusty - dist: focal
python: 2.7
env: dist="14.04 LTS trusty"
- dist: trusty
python: 3.6 python: 3.6
env: dist="14.04 LTS trusty" env: dist="24.04 LTS focal"
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq vlan - sudo apt-get install -qq vlan pyflakes
- PYTHON=`which python` util/install.sh -n - PYTHON=`which python` util/install.sh -n
install: install:
- bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi" - make codecheck
- pip install pexpect || pip3 install pexpect - pip install pexpect || pip3 install pexpect
- util/install.sh -nfvw - util/install.sh -nfvw
+1 -1
View File
@@ -8,7 +8,7 @@ BIN = $(MN)
PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN) PYSRC = $(MININET) $(TEST) $(EXAMPLES) $(BIN)
MNEXEC = mnexec MNEXEC = mnexec
MANPAGES = mn.1 mnexec.1 MANPAGES = mn.1 mnexec.1
P8IGN = E251,E201,E302,E202,E126,E127,E203,E226 P8IGN = E251,E201,E302,E202,E126,E127,E203,E226,E402,W504,W503,E731
PREFIX ?= /usr PREFIX ?= /usr
BINDIR ?= $(PREFIX)/bin BINDIR ?= $(PREFIX)/bin
MANDIR ?= $(PREFIX)/share/man/man1 MANDIR ?= $(PREFIX)/share/man/man1
+10 -6
View File
@@ -11,15 +11,20 @@ Example to pull custom params (topo, switch, etc.) from a file:
sudo mn --custom ~/mininet/custom/custom_example.py sudo mn --custom ~/mininet/custom/custom_example.py
""" """
from optparse import OptionParser
import os import os
import sys import sys
import time import time
from functools import partial
from optparse import OptionParser # pylint: disable=deprecated-module
from sys import exit # pylint: disable=redefined-builtin
# Fix setuptools' evil madness, and open up (more?) security holes # Fix setuptools' evil madness, and open up (more?) security holes
if 'PYTHONPATH' in os.environ: if 'PYTHONPATH' in os.environ:
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
# pylint: disable=wrong-import-position
from mininet.clean import cleanup from mininet.clean import cleanup
import mininet.cli import mininet.cli
from mininet.log import lg, LEVELS, info, debug, warn, error, output from mininet.log import lg, LEVELS, info, debug, warn, error, output
@@ -34,10 +39,7 @@ from mininet.link import Link, TCLink, TCULink, OVSLink
from mininet.topo import ( SingleSwitchTopo, LinearTopo, from mininet.topo import ( SingleSwitchTopo, LinearTopo,
SingleSwitchReversedTopo, MinimalTopo ) SingleSwitchReversedTopo, MinimalTopo )
from mininet.topolib import TreeTopo, TorusTopo from mininet.topolib import TreeTopo, TorusTopo
from mininet.util import customClass, specialClass, splitArgs from mininet.util import customClass, specialClass, splitArgs, buildTopo
from mininet.util import buildTopo
from functools import partial
# Experimental! cluster edition prototype # Experimental! cluster edition prototype
from mininet.examples.cluster import ( MininetCluster, RemoteHost, from mininet.examples.cluster import ( MininetCluster, RemoteHost,
@@ -46,6 +48,7 @@ from mininet.examples.cluster import ( MininetCluster, RemoteHost,
ClusterCleanup ) ClusterCleanup )
from mininet.examples.clustercli import ClusterCLI from mininet.examples.clustercli import ClusterCLI
PLACEMENT = { 'block': SwitchBinPlacer, 'random': RandomPlacer } PLACEMENT = { 'block': SwitchBinPlacer, 'random': RandomPlacer }
# built in topologies, created only when run # built in topologies, created only when run
@@ -107,6 +110,7 @@ def nullTest( _net ):
"Null 'test' (does nothing)" "Null 'test' (does nothing)"
pass pass
TESTS.update( all=allTest, none=nullTest, build=nullTest ) TESTS.update( all=allTest, none=nullTest, build=nullTest )
# Map to alternate spellings of Mininet() methods # Map to alternate spellings of Mininet() methods
@@ -425,7 +429,7 @@ if __name__ == "__main__":
except KeyboardInterrupt: except KeyboardInterrupt:
info( "\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n") info( "\n\nKeyboard Interrupt. Shutting down and cleaning up...\n\n")
cleanup() cleanup()
except Exception: except Exception: # pylint: disable=broad-except
# Print exception # Print exception
type_, val_, trace_ = sys.exc_info() type_, val_, trace_ = sys.exc_info()
errorMsg = ( "-"*80 + "\n" + errorMsg = ( "-"*80 + "\n" +
+3 -2
View File
@@ -34,14 +34,14 @@ and '/var/run'. It also has a temporary private directory mounted
on '/var/mn' on '/var/mn'
""" """
from functools import partial
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import Host from mininet.node import Host
from mininet.cli import CLI from mininet.cli import CLI
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from functools import partial
# Sample usage # Sample usage
@@ -61,6 +61,7 @@ def testHostWithPrivateDirs():
CLI( net ) CLI( net )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
testHostWithPrivateDirs() testHostWithPrivateDirs()
+38 -28
View File
@@ -74,6 +74,15 @@ Things to do:
- hifi support (e.g. delay compensation) - hifi support (e.g. delay compensation)
""" """
from signal import signal, SIGINT, SIG_IGN
from subprocess import Popen, PIPE, STDOUT
import os
from random import randrange
import sys
import re
from itertools import groupby
from operator import attrgetter
from distutils.version import StrictVersion
from mininet.node import Node, Host, OVSSwitch, Controller from mininet.node import Node, Host, OVSSwitch, Controller
from mininet.link import Link, Intf from mininet.link import Link, Intf
@@ -85,15 +94,7 @@ from mininet.examples.clustercli import CLI
from mininet.log import setLogLevel, debug, info, error from mininet.log import setLogLevel, debug, info, error
from mininet.clean import addCleanupCallback from mininet.clean import addCleanupCallback
from signal import signal, SIGINT, SIG_IGN # pylint: disable=too-many-arguments
from subprocess import Popen, PIPE, STDOUT
import os
from random import randrange
import sys
import re
from itertools import groupby
from operator import attrgetter
from distutils.version import StrictVersion
def findUser(): def findUser():
@@ -261,7 +262,7 @@ class RemoteMixin( object ):
cmd: remote command to run (list) cmd: remote command to run (list)
**params: parameters to Popen() **params: parameters to Popen()
returns: Popen() object""" returns: Popen() object"""
if type( cmd ) is str: if isinstance( cmd, str):
cmd = cmd.split() cmd = cmd.split()
if self.isRemote: if self.isRemote:
if sudo: if sudo:
@@ -289,6 +290,7 @@ class RemoteMixin( object ):
def addIntf( self, *args, **kwargs ): def addIntf( self, *args, **kwargs ):
"Override: use RemoteLink.moveIntf" "Override: use RemoteLink.moveIntf"
# kwargs.update( moveIntfFn=RemoteLink.moveIntf ) # kwargs.update( moveIntfFn=RemoteLink.moveIntf )
# pylint: disable=useless-super-delegation
return super( RemoteMixin, self).addIntf( *args, **kwargs ) return super( RemoteMixin, self).addIntf( *args, **kwargs )
@@ -325,6 +327,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
StrictVersion( '1.10' ) ) StrictVersion( '1.10' ) )
@classmethod @classmethod
# pylint: disable=arguments-differ
def batchStartup( cls, switches, **_kwargs ): def batchStartup( cls, switches, **_kwargs ):
"Start up switches in per-server batches" "Start up switches in per-server batches"
key = attrgetter( 'server' ) key = attrgetter( 'server' )
@@ -336,6 +339,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
return switches return switches
@classmethod @classmethod
# pylint: disable=arguments-differ
def batchShutdown( cls, switches, **_kwargs ): def batchShutdown( cls, switches, **_kwargs ):
"Stop switches in per-server batches" "Stop switches in per-server batches"
key = attrgetter( 'server' ) key = attrgetter( 'server' )
@@ -413,8 +417,9 @@ class RemoteLink( Link ):
# And we can't ssh into this server remotely as 'localhost', # And we can't ssh into this server remotely as 'localhost',
# so try again swappping node1 and node2 # so try again swappping node1 and node2
if node2.server == 'localhost': if node2.server == 'localhost':
return self.makeTunnel( node2, node1, intfname2, intfname1, return self.makeTunnel( node1=node2, node2=node1,
addr2, addr1 ) intfname1=intfname2, intfname2=intfname1,
addr1=addr2, addr2=addr1 )
debug( '\n*** Make SSH tunnel ' + node1.server + ':' + intfname1 + debug( '\n*** Make SSH tunnel ' + node1.server + ':' + intfname1 +
' == ' + node2.server + ':' + intfname2 ) ' == ' + node2.server + ':' + intfname2 )
# 1. Create tap interfaces # 1. Create tap interfaces
@@ -526,8 +531,9 @@ class RemoteGRELink( RemoteLink ):
# We should never try to create a tunnel to ourselves! # We should never try to create a tunnel to ourselves!
assert node1.server != node2.server assert node1.server != node2.server
if node2.server == 'localhost': if node2.server == 'localhost':
return self.makeTunnel( node2, node1, intfname2, intfname1, return self.makeTunnel( node1=node2, node2=node1,
addr2, addr1 ) intfname1=intfname2, intfname2=intfname1,
addr1=addr2, addr2=addr1 )
IP1, IP2 = node1.serverIP, node2.serverIP IP1, IP2 = node1.serverIP, node2.serverIP
# GRE tunnel needs to be set up with the IP of the local interface # GRE tunnel needs to be set up with the IP of the local interface
# that connects the remote node, NOT '127.0.0.1' of localhost # that connects the remote node, NOT '127.0.0.1' of localhost
@@ -555,6 +561,7 @@ class RemoteGRELink( RemoteLink ):
node.rcmd('ip link set dev %s mtu 1450' % intfname) node.rcmd('ip link set dev %s mtu 1450' % intfname)
if not self.moveIntf(intfname, node): if not self.moveIntf(intfname, node):
raise Exception('interface move failed on node %s' % node) raise Exception('interface move failed on node %s' % node)
return None # May want to return something useful here
# Some simple placement algorithms for MininetCluster # Some simple placement algorithms for MininetCluster
@@ -589,10 +596,10 @@ class Placer( object ):
class RandomPlacer( Placer ): class RandomPlacer( Placer ):
"Random placement" "Random placement"
def place( self, nodename ): def place( self, node ):
"""Random placement function """Random placement function
nodename: node name""" node: node"""
assert nodename # please pylint assert node # please pylint
# This may be slow with lots of servers # This may be slow with lots of servers
return self.servers[ randrange( 0, len( self.servers ) ) ] return self.servers[ randrange( 0, len( self.servers ) ) ]
@@ -606,10 +613,10 @@ class RoundRobinPlacer( Placer ):
Placer.__init__( self, *args, **kwargs ) Placer.__init__( self, *args, **kwargs )
self.next = 0 self.next = 0
def place( self, nodename ): def place( self, node ):
"""Round-robin placement function """Round-robin placement function
nodename: node name""" node: node"""
assert nodename # please pylint assert node # please pylint
# This may be slow with lots of servers # This may be slow with lots of servers
server = self.servers[ self.next ] server = self.servers[ self.next ]
self.next = ( self.next + 1 ) % len( self.servers ) self.next = ( self.next + 1 ) % len( self.servers )
@@ -647,7 +654,7 @@ class SwitchBinPlacer( Placer ):
tickets = sum( [ binsizes[ server ] * [ server ] tickets = sum( [ binsizes[ server ] * [ server ]
for server in servers ], [] ) for server in servers ], [] )
# And assign one ticket to each node # And assign one ticket to each node
return { node: ticket for node, ticket in zip( nodes, tickets ) } return dict( zip( nodes, tickets ) )
def calculatePlacement( self ): def calculatePlacement( self ):
"Pre-calculate node placement" "Pre-calculate node placement"
@@ -704,21 +711,21 @@ class HostSwitchBinPlacer( Placer ):
self.cset = frozenset( self.controllers ) self.cset = frozenset( self.controllers )
self.hind, self.sind, self.cind = 0, 0, 0 self.hind, self.sind, self.cind = 0, 0, 0
def place( self, nodename ): def place( self, node ):
"""Simple placement algorithm: """Simple placement algorithm:
place nodes into evenly sized bins""" place nodes into evenly sized bins"""
# Place nodes into bins # Place nodes into bins
if nodename in self.hset: if node in self.hset:
server = self.servdict[ self.hind / self.hbin ] server = self.servdict[ self.hind / self.hbin ]
self.hind += 1 self.hind += 1
elif nodename in self.sset: elif node in self.sset:
server = self.servdict[ self.sind / self.sbin ] server = self.servdict[ self.sind / self.sbin ]
self.sind += 1 self.sind += 1
elif nodename in self.cset: elif node in self.cset:
server = self.servdict[ self.cind / self.cbin ] server = self.servdict[ self.cind / self.cbin ]
self.cind += 1 self.cind += 1
else: else:
info( 'warning: unknown node', nodename ) info( 'warning: unknown node', node )
server = self.servdict[ 0 ] server = self.servdict[ 0 ]
return server return server
@@ -764,6 +771,7 @@ class MininetCluster( Mininet ):
# Make sure control directory exists # Make sure control directory exists
self.cdir = os.environ[ 'HOME' ] + '/.ssh/mn' self.cdir = os.environ[ 'HOME' ] + '/.ssh/mn'
errRun( [ 'mkdir', '-p', self.cdir ] ) errRun( [ 'mkdir', '-p', self.cdir ] )
# pylint: disable=unexpected-keyword-arg
Mininet.__init__( self, *args, **params ) Mininet.__init__( self, *args, **params )
def popen( self, cmd ): def popen( self, cmd ):
@@ -840,18 +848,19 @@ class MininetCluster( Mininet ):
if cfile: if cfile:
config.setdefault( 'controlPath', cfile ) config.setdefault( 'controlPath', cfile )
# pylint: disable=arguments-differ,signature-differs
def addController( self, *args, **kwargs ): def addController( self, *args, **kwargs ):
"Patch to update IP address to global IP address" "Patch to update IP address to global IP address"
controller = Mininet.addController( self, *args, **kwargs ) controller = Mininet.addController( self, *args, **kwargs )
loopback = '127.0.0.1' loopback = '127.0.0.1'
if ( not isinstance( controller, Controller ) or if ( not isinstance( controller, Controller ) or
controller.IP() != loopback ): controller.IP() != loopback ):
return return None
# Find route to a different server IP address # Find route to a different server IP address
serverIPs = [ ip for ip in self.serverIP.values() serverIPs = [ ip for ip in self.serverIP.values()
if ip is not controller.IP() ] if ip is not controller.IP() ]
if not serverIPs: if not serverIPs:
return # no remote servers - loopback is fine return None # no remote servers - loopback is fine
remoteIP = serverIPs[ 0 ] remoteIP = serverIPs[ 0 ]
# Route should contain 'dev <intfname>' # Route should contain 'dev <intfname>'
route = controller.cmd( 'ip route get', remoteIP, route = controller.cmd( 'ip route get', remoteIP,
@@ -865,6 +874,7 @@ class MininetCluster( Mininet ):
debug( controller, 'IP address updated to', controller.IP() ) debug( controller, 'IP address updated to', controller.IP() )
return controller return controller
# pylint: disable=arguments-differ,signature-differs
def buildFromTopo( self, *args, **kwargs ): def buildFromTopo( self, *args, **kwargs ):
"Start network" "Start network"
info( '*** Placing nodes\n' ) info( '*** Placing nodes\n' )
+1
View File
@@ -17,6 +17,7 @@ def clusterSanity():
CLI( net ) CLI( net )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
clusterSanity() clusterSanity()
+1
View File
@@ -31,6 +31,7 @@ class ClusterCLI( CLI ):
if not nx: if not nx:
try: try:
# pylint: disable=import-error,no-member # pylint: disable=import-error,no-member
# pylint: disable=import-outside-toplevel
import networkx import networkx
nx = networkx # satisfy pylint nx = networkx # satisfy pylint
from matplotlib import pyplot from matplotlib import pyplot
+1
View File
@@ -19,6 +19,7 @@ def demo():
CLI( net ) CLI( net )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
demo() demo()
+1
View File
@@ -17,6 +17,7 @@ def perf(Link):
net.iperf() net.iperf()
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel('info') setLogLevel('info')
perf( RemoteSSHLink ) perf( RemoteSSHLink )
+5 -1
View File
@@ -27,6 +27,7 @@ Bob Lantz, April 2010
import re import re
# pylint: disable=import-error
from Tkinter import Frame, Button, Label, Text, Scrollbar, Canvas, Wm, READABLE from Tkinter import Frame, Button, Label, Text, Scrollbar, Canvas, Wm, READABLE
from mininet.log import setLogLevel from mininet.log import setLogLevel
@@ -34,6 +35,9 @@ from mininet.topolib import TreeNet
from mininet.term import makeTerms, cleanUpScreens from mininet.term import makeTerms, cleanUpScreens
from mininet.util import quietRun from mininet.util import quietRun
# pylint: disable=too-many-arguments
class Console( Frame ): class Console( Frame ):
"A simple console on a host." "A simple console on a host."
@@ -319,7 +323,7 @@ class ConsoleApp( Frame ):
if not m: if not m:
return return
val, units = float( m.group( 1 ) ), m.group( 2 ) val, units = float( m.group( 1 ) ), m.group( 2 )
#convert to Gbps # convert to Gbps
if units[0] == 'M': if units[0] == 'M':
val *= 10 ** -3 val *= 10 ** -3
elif units[0] == 'K': elif units[0] == 'K':
+1
View File
@@ -26,6 +26,7 @@ class MultiSwitch( OVSSwitch ):
def start( self, controllers ): def start( self, controllers ):
return OVSSwitch.start( self, [ cmap[ self.name ] ] ) return OVSSwitch.start( self, [ cmap[ self.name ] ] )
topo = TreeTopo( depth=2, fanout=2 ) topo = TreeTopo( depth=2, fanout=2 )
net = Mininet( topo=topo, switch=MultiSwitch, build=False, waitConnected=True ) net = Mininet( topo=topo, switch=MultiSwitch, build=False, waitConnected=True )
for c in [ c0, c1 ]: for c in [ c0, c1 ]:
+1
View File
@@ -58,6 +58,7 @@ def multiControllerNet():
info( "*** Stopping network\n" ) info( "*** Stopping network\n" )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) # for CLI output setLogLevel( 'info' ) # for CLI output
multiControllerNet() multiControllerNet()
+4 -2
View File
@@ -59,13 +59,14 @@ class MininetFacade( object ):
def __getitem__( self, key ): def __getitem__( self, key ):
"returns primary/named networks or node from any net" "returns primary/named networks or node from any net"
#search kwargs for net named key # search kwargs for net named key
if key in self.nameToNet: if key in self.nameToNet:
return self.nameToNet[ key ] return self.nameToNet[ key ]
#search each net for node named key # search each net for node named key
for net in self.nets: for net in self.nets:
if key in net: if key in net:
return net[ key ] return net[ key ]
return None
def __iter__( self ): def __iter__( self ):
"Iterate through all nodes in all Mininet objects" "Iterate through all nodes in all Mininet objects"
@@ -100,6 +101,7 @@ class MininetFacade( object ):
class ControlNetwork( Topo ): class ControlNetwork( Topo ):
"Control Network Topology" "Control Network Topology"
# pylint: disable=arguments-differ
def build( self, n, dataController=DataController, **_kwargs ): def build( self, n, dataController=DataController, **_kwargs ):
"""n: number of data network controller nodes """n: number of data network controller nodes
dataController: class for data network controllers""" dataController: class for data network controllers"""
+1 -1
View File
@@ -54,7 +54,7 @@ def bwtest( cpuLimits, period_us=100000, seconds=10 ):
try: try:
net = Mininet( topo=topo, host=host, waitConnected=True ) net = Mininet( topo=topo, host=host, waitConnected=True )
# pylint: disable=bare-except # pylint: disable=bare-except
except: except: # noqa
info( '*** Skipping scheduler %s and cleaning up\n' % sched ) info( '*** Skipping scheduler %s and cleaning up\n' % sched )
cleanup() cleanup()
break break
+1
View File
@@ -39,6 +39,7 @@ def emptyNet():
info( '*** Stopping network' ) info( '*** Stopping network' )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
emptyNet() emptyNet()
+4
View File
@@ -8,6 +8,8 @@ hardware interface) to a network after the network is created.
import re import re
import sys import sys
from sys import exit # pylint: disable=redefined-builtin
from mininet.cli import CLI from mininet.cli import CLI
from mininet.log import setLogLevel, info, error from mininet.log import setLogLevel, info, error
from mininet.net import Mininet from mininet.net import Mininet
@@ -15,6 +17,7 @@ from mininet.link import Intf
from mininet.topolib import TreeTopo from mininet.topolib import TreeTopo
from mininet.util import quietRun from mininet.util import quietRun
def checkIntf( intf ): def checkIntf( intf ):
"Make sure intf exists and is not configured." "Make sure intf exists and is not configured."
config = quietRun( 'ifconfig %s 2>/dev/null' % intf, shell=True ) config = quietRun( 'ifconfig %s 2>/dev/null' % intf, shell=True )
@@ -27,6 +30,7 @@ def checkIntf( intf ):
'and is probably in use!\n' ) 'and is probably in use!\n' )
exit( 1 ) exit( 1 )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
+1
View File
@@ -43,6 +43,7 @@ def intfOptions():
info( '\n*** Done testing\n' ) info( '\n*** Done testing\n' )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
intfOptions() intfOptions()
+1
View File
@@ -55,6 +55,7 @@ def verySimpleLimit( bw=150 ):
h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() ) h2.cmdPrint( 'tc -d class show dev', h2.defaultIntf() )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
limit() limit()
+9 -4
View File
@@ -24,20 +24,24 @@ of switches, this example demonstrates:
""" """
import sys
from functools import partial
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import UserSwitch, OVSKernelSwitch, Controller from mininet.node import UserSwitch, OVSKernelSwitch, Controller
from mininet.topo import Topo from mininet.topo import Topo
from mininet.log import lg, info from mininet.log import lg, info
from mininet.util import irange, quietRun from mininet.util import irange, quietRun
from mininet.link import TCLink from mininet.link import TCLink
from functools import partial
import sys
flush = sys.stdout.flush flush = sys.stdout.flush
class LinearTestTopo( Topo ): class LinearTestTopo( Topo ):
"Topology for a string of N hosts and N-1 switches." "Topology for a string of N hosts and N-1 switches."
# pylint: disable=arguments-differ
def build( self, N, **params ): def build( self, N, **params ):
# Create switches and hosts # Create switches and hosts
hosts = [ self.addHost( 'h%s' % h ) hosts = [ self.addHost( 'h%s' % h )
@@ -79,7 +83,7 @@ def linearBandwidthTest( lengths ):
output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' ) output = quietRun( 'sysctl -w net.ipv4.tcp_congestion_control=reno' )
assert 'reno' in output assert 'reno' in output
for datapath in switches.keys(): for datapath in switches:
info( "*** testing", datapath, "datapath\n" ) info( "*** testing", datapath, "datapath\n" )
Switch = switches[ datapath ] Switch = switches[ datapath ]
results[ datapath ] = [] results[ datapath ] = []
@@ -105,7 +109,7 @@ def linearBandwidthTest( lengths ):
results[ datapath ] += [ ( n, serverbw ) ] results[ datapath ] += [ ( n, serverbw ) ]
net.stop() net.stop()
for datapath in switches.keys(): for datapath in switches:
info( "\n*** Linear network results for", datapath, "datapath:\n" ) info( "\n*** Linear network results for", datapath, "datapath:\n" )
result = results[ datapath ] result = results[ datapath ]
info( "SwitchCount\tiperf Results\n" ) info( "SwitchCount\tiperf Results\n" )
@@ -115,6 +119,7 @@ def linearBandwidthTest( lengths ):
info( '\n') info( '\n')
info( '\n' ) info( '\n' )
if __name__ == '__main__': if __name__ == '__main__':
lg.setLogLevel( 'info' ) lg.setLogLevel( 'info' )
sizes = [ 1, 2, 3, 4 ] sizes = [ 1, 2, 3, 4 ]
+3
View File
@@ -38,6 +38,7 @@ from mininet.cli import CLI
class LinuxRouter( Node ): class LinuxRouter( Node ):
"A Node with IP forwarding enabled." "A Node with IP forwarding enabled."
# pylint: disable=arguments-differ
def config( self, **params ): def config( self, **params ):
super( LinuxRouter, self).config( **params ) super( LinuxRouter, self).config( **params )
# Enable forwarding on the router # Enable forwarding on the router
@@ -51,6 +52,7 @@ class LinuxRouter( Node ):
class NetworkTopo( Topo ): class NetworkTopo( Topo ):
"A LinuxRouter connecting three IP subnets" "A LinuxRouter connecting three IP subnets"
# pylint: disable=arguments-differ
def build( self, **_opts ): def build( self, **_opts ):
defaultIP = '192.168.1.1/24' # IP address for r0-eth1 defaultIP = '192.168.1.1/24' # IP address for r0-eth1
@@ -87,6 +89,7 @@ def run():
CLI( net ) CLI( net )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
run() run()
+65 -60
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python
""" """
MiniEdit: a simple network editor for Mininet MiniEdit: a simple network editor for Mininet
@@ -13,16 +13,30 @@ Controller icon from http://semlabs.co.uk/
OpenFlow icon from https://www.opennetworking.org/ OpenFlow icon from https://www.opennetworking.org/
""" """
# Miniedit needs some work in order to pass pylint... import json
# pylint: disable=line-too-long,too-many-branches import os
# pylint: disable=too-many-statements,attribute-defined-outside-init import re
# pylint: disable=missing-docstring
MINIEDIT_VERSION = '2.2.0.1'
import sys import sys
from distutils.version import StrictVersion
from functools import partial
from optparse import OptionParser from optparse import OptionParser
from subprocess import call from subprocess import call
from sys import exit # pylint: disable=redefined-builtin
from mininet.log import info, debug, warn, setLogLevel
from mininet.net import Mininet, VERSION
from mininet.util import (netParse, ipAdd, quietRun,
buildTopo, custom, customClass )
from mininet.term import makeTerm, cleanUpScreens
from mininet.node import (Controller, RemoteController, NOX, OVSController,
CPULimitedHost, Host, Node,
OVSSwitch, UserSwitch, IVSSwitch )
from mininet.link import TCLink, Intf, Link
from mininet.cli import CLI
from mininet.moduledeps import moduleDeps
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.topolib import TreeTopo
# pylint: disable=import-error # pylint: disable=import-error
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
@@ -47,38 +61,24 @@ else:
from tkinter import font as tkFont from tkinter import font as tkFont
from tkinter import simpledialog as tkSimpleDialog from tkinter import simpledialog as tkSimpleDialog
from tkinter import filedialog as tkFileDialog from tkinter import filedialog as tkFileDialog
# someday: from ttk import *
# pylint: enable=import-error # pylint: enable=import-error
import re
import json # Miniedit still needs work in order to pass pylint...
from distutils.version import StrictVersion # pylint: disable=line-too-long,too-many-branches
import os # pylint: disable=too-many-statements,attribute-defined-outside-init
from functools import partial # pylint: disable=missing-docstring,too-many-ancestors
# pylint: disable=too-many-nested-blocks,too-many-arguments
MINIEDIT_VERSION = '2.2.0.1'
if 'PYTHONPATH' in os.environ: if 'PYTHONPATH' in os.environ:
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
# someday: from ttk import *
from mininet.log import info, debug, warn, setLogLevel
from mininet.net import Mininet, VERSION
from mininet.util import netParse, ipAdd, quietRun
from mininet.util import buildTopo
from mininet.util import custom, customClass
from mininet.term import makeTerm, cleanUpScreens
from mininet.node import Controller, RemoteController, NOX, OVSController
from mininet.node import CPULimitedHost, Host, Node
from mininet.node import OVSSwitch, UserSwitch
from mininet.link import TCLink, Intf, Link
from mininet.cli import CLI
from mininet.moduledeps import moduleDeps
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.topolib import TreeTopo
info( 'MiniEdit running against Mininet '+VERSION, '\n' ) info( 'MiniEdit running against Mininet '+VERSION, '\n' )
MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION) MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
from mininet.node import IVSSwitch
TOPODEF = 'none' TOPODEF = 'none'
TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ), TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
@@ -138,6 +138,7 @@ class LegacyRouter( Node ):
def __init__( self, name, inNamespace=True, **params ): def __init__( self, name, inNamespace=True, **params ):
Node.__init__( self, name, inNamespace, **params ) Node.__init__( self, name, inNamespace, **params )
# pylint: disable=arguments-differ
def config( self, **_params ): def config( self, **_params ):
if self.intfs: if self.intfs:
self.setParam( _params, 'setIP', ip='0.0.0.0' ) self.setParam( _params, 'setIP', ip='0.0.0.0' )
@@ -818,8 +819,8 @@ class VerticalScrolledTable(LabelFrame):
* This frame only allows vertical scrolling * This frame only allows vertical scrolling
""" """
def __init__(self, parent, rows=2, columns=2, title=None, *args, **kw): def __init__(self, parent, rows=2, columns=2, title=None, **kw):
LabelFrame.__init__(self, parent, text=title, padx=5, pady=5, *args, **kw) LabelFrame.__init__(self, parent, text=title, padx=5, pady=5, **kw)
# create a canvas object and a vertical scrollbar for scrolling it # create a canvas object and a vertical scrollbar for scrolling it
vscrollbar = Scrollbar(self, orient=VERTICAL) vscrollbar = Scrollbar(self, orient=VERTICAL)
@@ -855,8 +856,6 @@ class VerticalScrolledTable(LabelFrame):
canvas.itemconfigure(interior_id, width=canvas.winfo_width()) canvas.itemconfigure(interior_id, width=canvas.winfo_width())
canvas.bind('<Configure>', _configure_canvas) canvas.bind('<Configure>', _configure_canvas)
return
class TableFrame(Frame): class TableFrame(Frame):
def __init__(self, parent, rows=2, columns=2): def __init__(self, parent, rows=2, columns=2):
@@ -888,7 +887,7 @@ class TableFrame(Frame):
label.grid(row=self.rows, column=column, sticky="wens", padx=1, pady=1) label.grid(row=self.rows, column=column, sticky="wens", padx=1, pady=1)
if value is not None: if value is not None:
label.insert(0, value[column]) label.insert(0, value[column])
if readonly == True: if readonly:
label.configure(state='readonly') label.configure(state='readonly')
current_row.append(label) current_row.append(label)
self._widgets.append(current_row) self._widgets.append(current_row)
@@ -1401,11 +1400,11 @@ class MiniEdit( Frame ):
def addNode( self, node, nodeNum, x, y, name=None): def addNode( self, node, nodeNum, x, y, name=None):
"Add a new node to our canvas." "Add a new node to our canvas."
if 'Switch' == node: if node == 'Switch':
self.switchCount += 1 self.switchCount += 1
if 'Host' == node: if node == 'Host':
self.hostCount += 1 self.hostCount += 1
if 'Controller' == node: if node == 'Controller':
self.controllerCount += 1 self.controllerCount += 1
if name is None: if name is None:
name = self.nodePrefixes[ node ] + nodeNum name = self.nodePrefixes[ node ] + nodeNum
@@ -1422,13 +1421,16 @@ class MiniEdit( Frame ):
def convertJsonUnicode(self, text): def convertJsonUnicode(self, text):
"Some part of Mininet don't like Unicode" "Some part of Mininet don't like Unicode"
try:
unicode
except NameError:
return text
if isinstance(text, dict): if isinstance(text, dict):
return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in text.items()} return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in text.items()}
elif isinstance(text, list): if isinstance(text, list):
return [self.convertJsonUnicode(element) for element in text] return [self.convertJsonUnicode(element) for element in text]
elif isinstance(text, unicode): if isinstance(text, unicode): # pylint: disable=undefined-variable
return text.encode('utf-8') return text.encode('utf-8')
else:
return text return text
def loadTopology( self ): def loadTopology( self ):
@@ -1440,7 +1442,7 @@ class MiniEdit( Frame ):
('All Files','*'), ('All Files','*'),
] ]
f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb') f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
if f == None: if f is None:
return return
self.newTopology() self.newTopology()
loadedTopology = self.convertJsonUnicode(json.load(f)) loadedTopology = self.convertJsonUnicode(json.load(f))
@@ -1601,10 +1603,11 @@ class MiniEdit( Frame ):
for widget in self.widgetToItem: for widget in self.widgetToItem:
if name == widget[ 'text' ]: if name == widget[ 'text' ]:
return widget return widget
return None
def newTopology( self ): def newTopology( self ):
"New command." "New command."
for widget in self.widgetToItem.keys(): for widget in self.widgetToItem:
self.deleteItem( self.widgetToItem[ widget ] ) self.deleteItem( self.widgetToItem[ widget ] )
self.hostCount = 0 self.hostCount = 0
self.switchCount = 0 self.switchCount = 0
@@ -1725,7 +1728,7 @@ class MiniEdit( Frame ):
if controllerType == 'inband': if controllerType == 'inband':
inBandCtrl = True inBandCtrl = True
if inBandCtrl == True: if inBandCtrl:
f.write("\n") f.write("\n")
f.write("class InbandController( RemoteController ):\n") f.write("class InbandController( RemoteController ):\n")
f.write("\n") f.write("\n")
@@ -2122,7 +2125,7 @@ class MiniEdit( Frame ):
c = self.canvas c = self.canvas
x, y = c.canvasx( event.x ), c.canvasy( event.y ) x, y = c.canvasx( event.x ), c.canvasy( event.y )
name = self.nodePrefixes[ node ] name = self.nodePrefixes[ node ]
if 'Switch' == node: if node == 'Switch':
self.switchCount += 1 self.switchCount += 1
name = self.nodePrefixes[ node ] + str( self.switchCount ) name = self.nodePrefixes[ node ] + str( self.switchCount )
self.switchOpts[name] = {} self.switchOpts[name] = {}
@@ -2130,14 +2133,14 @@ class MiniEdit( Frame ):
self.switchOpts[name]['hostname']=name self.switchOpts[name]['hostname']=name
self.switchOpts[name]['switchType']='default' self.switchOpts[name]['switchType']='default'
self.switchOpts[name]['controllers']=[] self.switchOpts[name]['controllers']=[]
if 'LegacyRouter' == node: if node == 'LegacyRouter':
self.switchCount += 1 self.switchCount += 1
name = self.nodePrefixes[ node ] + str( self.switchCount ) name = self.nodePrefixes[ node ] + str( self.switchCount )
self.switchOpts[name] = {} self.switchOpts[name] = {}
self.switchOpts[name]['nodeNum']=self.switchCount self.switchOpts[name]['nodeNum']=self.switchCount
self.switchOpts[name]['hostname']=name self.switchOpts[name]['hostname']=name
self.switchOpts[name]['switchType']='legacyRouter' self.switchOpts[name]['switchType']='legacyRouter'
if 'LegacySwitch' == node: if node == 'LegacySwitch':
self.switchCount += 1 self.switchCount += 1
name = self.nodePrefixes[ node ] + str( self.switchCount ) name = self.nodePrefixes[ node ] + str( self.switchCount )
self.switchOpts[name] = {} self.switchOpts[name] = {}
@@ -2145,13 +2148,13 @@ class MiniEdit( Frame ):
self.switchOpts[name]['hostname']=name self.switchOpts[name]['hostname']=name
self.switchOpts[name]['switchType']='legacySwitch' self.switchOpts[name]['switchType']='legacySwitch'
self.switchOpts[name]['controllers']=[] self.switchOpts[name]['controllers']=[]
if 'Host' == node: if node == 'Host':
self.hostCount += 1 self.hostCount += 1
name = self.nodePrefixes[ node ] + str( self.hostCount ) name = self.nodePrefixes[ node ] + str( self.hostCount )
self.hostOpts[name] = {'sched':'host'} self.hostOpts[name] = {'sched':'host'}
self.hostOpts[name]['nodeNum']=self.hostCount self.hostOpts[name]['nodeNum']=self.hostCount
self.hostOpts[name]['hostname']=name self.hostOpts[name]['hostname']=name
if 'Controller' == node: if node == 'Controller':
name = self.nodePrefixes[ node ] + str( self.controllerCount ) name = self.nodePrefixes[ node ] + str( self.controllerCount )
ctrlr = { 'controllerType': 'ref', ctrlr = { 'controllerType': 'ref',
'hostname': name, 'hostname': name,
@@ -2169,15 +2172,15 @@ class MiniEdit( Frame ):
self.itemToWidget[ item ] = icon self.itemToWidget[ item ] = icon
self.selectItem( item ) self.selectItem( item )
icon.links = {} icon.links = {}
if 'Switch' == node: if node == 'Switch':
icon.bind('<Button-3>', self.do_switchPopup ) icon.bind('<Button-3>', self.do_switchPopup )
if 'LegacyRouter' == node: if node == 'LegacyRouter':
icon.bind('<Button-3>', self.do_legacyRouterPopup ) icon.bind('<Button-3>', self.do_legacyRouterPopup )
if 'LegacySwitch' == node: if node == 'LegacySwitch':
icon.bind('<Button-3>', self.do_legacySwitchPopup ) icon.bind('<Button-3>', self.do_legacySwitchPopup )
if 'Host' == node: if node == 'Host':
icon.bind('<Button-3>', self.do_hostPopup ) icon.bind('<Button-3>', self.do_hostPopup )
if 'Controller' == node: if node == 'Controller':
icon.bind('<Button-3>', self.do_controllerPopup ) icon.bind('<Button-3>', self.do_controllerPopup )
def clickController( self, event ): def clickController( self, event ):
@@ -2374,6 +2377,8 @@ class MiniEdit( Frame ):
# For now, don't allow hosts to be directly linked # For now, don't allow hosts to be directly linked
stags = self.canvas.gettags( self.widgetToItem[ source ] ) stags = self.canvas.gettags( self.widgetToItem[ source ] )
dtags = self.canvas.gettags( target ) dtags = self.canvas.gettags( target )
# TODO: Make this less confusing
# pylint: disable=too-many-boolean-expressions
if (('Host' in stags and 'Host' in dtags) or if (('Host' in stags and 'Host' in dtags) or
('Controller' in dtags and 'LegacyRouter' in stags) or ('Controller' in dtags and 'LegacyRouter' in stags) or
('Controller' in stags and 'LegacyRouter' in dtags) or ('Controller' in stags and 'LegacyRouter' in dtags) or
@@ -2657,7 +2662,7 @@ class MiniEdit( Frame ):
linkopts = {} linkopts = {}
source.links[ dest ] = self.link source.links[ dest ] = self.link
dest.links[ source ] = self.link dest.links[ source ] = self.link
self.links[ self.link ] = {'type' :linktype, self.links[ self.link ] = {'type':linktype,
'src':source, 'src':source,
'dest':dest, 'dest':dest,
'linkOpts':linkopts} 'linkOpts':linkopts}
@@ -3225,7 +3230,8 @@ class MiniEdit( Frame ):
"Parse custom file and add params before parsing cmd-line options." "Parse custom file and add params before parsing cmd-line options."
customs = {} customs = {}
if os.path.isfile( fileName ): if os.path.isfile( fileName ):
execfile( fileName, customs, customs ) with open( fileName, 'r' ) as f:
exec( f.read() ) # pylint: disable=exec-used
for name, val in customs.items(): for name, val in customs.items():
self.setCustom( name, val ) self.setCustom( name, val )
else: else:
@@ -3592,8 +3598,7 @@ def addDictOption( opts, choicesDict, default, name, helpStr=None ):
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
app = MiniEdit() app = MiniEdit()
### import topology if specified ###
app.parseArgs() app.parseArgs()
### import topology if specified ###
app.importTopo() app.importTopo()
app.mainloop() app.mainloop()
+3 -2
View File
@@ -19,14 +19,13 @@ to-do:
- think about clearing last hop - why doesn't that work? - think about clearing last hop - why doesn't that work?
""" """
from random import randint
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import OVSSwitch from mininet.node import OVSSwitch
from mininet.topo import LinearTopo from mininet.topo import LinearTopo
from mininet.log import info, output, warn, setLogLevel from mininet.log import info, output, warn, setLogLevel
from random import randint
class MobilitySwitch( OVSSwitch ): class MobilitySwitch( OVSSwitch ):
"Switch that can reattach and rename interfaces" "Switch that can reattach and rename interfaces"
@@ -38,6 +37,7 @@ class MobilitySwitch( OVSSwitch ):
del self.intfs[ port ] del self.intfs[ port ]
del self.nameToIntf[ intf.name ] del self.nameToIntf[ intf.name ]
# pylint: disable=arguments-differ
def addIntf( self, intf, rename=False, **kwargs ): def addIntf( self, intf, rename=False, **kwargs ):
"Add (and reparent) an interface" "Add (and reparent) an interface"
OVSSwitch.addIntf( self, intf, **kwargs ) OVSSwitch.addIntf( self, intf, **kwargs )
@@ -132,6 +132,7 @@ def mobilityTest():
old = new old = new
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
mobilityTest() mobilityTest()
+2
View File
@@ -21,6 +21,7 @@ def runMultiLink():
class simpleMultiLinkTopo( Topo ): class simpleMultiLinkTopo( Topo ):
"Simple topology with multiple links" "Simple topology with multiple links"
# pylint: disable=arguments-differ
def build( self, n, **_kwargs ): def build( self, n, **_kwargs ):
h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' ) h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' )
s1 = self.addSwitch( 's1' ) s1 = self.addSwitch( 's1' )
@@ -29,6 +30,7 @@ class simpleMultiLinkTopo( Topo ):
self.addLink( s1, h1 ) self.addLink( s1, h1 )
self.addLink( s1, h2 ) self.addLink( s1, h2 )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
runMultiLink() runMultiLink()
+3 -3
View File
@@ -8,14 +8,14 @@ multiple hosts and monitor their output interactively for a period=
of time. of time.
""" """
from select import poll, POLLIN
from time import time
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import Node from mininet.node import Node
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.log import info, setLogLevel from mininet.log import info, setLogLevel
from select import poll, POLLIN
from time import time
def chunks( l, n ): def chunks( l, n ):
"Divide list l into chunks of size n - thanks Stackoverflow" "Divide list l into chunks of size n - thanks Stackoverflow"
@@ -59,7 +59,7 @@ def multiping( netsize, chunksize, seconds):
# Start pings # Start pings
for subnet in subnets: for subnet in subnets:
ips = [ host.IP() for host in subnet ] ips = [ host.IP() for host in subnet ]
#adding bogus to generate packet loss # adding bogus to generate packet loss
ips.append( '10.0.0.200' ) ips.append( '10.0.0.200' )
for host in subnet: for host in subnet:
startpings( host, ips ) startpings( host, ips )
+4 -4
View File
@@ -6,15 +6,15 @@ monitoring them
""" """
from time import time
from select import poll, POLLIN
from subprocess import Popen, PIPE
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.net import Mininet from mininet.net import Mininet
from mininet.log import info, setLogLevel from mininet.log import info, setLogLevel
from mininet.util import decode from mininet.util import decode
from time import time
from select import poll, POLLIN
from subprocess import Popen, PIPE
def monitorFiles( outfiles, seconds, timeoutms ): def monitorFiles( outfiles, seconds, timeoutms ):
"Monitor set of files and return [(host, line)...]" "Monitor set of files and return [(host, line)...]"
+1
View File
@@ -17,6 +17,7 @@ def ifconfigTest( net ):
for host in hosts: for host in hosts:
info( host.cmd( 'ifconfig' ) ) info( host.cmd( 'ifconfig' ) )
if __name__ == '__main__': if __name__ == '__main__':
lg.setLogLevel( 'info' ) lg.setLogLevel( 'info' )
info( "*** Initializing Mininet and kernel modules\n" ) info( "*** Initializing Mininet and kernel modules\n" )
+2
View File
@@ -27,6 +27,7 @@ from mininet.util import irange
class InternetTopo(Topo): class InternetTopo(Topo):
"Single switch connected to n hosts." "Single switch connected to n hosts."
# pylint: disable=arguments-differ
def build(self, n=2, **_kwargs ): def build(self, n=2, **_kwargs ):
# set up inet switch # set up inet switch
inetSwitch = self.addSwitch('s0') inetSwitch = self.addSwitch('s0')
@@ -62,6 +63,7 @@ def run():
CLI(net) CLI(net)
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel('info') setLogLevel('info')
run() run()
+1
View File
@@ -75,6 +75,7 @@ def testPortNumbering():
info( '*** Stopping network\n' ) info( '*** Stopping network\n' )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
testPortNumbering() testPortNumbering()
+1
View File
@@ -28,6 +28,7 @@ def monitorhosts( hosts=5 ):
# Done # Done
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
monitorhosts( hosts=5 ) monitorhosts( hosts=5 )
+4 -2
View File
@@ -2,13 +2,14 @@
"Monitor multiple hosts using popen()/pmonitor()" "Monitor multiple hosts using popen()/pmonitor()"
from time import time
from signal import SIGINT
from mininet.net import Mininet from mininet.net import Mininet
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.util import pmonitor from mininet.util import pmonitor
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from time import time
from signal import SIGINT
def pmonitorTest( N=3, seconds=10 ): def pmonitorTest( N=3, seconds=10 ):
"Run pings and monitor multiple hosts using pmonitor" "Run pings and monitor multiple hosts using pmonitor"
@@ -31,6 +32,7 @@ def pmonitorTest( N=3, seconds=10 ):
p.send_signal( SIGINT ) p.send_signal( SIGINT )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
pmonitorTest() pmonitorTest()
+2 -1
View File
@@ -8,6 +8,7 @@ but it exposes the configuration details and allows customization.
For most tasks, the higher-level API will be preferable. For most tasks, the higher-level API will be preferable.
""" """
from time import sleep
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import Node from mininet.node import Node
@@ -15,7 +16,6 @@ from mininet.link import Link
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from mininet.util import quietRun from mininet.util import quietRun
from time import sleep
def scratchNet( cname='controller', cargs='-v ptcp:' ): def scratchNet( cname='controller', cargs='-v ptcp:' ):
"Create network from scratch using Open vSwitch." "Create network from scratch using Open vSwitch."
@@ -62,6 +62,7 @@ def scratchNet( cname='controller', cargs='-v ptcp:' ):
switch.deleteIntfs() switch.deleteIntfs()
info( '\n' ) info( '\n' )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
info( '*** Scratch network demo (kernel datapath)\n' ) info( '*** Scratch network demo (kernel datapath)\n' )
+1
View File
@@ -66,6 +66,7 @@ def scratchNetUser( cname='controller', cargs='ptcp:' ):
switch.deleteIntfs() switch.deleteIntfs()
info( '\n' ) info( '\n' )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
info( '*** Scratch network demo (user datapath)\n' ) info( '*** Scratch network demo (user datapath)\n' )
+2 -1
View File
@@ -9,6 +9,7 @@ iperf will hang indefinitely if the TCP handshake fails
to complete. to complete.
""" """
from sys import argv
from mininet.topo import Topo from mininet.topo import Topo
from mininet.net import Mininet from mininet.net import Mininet
@@ -17,7 +18,6 @@ from mininet.link import TCLink
from mininet.util import dumpNodeConnections from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel, info from mininet.log import setLogLevel, info
from sys import argv
# It would be nice if we didn't have to do this: # It would be nice if we didn't have to do this:
# pylint: disable=arguments-differ # pylint: disable=arguments-differ
@@ -54,6 +54,7 @@ def perfTest( lossy=True ):
net.iperf( ( h1, h4 ), l4Type='UDP' ) net.iperf( ( h1, h4 ), l4Type='UDP' )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
# Prevent test_simpleperf from failing due to packet loss # Prevent test_simpleperf from failing due to packet loss
+2
View File
@@ -47,6 +47,7 @@ def connectToRootNS( network, switch, ip, routes ):
for route in routes: for route in routes:
root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) ) root.cmd( 'route add -net ' + route + ' dev ' + str( intf ) )
# pylint: disable=too-many-arguments
def sshd( network, cmd='/usr/sbin/sshd', opts='-D', def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
ip='10.123.123.1/32', routes=None, switch=None ): ip='10.123.123.1/32', routes=None, switch=None ):
"""Start a network, connect it to root ns, and run sshd on all hosts. """Start a network, connect it to root ns, and run sshd on all hosts.
@@ -73,6 +74,7 @@ def sshd( network, cmd='/usr/sbin/sshd', opts='-D',
host.cmd( 'kill %' + cmd ) host.cmd( 'kill %' + cmd )
network.stop() network.stop()
if __name__ == '__main__': if __name__ == '__main__':
lg.setLogLevel( 'info') lg.setLogLevel( 'info')
net = TreeNet( depth=1, fanout=4 ) net = TreeNet( depth=1, fanout=4 )
+1
View File
@@ -38,6 +38,7 @@ def treePing64():
info( "%s: %d%% packet loss\n" % ( name, results[ name ] ) ) info( "%s: %d%% packet loss\n" % ( name, results[ name ] ) )
info( '\n' ) info( '\n' )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'info' ) setLogLevel( 'info' )
treePing64() treePing64()
+6
View File
@@ -24,14 +24,18 @@ Usage (example uses VLAN ID=1000):
""" """
from sys import exit # pylint: disable=redefined-builtin
from mininet.node import Host from mininet.node import Host
from mininet.topo import Topo from mininet.topo import Topo
from mininet.util import quietRun from mininet.util import quietRun
from mininet.log import error from mininet.log import error
class VLANHost( Host ): class VLANHost( Host ):
"Host connected to VLAN interface" "Host connected to VLAN interface"
# pylint: disable=arguments-differ
def config( self, vlan=100, **params ): def config( self, vlan=100, **params ):
"""Configure VLANHost according to (optional) parameters: """Configure VLANHost according to (optional) parameters:
vlan: VLAN ID for default interface""" vlan: VLAN ID for default interface"""
@@ -54,6 +58,7 @@ class VLANHost( Host ):
return r return r
hosts = { 'vlan': VLANHost } hosts = { 'vlan': VLANHost }
@@ -101,6 +106,7 @@ def exampleCustomTags():
CLI( net ) CLI( net )
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
from functools import partial from functools import partial
+8 -5
View File
@@ -47,7 +47,7 @@ class CLI( Cmd ):
prompt = 'mininet> ' prompt = 'mininet> '
def __init__( self, mininet, stdin=sys.stdin, script=None, def __init__( self, mininet, stdin=sys.stdin, script=None,
*args, **kwargs ): **kwargs ):
"""Start and run interactive or batch mode CLI """Start and run interactive or batch mode CLI
mininet: Mininet network object mininet: Mininet network object
stdin: standard input for CLI stdin: standard input for CLI
@@ -59,7 +59,7 @@ class CLI( Cmd ):
self.inPoller = poll() self.inPoller = poll()
self.inPoller.register( stdin ) self.inPoller.register( stdin )
self.inputFile = script self.inputFile = script
Cmd.__init__( self, *args, stdin=stdin, **kwargs ) Cmd.__init__( self, stdin=stdin, **kwargs )
info( '*** Starting CLI:\n' ) info( '*** Starting CLI:\n' )
if self.inputFile: if self.inputFile:
@@ -79,6 +79,7 @@ class CLI( Cmd ):
return return
cls.readlineInited = True cls.readlineInited = True
try: try:
# pylint: disable=import-outside-toplevel
from readline import ( read_history_file, write_history_file, from readline import ( read_history_file, write_history_file,
set_history_length ) set_history_length )
except ImportError: except ImportError:
@@ -141,7 +142,7 @@ class CLI( Cmd ):
' mininet> xterm h2\n\n' ' mininet> xterm h2\n\n'
) )
def do_help( self, line ): def do_help( self, line ): # pylint: disable=arguments-differ
"Describe available CLI commands." "Describe available CLI commands."
Cmd.do_help( self, line ) Cmd.do_help( self, line )
if line == '': if line == '':
@@ -173,6 +174,7 @@ class CLI( Cmd ):
"""Evaluate a Python expression. """Evaluate a Python expression.
Node names may be used, e.g.: py h1.cmd('ls')""" Node names may be used, e.g.: py h1.cmd('ls')"""
try: try:
# pylint: disable=eval-used
result = eval( line, globals(), self.getLocals() ) result = eval( line, globals(), self.getLocals() )
if not result: if not result:
return return
@@ -467,10 +469,10 @@ class CLI( Cmd ):
node.sendInt() node.sendInt()
except select.error as e: except select.error as e:
# pylint: disable=unpacking-non-sequence # pylint: disable=unpacking-non-sequence
# pylint: disable=unbalanced-tuple-unpacking
errno_, errmsg = e.args errno_, errmsg = e.args
# pylint: enable=unpacking-non-sequence
if errno_ != errno.EINTR: if errno_ != errno.EINTR:
error( "select.error: %d, %s" % (errno_, errmsg) ) error( "select.error: %s, %s" % (errno_, errmsg) )
node.sendInt() node.sendInt()
def precmd( self, line ): def precmd( self, line ):
@@ -488,3 +490,4 @@ def isReadable( poller ):
mask = fdmask[ 1 ] mask = fdmask[ 1 ]
if mask & POLLIN: if mask & POLLIN:
return True return True
return False
+14 -3
View File
@@ -24,9 +24,14 @@ TCIntf: interface with bandwidth limiting and delay via tc
Link: basic link class for creating veth pairs Link: basic link class for creating veth pairs
""" """
import re
from mininet.log import info, error, debug from mininet.log import info, error, debug
from mininet.util import makeIntfPair from mininet.util import makeIntfPair
import re
# Make pylint happy:
# pylint: disable=too-many-arguments
class Intf( object ): class Intf( object ):
@@ -170,7 +175,7 @@ class Intf( object ):
name, value = list( param.items() )[ 0 ] name, value = list( param.items() )[ 0 ]
f = getattr( self, method, None ) f = getattr( self, method, None )
if not f or value is None: if not f or value is None:
return return None
if isinstance( value, list ): if isinstance( value, list ):
result = f( *value ) result = f( *value )
elif isinstance( value, dict ): elif isinstance( value, dict ):
@@ -311,6 +316,7 @@ class TCIntf( Intf ):
debug(" *** executing command: %s\n" % c) debug(" *** executing command: %s\n" % c)
return self.cmd( c ) return self.cmd( c )
# pylint: disable=arguments-differ
def config( self, bw=None, delay=None, jitter=None, loss=None, def config( self, bw=None, delay=None, jitter=None, loss=None,
gro=False, txo=True, rxo=True, gro=False, txo=True, rxo=True,
speedup=0, use_hfsc=False, use_tbf=False, speedup=0, use_hfsc=False, use_tbf=False,
@@ -351,7 +357,7 @@ class TCIntf( Intf ):
# Question: what happens if we want to reset things? # Question: what happens if we want to reset things?
if ( bw is None and not delay and not loss if ( bw is None and not delay and not loss
and max_queue_size is None ): and max_queue_size is None ):
return return None
# Clear existing configuration # Clear existing configuration
tcoutput = self.tc( '%s qdisc show dev %s' ) tcoutput = self.tc( '%s qdisc show dev %s' )
@@ -533,6 +539,10 @@ class OVSLink( Link ):
def __init__( self, node1, node2, **kwargs ): def __init__( self, node1, node2, **kwargs ):
"See Link.__init__() for options" "See Link.__init__() for options"
try:
OVSSwitch
except NameError:
# pylint: disable=import-outside-toplevel,cyclic-import
from mininet.node import OVSSwitch from mininet.node import OVSSwitch
self.isPatchLink = False self.isPatchLink = False
if ( isinstance( node1, OVSSwitch ) and if ( isinstance( node1, OVSSwitch ) and
@@ -541,6 +551,7 @@ class OVSLink( Link ):
kwargs.update( cls1=OVSIntf, cls2=OVSIntf ) kwargs.update( cls1=OVSIntf, cls2=OVSIntf )
Link.__init__( self, node1, node2, **kwargs ) Link.__init__( self, node1, node2, **kwargs )
# pylint: disable=arguments-differ, signature-differs
def makeIntfPair( self, *args, **kwargs ): def makeIntfPair( self, *args, **kwargs ):
"Usually delegated to OVSSwitch" "Usually delegated to OVSSwitch"
if self.isPatchLink: if self.isPatchLink:
+5 -3
View File
@@ -20,7 +20,7 @@ LEVELS = { 'debug': logging.DEBUG,
# change this to logging.INFO to get printouts when running unit tests # change this to logging.INFO to get printouts when running unit tests
LOGLEVELDEFAULT = OUTPUT LOGLEVELDEFAULT = OUTPUT
#default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # default: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
LOGMSGFORMAT = '%(message)s' LOGMSGFORMAT = '%(message)s'
@@ -51,7 +51,7 @@ class StreamHandlerNoNewline( logging.StreamHandler ):
self.flush() self.flush()
except ( KeyboardInterrupt, SystemExit ): except ( KeyboardInterrupt, SystemExit ):
raise raise
except: except: # noqa pylint: disable=bare-except
self.handleError( record ) self.handleError( record )
@@ -137,13 +137,14 @@ class MininetLogger( Logger, object ):
logger.warning("Houston, we have a %s", "cli output", exc_info=1) logger.warning("Houston, we have a %s", "cli output", exc_info=1)
""" """
if self.manager.disable >= OUTPUT: if getattr( self.manager, 'disabled', 0 ) >= OUTPUT:
return return
if self.isEnabledFor( OUTPUT ): if self.isEnabledFor( OUTPUT ):
self._log( OUTPUT, msg, args, kwargs ) self._log( OUTPUT, msg, args, kwargs )
# pylint: enable=method-hidden # pylint: enable=method-hidden
lg = MininetLogger() lg = MininetLogger()
# Make things a bit more convenient by adding aliases # Make things a bit more convenient by adding aliases
@@ -168,6 +169,7 @@ def makeListCompatible( fn ):
setattr( newfn, '__doc__', fn.__doc__ ) setattr( newfn, '__doc__', fn.__doc__ )
return newfn return newfn
_loggers = lg.info, lg.output, lg.warn, lg.error, lg.debug _loggers = lg.info, lg.output, lg.warn, lg.error, lg.debug
_loggers = tuple( makeListCompatible( logger ) _loggers = tuple( makeListCompatible( logger )
for logger in _loggers ) for logger in _loggers )
+5 -1
View File
@@ -1,8 +1,11 @@
"Module dependency utility functions for Mininet." "Module dependency utility functions for Mininet."
from os import environ
from sys import exit # pylint: disable=redefined-builtin
from mininet.util import quietRun, BaseString from mininet.util import quietRun, BaseString
from mininet.log import info, error, debug from mininet.log import info, error, debug
from os import environ
def lsmod(): def lsmod():
"Return output of lsmod." "Return output of lsmod."
@@ -18,6 +21,7 @@ def modprobe( mod ):
mod: module string""" mod: module string"""
return quietRun( [ 'modprobe', mod ] ) return quietRun( [ 'modprobe', mod ] )
OF_KMOD = 'ofdatapath' OF_KMOD = 'ofdatapath'
OVS_KMOD = 'openvswitch_mod' # Renamed 'openvswitch' in OVS 1.7+/Linux 3.5+ OVS_KMOD = 'openvswitch_mod' # Renamed 'openvswitch' in OVS 1.7+/Linux 3.5+
TUN = 'tun' TUN = 'tun'
+2
View File
@@ -92,6 +92,7 @@ import select
import signal import signal
import random import random
from sys import exit # pylint: disable=redefined-builtin
from time import sleep from time import sleep
from itertools import chain, groupby from itertools import chain, groupby
from math import ceil from math import ceil
@@ -113,6 +114,7 @@ VERSION = "2.3.0a1"
class Mininet( object ): class Mininet( object ):
"Network emulation with hosts spawned in network namespaces." "Network emulation with hosts spawned in network namespaces."
# pylint: disable=too-many-arguments
def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host, def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
controller=DefaultController, link=Link, intf=Intf, controller=DefaultController, link=Link, intf=Intf,
build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8', build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
+34 -14
View File
@@ -57,7 +57,10 @@ import pty
import re import re
import signal import signal
import select import select
from distutils.version import StrictVersion
from re import findall
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from sys import exit # pylint: disable=redefined-builtin
from time import sleep from time import sleep
from mininet.log import info, error, warn, debug from mininet.log import info, error, warn, debug
@@ -66,8 +69,10 @@ from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
encode, getincrementaldecoder, Python3, which ) encode, getincrementaldecoder, Python3, which )
from mininet.moduledeps import moduleDeps, pathCheck, TUN from mininet.moduledeps import moduleDeps, pathCheck, TUN
from mininet.link import Link, Intf, TCIntf, OVSIntf from mininet.link import Link, Intf, TCIntf, OVSIntf
from re import findall
from distutils.version import StrictVersion
# pylint: disable=too-many-arguments
class Node( object ): class Node( object ):
"""A virtual network node is simply a shell in a network namespace. """A virtual network node is simply a shell in a network namespace.
@@ -94,9 +99,13 @@ class Node( object ):
# Stash configuration parameters for future reference # Stash configuration parameters for future reference
self.params = params self.params = params
self.intfs = {} # dict of port numbers to interfaces # dict of port numbers to interfacse
self.ports = {} # dict of interfaces to port numbers self.intfs = {}
# replace with Port objects, eventually ?
# dict of interfaces to port numbers
# todo: replace with Port objects, eventually ?
self.ports = {}
self.nameToIntf = {} # dict of interface names to Intfs self.nameToIntf = {} # dict of interface names to Intfs
# Make pylint happy # Make pylint happy
@@ -284,6 +293,7 @@ class Node( object ):
returns: result of poll()""" returns: result of poll()"""
if len( self.readbuf ) == 0: if len( self.readbuf ) == 0:
return self.pollOut.poll( timeoutms ) return self.pollOut.poll( timeoutms )
return None
def sendCmd( self, *args, **kwargs ): def sendCmd( self, *args, **kwargs ):
"""Send a command, followed by a command to echo a sentinel, """Send a command, followed by a command to echo a sentinel,
@@ -377,6 +387,7 @@ class Node( object ):
return self.waitOutput( verbose ) return self.waitOutput( verbose )
else: else:
warn( '(%s exited - ignoring cmd%s)\n' % ( self, args ) ) warn( '(%s exited - ignoring cmd%s)\n' % ( self, args ) )
return None
def cmdPrint( self, *args): def cmdPrint( self, *args):
"""Call cmd and printing its output """Call cmd and printing its output
@@ -469,6 +480,7 @@ class Node( object ):
else: else:
warn( '*** defaultIntf: warning:', self.name, warn( '*** defaultIntf: warning:', self.name,
'has no interfaces\n' ) 'has no interfaces\n' )
return None
def intf( self, intf=None ): def intf( self, intf=None ):
"""Return our interface object with given string name, """Return our interface object with given string name,
@@ -582,10 +594,10 @@ class Node( object ):
value may also be list or dict""" value may also be list or dict"""
name, value = list( param.items() )[ 0 ] name, value = list( param.items() )[ 0 ]
if value is None: if value is None:
return return None
f = getattr( self, method, None ) f = getattr( self, method, None )
if not f: if not f:
return return None
if isinstance( value, list ): if isinstance( value, list ):
result = f( *value ) result = f( *value )
elif isinstance( value, dict ): elif isinstance( value, dict ):
@@ -653,11 +665,12 @@ class Node( object ):
@classmethod @classmethod
def checkSetup( cls ): def checkSetup( cls ):
"Make sure our class and superclasses are set up" "Make sure our class and superclasses are set up"
while cls and not getattr( cls, 'isSetup', True ): clas = cls
cls.setup() while clas and not getattr( clas, 'isSetup', True ):
cls.isSetup = True clas.setup()
clas.isSetup = True
# Make pylint happy # Make pylint happy
cls = getattr( type( cls ), '__base__', None ) clas = getattr( type( clas ), '__base__', None )
@classmethod @classmethod
def setup( cls ): def setup( cls ):
@@ -838,6 +851,7 @@ class CPULimitedHost( Host ):
errFail( 'cgclassify -g cpuset:/%s %s' % ( errFail( 'cgclassify -g cpuset:/%s %s' % (
self.name, self.pid ) ) self.name, self.pid ) )
# pylint: disable=arguments-differ
def config( self, cpu=-1, cores=None, **params ): def config( self, cpu=-1, cores=None, **params ):
"""cpu: desired overall system CPU fraction """cpu: desired overall system CPU fraction
cores: (real) core(s) this host can run on cores: (real) core(s) this host can run on
@@ -930,6 +944,7 @@ class Switch( Node ):
else: else:
error( '*** Error: %s has execed and cannot accept commands' % error( '*** Error: %s has execed and cannot accept commands' %
self.name ) self.name )
return None
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)"
@@ -1115,6 +1130,7 @@ class OVSSwitch( Switch ):
if self.batch: if self.batch:
cmd = ' '.join( str( arg ).strip() for arg in args ) cmd = ' '.join( str( arg ).strip() for arg in args )
self.commands.append( cmd ) self.commands.append( cmd )
return None
else: else:
return self.cmd( 'ovs-vsctl', *args, **kwargs ) return self.cmd( 'ovs-vsctl', *args, **kwargs )
@@ -1302,7 +1318,7 @@ class OVSBridge( OVSSwitch ):
"Are we forwarding yet?" "Are we forwarding yet?"
if self.stp: if self.stp:
status = self.dpctl( 'show' ) status = self.dpctl( 'show' )
return 'STP_FORWARD' in status and not 'STP_LEARN' in status return 'STP_FORWARD' in status and 'STP_LEARN' not in status
else: else:
return True return True
@@ -1429,6 +1445,7 @@ class Controller( Node ):
' 1>' + cout + ' 2>' + cout + ' &' ) ' 1>' + cout + ' 2>' + cout + ' &' )
self.execed = False self.execed = False
# pylint: disable=arguments-differ,signature-differs
def stop( self, *args, **kwargs ): def stop( self, *args, **kwargs ):
"Stop controller." "Stop controller."
self.cmd( 'kill %' + self.command ) self.cmd( 'kill %' + self.command )
@@ -1479,7 +1496,7 @@ class NOX( Controller ):
warn( 'warning: no NOX modules specified; ' warn( 'warning: no NOX modules specified; '
'running packetdump only\n' ) 'running packetdump only\n' )
noxArgs = [ 'packetdump' ] noxArgs = [ 'packetdump' ]
elif type( noxArgs ) not in ( list, tuple ): elif not isinstance( noxArgs, ( list, tuple ) ):
noxArgs = [ noxArgs ] noxArgs = [ noxArgs ]
if 'NOX_CORE_DIR' not in os.environ: if 'NOX_CORE_DIR' not in os.environ:
@@ -1505,7 +1522,7 @@ class Ryu( Controller ):
warn( 'warning: no Ryu modules specified; ' warn( 'warning: no Ryu modules specified; '
'running simple_switch only\n' ) 'running simple_switch only\n' )
ryuArgs = [ ryuCoreDir + 'simple_switch.py' ] ryuArgs = [ ryuCoreDir + 'simple_switch.py' ]
elif type( ryuArgs ) not in ( list, tuple ): elif not isinstance( ryuArgs, ( list, tuple ) ):
ryuArgs = [ ryuArgs ] ryuArgs = [ ryuArgs ]
Controller.__init__( self, name, Controller.__init__( self, name,
@@ -1532,6 +1549,7 @@ class RemoteController( Controller ):
"Overridden to do nothing." "Overridden to do nothing."
return return
# pylint: disable=arguments-differ
def stop( self ): def stop( self ):
"Overridden to do nothing." "Overridden to do nothing."
return return
@@ -1563,6 +1581,7 @@ class RemoteController( Controller ):
else: else:
return True return True
DefaultControllers = ( Controller, OVSController ) DefaultControllers = ( Controller, OVSController )
def findController( controllers=DefaultControllers ): def findController( controllers=DefaultControllers ):
@@ -1570,6 +1589,7 @@ def findController( controllers=DefaultControllers ):
for controller in controllers: for controller in controllers:
if controller.isAvailable(): if controller.isAvailable():
return controller return controller
return None
def DefaultController( name, controllers=DefaultControllers, **kwargs ): def DefaultController( name, controllers=DefaultControllers, **kwargs ):
"Find a controller that is available and instantiate it" "Find a controller that is available and instantiate it"
+1
View File
@@ -102,6 +102,7 @@ class NAT( Node ):
# hopefully this won't disconnect you # hopefully this won't disconnect you
self.cmd( 'service network-manager restart || netplan apply' ) self.cmd( 'service network-manager restart || netplan apply' )
# pylint: disable=arguments-differ
def config( self, **params ): def config( self, **params ):
"""Configure the NAT and iptables""" """Configure the NAT and iptables"""
+1 -1
View File
@@ -50,7 +50,7 @@ def makeTerm( node, title='Node', term='xterm', display=None, cmd='bash'):
} }
if term not in cmds: if term not in cmds:
error( 'invalid terminal type: %s' % term ) error( 'invalid terminal type: %s' % term )
return return None
display, tunnel = tunnelX11( node, display ) display, tunnel = tunnelX11( node, display )
if display is None: if display is None:
return [] return []
+1
View File
@@ -25,6 +25,7 @@ def runTests( testDir, verbosity=1 ):
.run( testSuite ).wasSuccessful() ) .run( testSuite ).wasSuccessful() )
sys.exit( 0 if success else 1 ) sys.exit( 0 if success else 1 )
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'warning' ) setLogLevel( 'warning' )
# get the directory containing example tests # get the directory containing example tests
+4 -3
View File
@@ -45,7 +45,7 @@ class testOptionsTopoCommon( object ):
@staticmethod @staticmethod
def tearDown(): def tearDown():
"Clean up if necessary" "Clean up if necessary"
if sys.exc_info != ( None, None, None ): if sys.exc_info() != ( None, None, None ):
cleanup() cleanup()
def runOptionsTopoTest( self, n, msg, hopts=None, lopts=None ): def runOptionsTopoTest( self, n, msg, hopts=None, lopts=None ):
@@ -95,7 +95,7 @@ class testOptionsTopoCommon( object ):
CPU_FRACTION = 0.1 CPU_FRACTION = 0.1
CPU_TOLERANCE = 0.8 # CPU fraction below which test should fail CPU_TOLERANCE = 0.8 # CPU fraction below which test should fail
hopts = { 'cpu': CPU_FRACTION } hopts = { 'cpu': CPU_FRACTION }
#self.runOptionsTopoTest( N, hopts=hopts ) # self.runOptionsTopoTest( N, hopts=hopts )
mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ), mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ),
host=CPULimitedHost, switch=self.switchClass, host=CPULimitedHost, switch=self.switchClass,
@@ -118,7 +118,7 @@ class testOptionsTopoCommon( object ):
% ( CPU_FRACTION * 100, hostUsage, N, hoptsStr, % ( CPU_FRACTION * 100, hostUsage, N, hoptsStr,
self.switchClass ) ) self.switchClass ) )
for pct in results: for pct in results:
#divide cpu by 100 to convert from percentage to fraction # divide cpu by 100 to convert from percentage to fraction
self.assertWithinTolerance( pct/100, CPU_FRACTION, self.assertWithinTolerance( pct/100, CPU_FRACTION,
CPU_TOLERANCE, msg ) CPU_TOLERANCE, msg )
@@ -263,6 +263,7 @@ class testOptionsTopoUserspace( testOptionsTopoCommon, unittest.TestCase ):
longMessage = True longMessage = True
switchClass = UserSwitch switchClass = UserSwitch
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'warning' ) setLogLevel( 'warning' )
unittest.main() unittest.main()
+1 -1
View File
@@ -26,7 +26,7 @@ class testSingleSwitchCommon( object ):
@staticmethod @staticmethod
def tearDown(): def tearDown():
"Clean up if necessary" "Clean up if necessary"
if sys.exc_info != ( None, None, None ): if sys.exc_info() != ( None, None, None ):
cleanup() cleanup()
def testMinimal( self ): def testMinimal( self ):
+1
View File
@@ -26,6 +26,7 @@ class TestPtyLeak( unittest.TestCase ):
assert ( host.slave, host.master ) == oldptys assert ( host.slave, host.master ) == oldptys
net.stop() net.stop()
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
cleanup() cleanup()
+2 -1
View File
@@ -24,7 +24,7 @@ class TestSwitchDpidAssignmentOVS( unittest.TestCase ):
"Clean up if necessary" "Clean up if necessary"
# satisfy pylint # satisfy pylint
assert self assert self
if sys.exc_info != ( None, None, None ): if sys.exc_info() != ( None, None, None ):
cleanup() cleanup()
def testDefaultDpid( self ): def testDefaultDpid( self ):
@@ -95,6 +95,7 @@ class testSwitchUserspace( TestSwitchDpidAssignmentOVS ):
"Test dpid assignment of Userspace switch." "Test dpid assignment of Userspace switch."
switchClass = UserSwitch switchClass = UserSwitch
if __name__ == '__main__': if __name__ == '__main__':
setLogLevel( 'warning' ) setLogLevel( 'warning' )
unittest.main() unittest.main()
+1
View File
@@ -35,5 +35,6 @@ class testQuietRun( unittest.TestCase ):
output = quietRun(testQuietRun.getEchoCmd( n ) ) output = quietRun(testQuietRun.getEchoCmd( n ) )
self.assertEqual( n, len( output ) ) self.assertEqual( n, len( output ) )
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+9 -7
View File
@@ -6,14 +6,16 @@ Tests for the Mininet Walkthrough
TODO: missing xterm test TODO: missing xterm test
""" """
import unittest
import os import os
import re import re
from mininet.util import quietRun, pexpect import unittest
from mininet.clean import cleanup
from distutils.version import StrictVersion from distutils.version import StrictVersion
from sys import stdout from sys import stdout
from mininet.util import quietRun, pexpect
from mininet.clean import cleanup
def tsharkVersion(): def tsharkVersion():
"Return tshark version" "Return tshark version"
@@ -74,7 +76,7 @@ class testWalkthrough( unittest.TestCase ):
p.expect( self.prompt ) p.expect( self.prompt )
# net command # net command
p.sendline( 'net' ) p.sendline( 'net' )
expected = [ x for x in nodes ] expected = list( nodes )
while len( expected ) > 0: while len( expected ) > 0:
index = p.expect( expected ) index = p.expect( expected )
node = p.match.group( 0 ) node = p.match.group( 0 )
@@ -110,7 +112,7 @@ class testWalkthrough( unittest.TestCase ):
ifcount = 0 ifcount = 0
while True: while True:
index = p.expect( interfaces ) index = p.expect( interfaces )
if index == 0 or index == 3: if index in (0, 3):
ifcount += 1 ifcount += 1
elif index == 1: elif index == 1:
self.fail( 's1 interface displayed in "h1 ifconfig"' ) self.fail( 's1 interface displayed in "h1 ifconfig"' )
@@ -126,7 +128,7 @@ class testWalkthrough( unittest.TestCase ):
index = p.expect( interfaces ) index = p.expect( interfaces )
if index == 0: if index == 0:
self.fail( 'h1 interface displayed in "s1 ifconfig"' ) self.fail( 'h1 interface displayed in "s1 ifconfig"' )
elif index == 1 or index == 2 or index == 3: elif index in (1, 2, 3):
ifcount += 1 ifcount += 1
else: else:
break break
@@ -309,7 +311,7 @@ class testWalkthrough( unittest.TestCase ):
ifcount = 0 ifcount = 0
while True: while True:
index = p.expect( interfaces ) index = p.expect( interfaces )
if index == 1 or index == 3: if index in (1, 3):
ifcount += 1 ifcount += 1
elif index == 0: elif index == 0:
self.fail( 'h1 interface displayed in "s1 ifconfig"' ) self.fail( 'h1 interface displayed in "s1 ifconfig"' )
+3
View File
@@ -13,6 +13,9 @@ setup for testing, and can even be emulated with the Mininet package.
from mininet.util import irange, natural, naturalSeq from mininet.util import irange, natural, naturalSeq
# pylint: disable=too-many-arguments
class MultiGraph( object ): class MultiGraph( object ):
"Utility class to track nodes and edges - replaces networkx.MultiGraph" "Utility class to track nodes and edges - replaces networkx.MultiGraph"
+15 -11
View File
@@ -1,19 +1,23 @@
"Utility functions for Mininet." "Utility functions for Mininet."
import codecs
import os
import re
import sys
from mininet.log import output, info, error, warn, debug from fcntl import fcntl, F_GETFL, F_SETFL
from functools import partial
from time import sleep from os import O_NONBLOCK
from resource import getrlimit, setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE from resource import getrlimit, setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
from select import poll, POLLIN, POLLHUP from select import poll, POLLIN, POLLHUP
from subprocess import call, check_call, Popen, PIPE, STDOUT from subprocess import call, check_call, Popen, PIPE, STDOUT
import re from sys import exit # pylint: disable=redefined-builtin
from fcntl import fcntl, F_GETFL, F_SETFL from time import sleep
from os import O_NONBLOCK
import os from mininet.log import output, info, error, warn, debug
from functools import partial
import sys # pylint: disable=too-many-arguments
import codecs
# Python 2/3 compatibility # Python 2/3 compatibility
@@ -454,6 +458,7 @@ def pmonitor(popens, timeoutms=500, readline=True,
poller.register( fd, POLLIN ) poller.register( fd, POLLIN )
flags = fcntl( fd, F_GETFL ) flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK ) fcntl( fd, F_SETFL, flags | O_NONBLOCK )
# pylint: disable=too-many-nested-blocks
while popens: while popens:
fds = poller.poll( timeoutms ) fds = poller.poll( timeoutms )
if fds: if fds:
@@ -665,7 +670,6 @@ def ensureRoot():
if os.getuid() != 0: if os.getuid() != 0:
error( '*** Mininet must run as root.\n' ) error( '*** Mininet must run as root.\n' )
exit( 1 ) exit( 1 )
return
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.