update CI workflows: update/fix codecheck; remove Ubuntu 18.04 (#1167)

1. update/fix codecheck

Run workflow with pylint 2.15.7

Add a  bunch of fiddly and mostly cosmetic changes to
make pylint (and make codecheck) happy.

Also try to run pyflakes3 vs. pyflakes

2. remove Ubuntu 18.04

Ubuntu 18.04 has been removed from github actions, so
we remove it from our workflow as well
This commit is contained in:
lantz
2023-04-21 17:37:09 -07:00
committed by GitHub
parent 1169982c0a
commit cf5675876c
22 changed files with 142 additions and 129 deletions
+1 -1
View File
@@ -17,6 +17,6 @@ jobs:
- name: Install Mininet code check dependencies - name: Install Mininet code check dependencies
run: | run: |
PYTHON=`which python` util/install.sh -n PYTHON=`which python` util/install.sh -n
python -m pip install pylint==2.4.4 python -m pip install pylint==2.15.7
- name: Run code check - name: Run code check
run: make codecheck run: make codecheck
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-20.04, ubuntu-18.04] os: [ubuntu-20.04]
python-version: [3.x, 2.x] python-version: [3.x, 2.x]
steps: steps:
- name: Check out Mininet source - name: Check out Mininet source
+14 -13
View File
@@ -16,7 +16,7 @@
#init-hook= #init-hook=
# Profiled execution. # Profiled execution.
profile=no #profile=no
# Add <file or directory> to the black list. It should be a base name, not a # Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times. # path. You may set this option multiple times.
@@ -45,12 +45,13 @@ load-plugins=
# Note: we may want to re-enable some of these at some point, but many of them # Note: we may want to re-enable some of these at some point, but many of them
# are just style issues rather than errors. # are just style issues rather than errors.
# #
disable=pointless-except, invalid-name, super-init-not-called, fixme, star-args, disable=invalid-name, super-init-not-called, fixme,
too-many-instance-attributes, too-few-public-methods, 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,
locally-disabled, locally-enabled, bad-continuation, locally-disabled,
useless-object-inheritance, unnecessary-pass, no-else-return, useless-object-inheritance, unnecessary-pass, no-else-return,
no-else-raise, no-else-continue, super-with-arguments no-else-raise, no-else-continue, super-with-arguments,
consider-using-f-string, unspecified-encoding
# bad-continuation, wrong-import-order # bad-continuation, wrong-import-order
@@ -62,12 +63,12 @@ output-format=colorized
msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}' msg-template='{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'
# Include message's id in output # Include message's id in output
include-ids=yes # include-ids=yes
# Put messages in a separate file for each module / package specified on the # Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be # command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]". # written in a file name "pylint_global.[txt|html]".
files-output=no # files-output=no
# Tells whether to display a full report or only the messages # Tells whether to display a full report or only the messages
reports=no reports=no
@@ -81,7 +82,7 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme
# Add a comment according to your evaluation note. This is used by the global # Add a comment according to your evaluation note. This is used by the global
# evaluation report (R0004). # evaluation report (R0004).
comment=no #comment=no
# Enable the report(s) with the given id(s). # Enable the report(s) with the given id(s).
#enable-report= #enable-report=
@@ -103,7 +104,7 @@ comment=no
[BASIC] [BASIC]
# Required attributes for module, separated by a comma # Required attributes for module, separated by a comma
required-attributes= #required-attributes=
# Regular expression which should only match functions or classes name which do # Regular expression which should only match functions or classes name which do
# not require a docstring # not require a docstring
@@ -144,7 +145,7 @@ good-names=i,j,k,ex,Run,_
bad-names=foo,bar,baz,toto,tutu,tata bad-names=foo,bar,baz,toto,tutu,tata
# List of builtins function names that should not be used, separated by a comma # List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,inpu #bad-functions=map,filter,apply,inpu
# try to find bugs in the code using type inference # try to find bugs in the code using type inference
@@ -161,7 +162,7 @@ ignored-classes=SQLObjec
# When zope mode is activated, add a predefined set of Zope acquired attributes # When zope mode is activated, add a predefined set of Zope acquired attributes
# to generated-members. # to generated-members.
zope=no #zope=no
# List of members which are set dynamically and missed by pylint inference # List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed. # system, and so shouldn't trigger E0201 when accessed.
@@ -199,7 +200,7 @@ additional-builtins=
# List of interface methods to ignore, separated by a comma. This is used for # List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class. # instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by #ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes. # List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp,build defining-attr-methods=__init__,__new__,setUp,build
@@ -221,7 +222,7 @@ max-locals=15
max-returns=6 max-returns=6
# Maximum number of branch for function / method body # Maximum number of branch for function / method body
max-branchs=12 #max-branchs=12
# Maximum number of statements in function / method body # Maximum number of statements in function / method body
max-statements=50 max-statements=50
+2 -2
View File
@@ -26,14 +26,14 @@ clean:
codecheck: $(PYSRC) codecheck: $(PYSRC)
-echo "Running code check" -echo "Running code check"
util/versioncheck.py util/versioncheck.py
pyflakes $(PYSRC) pyflakes3 $(PYSRC) || pyflakes $(PYSRC)
pylint --rcfile=.pylint $(PYSRC) pylint --rcfile=.pylint $(PYSRC)
# Exclude miniedit from pep8 checking for now # Exclude miniedit from pep8 checking for now
pep8 --repeat --ignore=$(P8IGN) `ls $(PYSRC) | grep -v miniedit.py` pep8 --repeat --ignore=$(P8IGN) `ls $(PYSRC) | grep -v miniedit.py`
errcheck: $(PYSRC) errcheck: $(PYSRC)
-echo "Running check for errors only" -echo "Running check for errors only"
pyflakes $(PYSRC) pyflakes3 $(PYSRC) || pyflakes $(PYSRC)
pylint -E --rcfile=.pylint $(PYSRC) pylint -E --rcfile=.pylint $(PYSRC)
test: $(MININET) $(TEST) test: $(MININET) $(TEST)
+3 -2
View File
@@ -189,8 +189,9 @@ class MininetRunner( object ):
customs = {} customs = {}
if os.path.isfile( fileName ): if os.path.isfile( fileName ):
# pylint: disable=exec-used # pylint: disable=exec-used
exec( compile( open( fileName ).read(), fileName, 'exec' ), with open( fileName ) as f:
customs, customs ) exec( compile( f.read(), fileName, 'exec' ),
customs, customs )
for name, val in customs.items(): for name, val in customs.items():
self.setCustom( name, val ) self.setCustom( name, val )
else: else:
+2 -3
View File
@@ -27,9 +27,8 @@ h1.setIP( '10.0.0.1', 8 )
root.setIP( '10.0.0.2', 8 ) root.setIP( '10.0.0.2', 8 )
info( "*** Creating banner file\n" ) info( "*** Creating banner file\n" )
f = open( '/tmp/%s.banner' % h1.name, 'w' ) with open( '/tmp/%s.banner' % h1.name, 'w' ) as f:
f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) ) f.write( 'Welcome to %s at %s\n' % ( h1.name, h1.IP() ) )
f.close()
info( "*** Running sshd\n" ) info( "*** Running sshd\n" )
cmd = '/usr/sbin/sshd -o UseDNS=no -u0 -o "Banner /tmp/%s.banner"' % h1.name cmd = '/usr/sbin/sshd -o UseDNS=no -u0 -o "Banner /tmp/%s.banner"' % h1.name
+7 -5
View File
@@ -82,14 +82,13 @@ import sys
import re import re
from itertools import groupby from itertools import groupby
from operator import attrgetter 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
from mininet.net import Mininet from mininet.net import Mininet
from mininet.topo import LinearTopo from mininet.topo import LinearTopo
from mininet.topolib import TreeTopo from mininet.topolib import TreeTopo
from mininet.util import quietRun, errRun, decode from mininet.util import quietRun, errRun, decode, StrictVersion
from mininet.examples.clustercli import CLI 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
@@ -314,7 +313,7 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
kwargs.update( batch=True ) kwargs.update( batch=True )
super( RemoteOVSSwitch, self ).__init__( *args, **kwargs ) super( RemoteOVSSwitch, self ).__init__( *args, **kwargs )
def isOldOVS( self ): def isOldOVS( self ): # pylint: disable=arguments-differ
"Is remote switch using an old OVS version?" "Is remote switch using an old OVS version?"
cls = type( self ) cls = type( self )
if self.server not in cls.OVSVersions: if self.server not in cls.OVSVersions:
@@ -376,8 +375,9 @@ class RemoteLink( Link ):
Link.stop( self ) Link.stop( self )
self.tunnel = None self.tunnel = None
def makeIntfPair( self, intfname1, intfname2, addr1=None, addr2=None, def makeIntfPair( self, # pylint: disable=arguments-renamed
node1=None, node2=None, deleteIntfs=True ): intfname1, intfname2, addr1=None, addr2=None,
node1=None, node2=None, deleteIntfs=True ):
"""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
@@ -781,7 +781,9 @@ class MininetCluster( Mininet ):
"Popen() for server connections" "Popen() for server connections"
assert self # please pylint assert self # please pylint
old = signal( SIGINT, SIG_IGN ) old = signal( SIGINT, SIG_IGN )
# pylint: disable=consider-using-with
conn = Popen( cmd, stdin=PIPE, stdout=PIPE, close_fds=True ) conn = Popen( cmd, stdin=PIPE, stdout=PIPE, close_fds=True )
# pylint: enable=consider-using-with
signal( SIGINT, old ) signal( SIGINT, old )
return conn return conn
+8 -7
View File
@@ -69,7 +69,10 @@ class Console( Frame ):
self.bindEvents() self.bindEvents()
self.sendCmd( 'export TERM=dumb' ) self.sendCmd( 'export TERM=dumb' )
self.outputHook = None def outputHook( _obj, _text):
return True
self.outputHook = outputHook
def makeWidgets( self ): def makeWidgets( self ):
"Make a label, a text area, and a scroll bar." "Make a label, a text area, and a scroll bar."
@@ -111,10 +114,8 @@ class Console( Frame ):
self.text.insert( 'end', text ) self.text.insert( 'end', text )
self.text.mark_set( 'insert', 'end' ) self.text.mark_set( 'insert', 'end' )
self.text.see( 'insert' ) self.text.see( 'insert' )
outputHook = lambda x, y: True # make pylint happier if callable( self.outputHook ):
if self.outputHook: self.outputHook( self, text )
outputHook = self.outputHook
outputHook( self, text )
def handleKey( self, event ): def handleKey( self, event ):
"If it's an interactive command, send it to the node." "If it's an interactive command, send it to the node."
@@ -294,10 +295,10 @@ class ConsoleApp( Frame ):
'switches': 'Switch', 'switches': 'Switch',
'controllers': 'Controller' 'controllers': 'Controller'
} }
for name in titles: for name, title in titles.items():
nodes = getattr( net, name ) nodes = getattr( net, name )
frame, consoles = self.createConsoles( frame, consoles = self.createConsoles(
cframe, nodes, width, titles[ name ] ) cframe, nodes, width, title )
self.consoles[ name ] = Object( frame=frame, consoles=consoles ) self.consoles[ name ] = Object( frame=frame, consoles=consoles )
self.selected = None self.selected = None
self.select( 'hosts' ) self.select( 'hosts' )
+1 -2
View File
@@ -83,9 +83,8 @@ 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: for datapath, Switch in switches.items():
info( "*** testing", datapath, "datapath\n" ) info( "*** testing", datapath, "datapath\n" )
Switch = switches[ datapath ]
results[ datapath ] = [] results[ datapath ] = []
link = partial( TCLink, delay='30ms', bw=100 ) link = partial( TCLink, delay='30ms', bw=100 )
net = Mininet( topo=topo, switch=Switch, net = Mininet( topo=topo, switch=Switch,
+52 -56
View File
@@ -18,16 +18,15 @@ import os
import re import re
import sys import sys
from distutils.version import StrictVersion
from functools import partial from functools import partial
from optparse import OptionParser from optparse import OptionParser # pylint: disable=deprecated-module
from subprocess import call from subprocess import call
from sys import exit # pylint: disable=redefined-builtin from sys import exit # pylint: disable=redefined-builtin
from mininet.log import info, debug, warn, setLogLevel from mininet.log import info, debug, warn, setLogLevel
from mininet.net import Mininet, VERSION from mininet.net import Mininet, VERSION
from mininet.util import (netParse, ipAdd, quietRun, from mininet.util import (netParse, ipAdd, quietRun,
buildTopo, custom, customClass ) buildTopo, custom, customClass, StrictVersion )
from mininet.term import makeTerm, cleanUpScreens from mininet.term import makeTerm, cleanUpScreens
from mininet.node import (Controller, RemoteController, NOX, OVSController, from mininet.node import (Controller, RemoteController, NOX, OVSController,
CPULimitedHost, Host, Node, CPULimitedHost, Host, Node,
@@ -1363,7 +1362,7 @@ class MiniEdit( Frame ):
# Tools # Tools
for tool in self.tools: for tool in self.tools:
cmd = ( lambda t=tool: self.activate( t ) ) cmd = partial( self.activate, tool )
b = Button( toolbar, text=tool, font=self.smallFont, command=cmd) b = Button( toolbar, text=tool, font=self.smallFont, command=cmd)
if tool in self.images: if tool in self.images:
b.config( height=35, image=self.images[ tool ] ) b.config( height=35, image=self.images[ tool ] )
@@ -1421,10 +1420,7 @@ 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 = globals.get( 'unicode', str )
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()}
if isinstance(text, list): if isinstance(text, list):
@@ -1635,10 +1631,10 @@ class MiniEdit( Frame ):
hostsToSave = [] hostsToSave = []
switchesToSave = [] switchesToSave = []
controllersToSave = [] controllersToSave = []
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
x1, y1 = self.canvas.coords( self.widgetToItem[ widget ] ) x1, y1 = self.canvas.coords( item )
if 'Switch' in tags or 'LegacySwitch' in tags or 'LegacyRouter' in tags: if 'Switch' in tags or 'LegacySwitch' in tags or 'LegacyRouter' in tags:
nodeNum = self.switchOpts[name]['nodeNum'] nodeNum = self.switchOpts[name]['nodeNum']
nodeToSave = {'number':str(nodeNum), nodeToSave = {'number':str(nodeNum),
@@ -1683,14 +1679,13 @@ class MiniEdit( Frame ):
savingDictionary['application'] = self.appPrefs savingDictionary['application'] = self.appPrefs
try: try:
f = open(fileName, 'w') with open(fileName, 'w') as f:
f.write(json.dumps(savingDictionary, sort_keys=True, indent=4, separators=(',', ': '))) f.write(
# pylint: disable=broad-except json.dumps(savingDictionary,
except Exception as er: sort_keys=True,
indent=4, separators=(',', ': ')))
except Exception as er: # pylint: disable=broad-except
warn( er, '\n' ) warn( er, '\n' )
# pylint: enable=broad-except
finally:
f.close()
def exportScript( self ): def exportScript( self ):
"Export command." "Export command."
@@ -1702,7 +1697,7 @@ class MiniEdit( Frame ):
fileName = tkFileDialog.asksaveasfilename(filetypes=myFormats ,title="Export the topology as...") fileName = tkFileDialog.asksaveasfilename(filetypes=myFormats ,title="Export the topology as...")
if len(fileName ) > 0: if len(fileName ) > 0:
# debug( "Now saving under %s\n" % fileName ) # debug( "Now saving under %s\n" % fileName )
f = open(fileName, 'w') f = open(fileName, 'w') # pylint: disable=consider-using-with
f.write("#!/usr/bin/env python\n") f.write("#!/usr/bin/env python\n")
f.write("\n") f.write("\n")
@@ -1718,9 +1713,9 @@ class MiniEdit( Frame ):
f.write("from subprocess import call\n") f.write("from subprocess import call\n")
inBandCtrl = False inBandCtrl = False
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Controller' in tags: if 'Controller' in tags:
opts = self.controllers[name] opts = self.controllers[name]
@@ -1746,9 +1741,9 @@ class MiniEdit( Frame ):
f.write(" ipBase='"+self.appPrefs['ipBase']+"')\n") f.write(" ipBase='"+self.appPrefs['ipBase']+"')\n")
f.write("\n") f.write("\n")
f.write(" info( '*** Adding controller\\n' )\n") f.write(" info( '*** Adding controller\\n' )\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Controller' in tags: if 'Controller' in tags:
opts = self.controllers[name] opts = self.controllers[name]
@@ -1780,9 +1775,9 @@ class MiniEdit( Frame ):
# Save Switches and Hosts # Save Switches and Hosts
f.write(" info( '*** Add switches\\n')\n") f.write(" info( '*** Add switches\\n')\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'LegacyRouter' in tags: if 'LegacyRouter' in tags:
f.write(" "+name+" = net.addHost('"+name+"', cls=Node, ip='0.0.0.0')\n") f.write(" "+name+" = net.addHost('"+name+"', cls=Node, ip='0.0.0.0')\n")
f.write(" "+name+".cmd('sysctl -w net.ipv4.ip_forward=1')\n") f.write(" "+name+".cmd('sysctl -w net.ipv4.ip_forward=1')\n")
@@ -1820,9 +1815,9 @@ class MiniEdit( Frame ):
f.write("\n") f.write("\n")
f.write(" info( '*** Add hosts\\n')\n") f.write(" info( '*** Add hosts\\n')\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Host' in tags: if 'Host' in tags:
opts = self.hostOpts[name] opts = self.hostOpts[name]
ip = None ip = None
@@ -1915,9 +1910,9 @@ class MiniEdit( Frame ):
f.write("\n") f.write("\n")
f.write(" info( '*** Starting switches\\n')\n") f.write(" info( '*** Starting switches\\n')\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags or 'LegacySwitch' in tags: if 'Switch' in tags or 'LegacySwitch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
ctrlList = ",".join(opts['controllers']) ctrlList = ",".join(opts['controllers'])
@@ -1926,9 +1921,9 @@ class MiniEdit( Frame ):
f.write("\n") f.write("\n")
f.write(" info( '*** Post configure switches and hosts\\n')\n") f.write(" info( '*** Post configure switches and hosts\\n')\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
if opts['switchType'] == 'default': if opts['switchType'] == 'default':
@@ -1956,9 +1951,9 @@ class MiniEdit( Frame ):
if 'switchIP' in opts: if 'switchIP' in opts:
if len(opts['switchIP']) > 0: if len(opts['switchIP']) > 0:
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n") f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Host' in tags: if 'Host' in tags:
opts = self.hostOpts[name] opts = self.hostOpts[name]
# Attach vlan interfaces # Attach vlan interfaces
@@ -1980,9 +1975,9 @@ class MiniEdit( Frame ):
if len(nflowValues['nflowTarget']) > 0: if len(nflowValues['nflowTarget']) > 0:
nflowEnabled = False nflowEnabled = False
nflowSwitches = '' nflowSwitches = ''
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
@@ -2004,9 +1999,9 @@ class MiniEdit( Frame ):
if len(sflowValues['sflowTarget']) > 0: if len(sflowValues['sflowTarget']) > 0:
sflowEnabled = False sflowEnabled = False
sflowSwitches = '' sflowSwitches = ''
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
@@ -2021,9 +2016,9 @@ class MiniEdit( Frame ):
f.write("\n") f.write("\n")
f.write(" CLI(net)\n") f.write(" CLI(net)\n")
for widget in self.widgetToItem: for widget, item in self.widgetToItem:
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Host' in tags: if 'Host' in tags:
opts = self.hostOpts[name] opts = self.hostOpts[name]
# Run User Defined Stop Command # Run User Defined Stop Command
@@ -2445,7 +2440,8 @@ class MiniEdit( Frame ):
line3.pack(pady=10 ) line3.pack(pady=10 )
line4.pack(pady=10 ) line4.pack(pady=10 )
line5.pack(pady=10 ) line5.pack(pady=10 )
hide = ( lambda about=about: about.withdraw() ) def hide():
about.withdraw()
self.aboutBox = about self.aboutBox = about
# Hide on close rather than destroying window # Hide on close rather than destroying window
Wm.wm_protocol( about, name='WM_DELETE_WINDOW', func=hide ) Wm.wm_protocol( about, name='WM_DELETE_WINDOW', func=hide )
@@ -2620,9 +2616,9 @@ class MiniEdit( Frame ):
info( 'New controller details for ' + name + ' = ' + str(self.controllers[name]), '\n' ) info( 'New controller details for ' + name + ' = ' + str(self.controllers[name]), '\n' )
# Find references to controller and change name # Find references to controller and change name
if oldName != name: if oldName != name:
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
switchName = widget[ 'text' ] switchName = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
switch = self.switchOpts[switchName] switch = self.switchOpts[switchName]
if oldName in switch['controllers']: if oldName in switch['controllers']:
@@ -2703,9 +2699,9 @@ class MiniEdit( Frame ):
tags = self.canvas.gettags(item) tags = self.canvas.gettags(item)
if 'Controller' in tags: if 'Controller' in tags:
# remove from switch controller lists # remove from switch controller lists
for searchwidget in self.widgetToItem: for searchwidget, searchitem in self.widgetToItem.items():
name = searchwidget[ 'text' ] name = searchwidget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ searchwidget ] ) tags = self.canvas.gettags( searchitem )
if 'Switch' in tags: if 'Switch' in tags:
if widget['text'] in self.switchOpts[name]['controllers']: if widget['text'] in self.switchOpts[name]['controllers']:
self.switchOpts[name]['controllers'].remove(widget['text']) self.switchOpts[name]['controllers'].remove(widget['text'])
@@ -2718,9 +2714,9 @@ class MiniEdit( Frame ):
def buildNodes( self, net): def buildNodes( self, net):
# Make nodes # Make nodes
info( "Getting Hosts and Switches.\n" ) info( "Getting Hosts and Switches.\n" )
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
# debug( name+' has '+str(tags), '\n' ) # debug( name+' has '+str(tags), '\n' )
if 'Switch' in tags: if 'Switch' in tags:
@@ -2934,9 +2930,9 @@ class MiniEdit( Frame ):
def postStartSetup( self ): def postStartSetup( self ):
# Setup host details # Setup host details
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Host' in tags: if 'Host' in tags:
newHost = self.net.get(name) newHost = self.net.get(name)
opts = self.hostOpts[name] opts = self.hostOpts[name]
@@ -2961,9 +2957,9 @@ class MiniEdit( Frame ):
if len(nflowValues['nflowTarget']) > 0: if len(nflowValues['nflowTarget']) > 0:
nflowEnabled = False nflowEnabled = False
nflowSwitches = '' nflowSwitches = ''
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
@@ -2991,9 +2987,9 @@ class MiniEdit( Frame ):
if len(sflowValues['sflowTarget']) > 0: if len(sflowValues['sflowTarget']) > 0:
sflowEnabled = False sflowEnabled = False
sflowSwitches = '' sflowSwitches = ''
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
@@ -3036,9 +3032,9 @@ class MiniEdit( Frame ):
#for switch in self.net.switches: #for switch in self.net.switches:
# info( switch.name + ' ') # info( switch.name + ' ')
# switch.start( self.net.controllers ) # switch.start( self.net.controllers )
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
switchControllers = [] switchControllers = []
@@ -3058,9 +3054,9 @@ class MiniEdit( Frame ):
"Stop network." "Stop network."
if self.net is not None: if self.net is not None:
# Stop host details # Stop host details
for widget in self.widgetToItem: for widget, item in self.widgetToItem.items():
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( item )
if 'Host' in tags: if 'Host' in tags:
newHost = self.net.get(name) newHost = self.net.get(name)
opts = self.hostOpts[name] opts = self.hostOpts[name]
+2 -2
View File
@@ -17,9 +17,9 @@ from mininet.topo import SingleSwitchTopo
from mininet.log import info, setLogLevel from mininet.log import info, setLogLevel
def chunks( l, n ): def chunks( items, n ):
"Divide list l into chunks of size n - thanks Stackoverflow" "Divide list l into chunks of size n - thanks Stackoverflow"
return [ l[ i: i + n ] for i in range( 0, len( l ), n ) ] return [ items[ i: i + n ] for i in range( 0, len( items ), n ) ]
def startpings( host, targetips ): def startpings( host, targetips ):
"Tell host to repeatedly ping targets" "Tell host to repeatedly ping targets"
+4 -3
View File
@@ -18,11 +18,12 @@ from mininet.util import decode
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)...]"
devnull = open( '/dev/null', 'w' ) devnull = open( '/dev/null', 'w' ) # pylint: disable=consider-using-with
tails, fdToFile, fdToHost = {}, {}, {} tails, fdToFile, fdToHost = {}, {}, {}
for h, outfile in outfiles.items(): for h, outfile in outfiles.items():
tail = Popen( [ 'tail', '-f', outfile ], tail = Popen( # pylint: disable=consider-using-with
stdout=PIPE, stderr=devnull ) [ 'tail', '-f', outfile ],
stdout=PIPE, stderr=devnull )
fd = tail.stdout.fileno() fd = tail.stdout.fileno()
tails[ h ] = tail tails[ h ] = tail
fdToFile[ fd ] = tail.stdout fdToFile[ fd ] = tail.stdout
+1 -2
View File
@@ -25,9 +25,8 @@ def treePing64():
switches = { 'reference user': UserSwitch, switches = { 'reference user': UserSwitch,
'Open vSwitch kernel': OVSKernelSwitch } 'Open vSwitch kernel': OVSKernelSwitch }
for name in switches: for name, switch in switches.items():
info( "*** Testing", name, "datapath\n" ) info( "*** Testing", name, "datapath\n" )
switch = switches[ name ]
network = TreeNet( depth=2, fanout=8, switch=switch, network = TreeNet( depth=2, fanout=8, switch=switch,
waitConnected=True ) waitConnected=True )
result = network.run( network.pingAll ) result = network.run( network.pingAll )
+3 -1
View File
@@ -21,7 +21,9 @@ from mininet.util import decode
def sh( cmd ): def sh( cmd ):
"Print a command and send it to the shell" "Print a command and send it to the shell"
info( cmd + '\n' ) info( cmd + '\n' )
result = Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ] p = Popen( # pylint: disable=consider-using-with
[ '/bin/sh', '-c', cmd ], stdout=PIPE )
result = p.communicate()[ 0 ]
return decode( result ) return decode( result )
def killprocs( pattern ): def killprocs( pattern ):
+10 -8
View File
@@ -150,7 +150,7 @@ class CLI( Cmd ):
' mininet> xterm h2\n\n' ' mininet> xterm h2\n\n'
) )
def do_help( self, line ): # pylint: disable=arguments-differ def do_help( self, line ): # pylint: disable=arguments-renamed
"Describe available CLI commands." "Describe available CLI commands."
Cmd.do_help( self, line ) Cmd.do_help( self, line )
if line == '': if line == '':
@@ -352,13 +352,13 @@ class CLI( Cmd ):
error( 'usage: source <file>\n' ) error( 'usage: source <file>\n' )
return return
try: try:
self.inputFile = open( args[ 0 ] ) with open( args[ 0 ] ) as self.inputFile:
while True: while True:
line = self.inputFile.readline() line = self.inputFile.readline()
if len( line ) > 0: if len( line ) > 0:
self.onecmd( line ) self.onecmd( line )
else: else:
break break
except IOError: except IOError:
error( 'error reading file %s\n' % args[ 0 ] ) error( 'error reading file %s\n' % args[ 0 ] )
self.inputFile.close() self.inputFile.close()
@@ -456,12 +456,14 @@ class CLI( Cmd ):
try: try:
bothPoller.poll() bothPoller.poll()
# XXX BL: this doesn't quite do what we want. # XXX BL: this doesn't quite do what we want.
# pylint: disable=condition-evals-to-constant
if False and self.inputFile: if False and self.inputFile:
key = self.inputFile.read( 1 ) key = self.inputFile.read( 1 )
if key != '': if key != '':
node.write( key ) node.write( key )
else: else:
self.inputFile = None self.inputFile = None
# pylint: enable=condition-evals-to-constant
if isReadable( self.inPoller ): if isReadable( self.inPoller ):
key = self.stdin.read( 1 ) key = self.stdin.read( 1 )
node.write( key ) node.write( key )
+5 -6
View File
@@ -316,8 +316,9 @@ 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( # pylint: disable=arguments-renamed,arguments-differ
def config( self, bw=None, delay=None, jitter=None, loss=None, 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,
latency_ms=None, enable_ecn=False, enable_red=False, latency_ms=None, enable_ecn=False, enable_red=False,
@@ -539,9 +540,7 @@ 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: if 'OVSSwitch' not in globals():
OVSSwitch
except NameError:
# pylint: disable=import-outside-toplevel,cyclic-import # pylint: disable=import-outside-toplevel,cyclic-import
from mininet.node import OVSSwitch from mininet.node import OVSSwitch
self.isPatchLink = False self.isPatchLink = False
@@ -551,7 +550,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 # pylint: disable=arguments-renamed, 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:
+1 -1
View File
@@ -201,7 +201,7 @@ class Mininet( object ):
sleep( delay ) sleep( delay )
time += delay time += delay
warn( 'Timed out after %d seconds\n' % time ) warn( 'Timed out after %d seconds\n' % time )
for switch in remaining: for switch in remaining.copy():
if not switch.connected(): if not switch.connected():
warn( 'Warning: %s is not connected to a controller\n' warn( 'Warning: %s is not connected to a controller\n'
% switch.name ) % switch.name )
+3 -3
View File
@@ -57,7 +57,6 @@ import pty
import re import re
import signal import signal
import select import select
from distutils.version import StrictVersion
from re import findall from re import findall
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from sys import exit # pylint: disable=redefined-builtin from sys import exit # pylint: disable=redefined-builtin
@@ -66,7 +65,8 @@ from time import sleep
from mininet.log import info, error, warn, debug from mininet.log import info, error, warn, debug
from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin, from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
numCores, retry, mountCgroups, BaseString, decode, numCores, retry, mountCgroups, BaseString, decode,
encode, getincrementaldecoder, Python3, which ) encode, getincrementaldecoder, Python3, which,
StrictVersion )
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
@@ -219,7 +219,7 @@ class Node( object ):
params: parameters to Popen()""" params: parameters to Popen()"""
# Leave this is as an instance method for now # Leave this is as an instance method for now
assert self assert self
popen = Popen( cmd, **params ) popen = Popen( cmd, **params ) # pylint: disable=consider-using-with
debug( '_popen', cmd, popen.pid ) debug( '_popen', cmd, popen.pid )
return popen return popen
+1 -2
View File
@@ -10,10 +10,9 @@ import os
import re import re
import unittest import unittest
from distutils.version import StrictVersion
from sys import stdout from sys import stdout
from mininet.util import quietRun, pexpect from mininet.util import quietRun, pexpect, StrictVersion
from mininet.clean import cleanup from mininet.clean import cleanup
+4 -2
View File
@@ -336,9 +336,11 @@ class LinearTopo( Topo ):
self.n = n self.n = n
if n == 1: if n == 1:
genHostName = lambda i, j: 'h%s' % i def genHostName( i, _j ):
return 'h%s' % i
else: else:
genHostName = lambda i, j: 'h%ss%d' % ( j, i ) def genHostName( i, j ):
return 'h%ss%d' % ( j, i )
lastSwitch = None lastSwitch = None
for i in irange( 1, k ): for i in irange( 1, k ):
+4 -2
View File
@@ -53,9 +53,11 @@ class TorusTopo( Topo ):
raise Exception( 'Please use 3x3 or greater for compatibility ' raise Exception( 'Please use 3x3 or greater for compatibility '
'with 2.1' ) 'with 2.1' )
if n == 1: if n == 1:
genHostName = lambda loc, k: 'h%s' % ( loc ) def genHostName( loc, _k ):
return 'h%s' % ( loc )
else: else:
genHostName = lambda loc, k: 'h%sx%d' % ( loc, k ) def genHostName( loc, k ):
return 'h%sx%d' % ( loc, k )
hosts, switches, dpid = {}, {}, 0 hosts, switches, dpid = {}, {}, 0
# Create and wire interior # Create and wire interior
+13 -5
View File
@@ -46,6 +46,7 @@ if Python3:
"Encode buffer for Python 3" "Encode buffer for Python 3"
return buf.encode( Encoding ) return buf.encode( Encoding )
getincrementaldecoder = codecs.getincrementaldecoder( Encoding ) getincrementaldecoder = codecs.getincrementaldecoder( Encoding )
else: else:
decode, encode = NullCodec.decode, NullCodec.encode decode, encode = NullCodec.decode, NullCodec.encode
@@ -54,11 +55,16 @@ else:
return NullCodec return NullCodec
try: try:
# pylint: disable=import-error import packaging.version # replacement for distutils.version
StrictVersion = packaging.version.parse
except ImportError: # python2.7 lacks ModuleNotFoundError
import distutils.version # pylint: disable=deprecated-module
StrictVersion = distutils.version.StrictVersion
try:
oldpexpect = None oldpexpect = None
import pexpect as oldpexpect import pexpect as oldpexpect # pylint: disable=import-error
# pylint: enable=import-error
class Pexpect( object ): class Pexpect( object ):
"Custom pexpect that is compatible with str" "Custom pexpect that is compatible with str"
@staticmethod @staticmethod
@@ -97,11 +103,12 @@ def oldQuietRun( *cmd ):
cmd = cmd[ 0 ] cmd = cmd[ 0 ]
if isinstance( cmd, BaseString ): if isinstance( cmd, BaseString ):
cmd = cmd.split( ' ' ) cmd = cmd.split( ' ' )
popen = Popen( cmd, stdout=PIPE, stderr=STDOUT ) out = ''
popen = Popen( # pylint: disable=consider-using-with
cmd, stdout=PIPE, stderr=STDOUT )
# We can't use Popen.communicate() because it uses # We can't use Popen.communicate() because it uses
# select(), which can't handle # select(), which can't handle
# high file descriptor numbers! poll() can, however. # high file descriptor numbers! poll() can, however.
out = ''
readable = poll() readable = poll()
readable.register( popen.stdout ) readable.register( popen.stdout )
while True: while True:
@@ -142,6 +149,7 @@ def errRun( *cmd, **kwargs ):
elif isinstance( cmd, list ) and shell: elif isinstance( cmd, list ) and shell:
cmd = " ".join( arg for arg in cmd ) cmd = " ".join( arg for arg in cmd )
debug( '*** errRun:', cmd, '\n' ) debug( '*** errRun:', cmd, '\n' )
# pylint: disable=consider-using-with
popen = Popen( cmd, stdout=PIPE, stderr=stderr, shell=shell ) popen = Popen( cmd, stdout=PIPE, stderr=stderr, shell=shell )
# We use poll() because select() doesn't work with large fd numbers, # We use poll() because select() doesn't work with large fd numbers,
# and thus communicate() doesn't work either # and thus communicate() doesn't work either