Revision b1ec912d

View differences:

examples/cluster.py
87 87
from subprocess import Popen, PIPE, STDOUT
88 88
import os
89 89
from random import randrange
90
from sys import exit
90
import sys
91 91
import re
92 92

  
93 93
from distutils.version import StrictVersion
......
282 282
        cls = type( self )
283 283
        if self.server not in cls.OVSVersions:
284 284
            vers = self.cmd( 'ovs-vsctl --version' )
285
            cls.OVSVersions[ self.server ] = re.findall( '\d+\.\d+', vers )[ 0 ]
285
            cls.OVSVersions[ self.server ] = re.findall( r'\d+\.\d+', vers )[ 0 ]
286 286
        return ( StrictVersion( cls.OVSVersions[ self.server ] ) <
287 287
                StrictVersion( '1.10' ) )
288 288

  
......
387 387
            tunnel.wait()
388 388
            error( ch + tunnel.stdout.read() )
389 389
            error( tunnel.stderr.read() )
390
            exit( 1 )
390
            sys.exit( 1 )
391 391
        # 3. Move interfaces if necessary
392 392
        for node in node1, node2:
393 393
            if node.inNamespace:
......
643 643
        for server in self.servers:
644 644
            ip = self.serverIP[ server ]
645 645
            if not server or server == 'localhost':
646
                 continue
646
                continue
647 647
            info( server, '' )
648 648
            dest = '%s@%s' % ( self.user, ip )
649 649
            cmd = [ 'sudo', '-E', '-u', self.user ]
......
660 660
                   '*** Make sure that the above ssh command works correctly.\n'
661 661
                   '*** You may also need to run mn -c on all nodes, and/or\n'
662 662
                   '*** use sudo -E.\n' )
663
            exit( 1 )
663
            sys.exit( 1 )
664 664
        info( '\n' )
665 665

  
666 666
    def modifiedaddHost( self, *args, **kwargs ):
......
703 703
        if ( isinstance( controller, Controller)
704 704
             and controller.IP() == '127.0.0.1'
705 705
             and ' eth0:' in controller.cmd( 'ip link show' ) ):
706
             Intf( 'eth0', node=controller ).updateIP()
706
            Intf( 'eth0', node=controller ).updateIP()
707 707
        return controller
708 708

  
709 709
    def buildFromTopo( self, *args, **kwargs ):
mininet/clean.py
10 10
nothing irreplaceable!
11 11
"""
12 12

  
13
from subprocess import Popen, PIPE, check_output as co
13
from subprocess import ( Popen, PIPE, check_output as co,
14
                         CalledProcessError )
14 15
import time
15 16

  
16 17
from mininet.log import info
......
28 29
    # Make sure they are gone
29 30
    while True:
30 31
        try:
31
            pids = co( 'pgrep -f %s' % pattern )
32
        except:
32
            pids = co( [ 'pgrep', '-f', pattern ] )
33
        except CalledProcessError:
33 34
            pids = ''
34 35
        if pids:
35
            sh( 'pkill -f 9 mininet:' )
36
            sh( 'pkill -9 -f %s' % pattern )
36 37
            time.sleep( .5 )
37 38
        else:
38 39
            break
mininet/cli.py
96 96
    # Disable pylint "Unused argument: 'arg's'" messages, as well as
97 97
    # "method could be a function" warning, since each CLI function
98 98
    # must have the same interface
99
    # pylint: disable-msg=R0201
99
    # pylint: disable=R0201
100 100

  
101 101
    helpStr = (
102 102
        'You may also send a command to a node using:\n'
......
128 128
        nodes = ' '.join( sorted( self.mn ) )
129 129
        output( 'available nodes are: \n%s\n' % nodes )
130 130

  
131
    def do_ports( self, line ):
131
    def do_ports( self, _line ):
132 132
        "display ports and interfaces for each switch"
133 133
        dumpPorts( self.mn.switches )
134 134

  
......
142 142
        call( line, shell=True )
143 143

  
144 144
    # do_py() and do_px() need to catch any exception during eval()/exec()
145
    # pylint: disable-msg=W0703
145
    # pylint: disable=W0703
146 146

  
147 147
    def do_py( self, line ):
148 148
        """Evaluate a Python expression.
......
159 159
            output( str( e ) + '\n' )
160 160

  
161 161
    # We are in fact using the exec() pseudo-function
162
    # pylint: disable-msg=W0122
162
    # pylint: disable=W0122
163 163

  
164 164
    def do_px( self, line ):
165 165
        """Execute a Python statement.
......
169 169
        except Exception, e:
170 170
            output( str( e ) + '\n' )
171 171

  
172
    # pylint: enable-msg=W0703,W0122
172
    # pylint: enable=W0703,W0122
173 173

  
174 174
    def do_pingall( self, line ):
175 175
        "Ping between all hosts."
......
346 346
        elapsed = time.time() - start
347 347
        self.stdout.write("*** Elapsed time: %0.6f secs\n" % elapsed)
348 348

  
349
    def do_links( self, line ):
349
    def do_links( self, _line ):
350 350
        "Report on links"
351 351
        for link in self.mn.links:
352 352
            print link, link.status()
......
355 355
        "Starts or stops a switch"
356 356
        args = line.split()
357 357
        if len(args) != 2:
358
            error( 'invalid number of args: switch <switch name> {start, stop}\n' )
358
            error( 'invalid number of args: switch <switch name>'
359
                   '{start, stop}\n' )
359 360
            return
360 361
        sw = args[ 0 ]
361 362
        command = args[ 1 ]
......
397 398
        else:
398 399
            error( '*** Unknown command: %s\n' % line )
399 400

  
400
    # pylint: enable-msg=R0201
401
    # pylint: enable=R0201
401 402

  
402 403
    def waitForNode( self, node ):
403 404
        "Wait for a node to finish, and print its output."
mininet/link.py
33 33
    "Basic interface object that can configure itself."
34 34

  
35 35
    def __init__( self, name, node=None, port=None, link=None,
36
                  mac=None, srcNode=None, **params ):
36
                  mac=None, **params ):
37 37
        """name: interface name (e.g. h1-eth0)
38 38
           node: owning node (where this intf most likely lives)
39 39
           link: parent link if we're part of a link
......
71 71
            return self.ifconfig( ipstr, 'up' )
72 72
        else:
73 73
            if prefixLen is None:
74
                raise Exception( 'No prefix length set for IP address %s' % ( ipstr, ) )
74
                raise Exception( 'No prefix length set for IP address %s'
75
                                 % ( ipstr, ) )
75 76
            self.ip, self.prefixLen = ipstr, prefixLen
76 77
            return self.ifconfig( '%s/%s' % ( ipstr, prefixLen ) )
77 78

  
......
196 197

  
197 198
    def status( self ):
198 199
        "Return intf status as a string"
199
        links, err_, result_ = self.node.pexec( 'ip link show' )
200
        links, _err, _result = self.node.pexec( 'ip link show' )
200 201
        if self.name in links:
201 202
            return "OK"
202 203
        else:
......
419 420

  
420 421
    def intfName( self, node, n ):
421 422
        "Construct a canonical interface name node-ethN for interface n."
423
        # Leave this as an instance method for now
424
        assert self
422 425
        return node.name + '-eth' + repr( n )
423 426

  
424 427
    @classmethod
425
    def makeIntfPair( _cls, intfname1, intfname2, addr1=None, addr2=None ):
428
    def makeIntfPair( cls, intfname1, intfname2, addr1=None, addr2=None ):
426 429
        """Create pair of interfaces
427 430
           intfname1: name of interface 1
428 431
           intfname2: name of interface 2
429 432
           (override this method [and possibly delete()]
430 433
           to change link type)"""
434
        # Leave this as a class method for now
435
        assert cls
431 436
        return makeIntfPair( intfname1, intfname2, addr1, addr2 )
432 437

  
433 438
    def delete( self ):
mininet/log.py
124 124
        self.setLevel( level )
125 125
        self.handlers[ 0 ].setLevel( level )
126 126

  
127
    # pylint: disable-msg=E0202
127
    # pylint: disable=E0202
128 128
    # "An attribute inherited from mininet.log hide this method"
129 129
    # Not sure why this is occurring - this function definitely gets called.
130 130

  
......
142 142
        if self.isEnabledFor( OUTPUT ):
143 143
            self._log( OUTPUT, msg, args, kwargs )
144 144

  
145
    # pylint: enable-msg=E0202
145
    # pylint: enable=E0202
146 146

  
147 147
lg = MininetLogger()
148 148

  
mininet/net.py
98 98

  
99 99
from mininet.cli import CLI
100 100
from mininet.log import info, error, debug, output, warn
101
from mininet.node import Host, OVSKernelSwitch, DefaultController, Controller
101
from mininet.node import ( Node, Host, OVSKernelSwitch, DefaultController,
102
                          Controller )
102 103
from mininet.nodelib import NAT
103 104
from mininet.link import Link, Intf
104 105
from mininet.util import quietRun, fixLimits, numCores, ensureRoot
......
264 265
            self.nameToNode[ name ] = controller_new
265 266
        return controller_new
266 267

  
267
    def addNAT( self, name='nat0', connect=True, inNamespace=False, **params ):
268
    def addNAT( self, name='nat0', connect=True, inNamespace=False,
269
                **params):
270
        """Add a NAT to the Mininet network
271
           name: name of NAT node
272
           connect: switch to connect to | True (s1) | None
273
           inNamespace: create in a network namespace
274
           params: other NAT node params, notably:
275
               ip: used as default gateway address"""
268 276
        nat = self.addHost( name, cls=NAT, inNamespace=inNamespace,
269 277
                            subnet=self.ipBase, **params )
270 278
        # find first switch and create link
271 279
        if connect:
272
            # connect the nat to the first switch
280
            if not isinstance( connect, Node ):
281
                # Use first switch if not specified
282
                connect = self.switches[ 0 ]
283
            # Connect the nat to the switch
273 284
            self.addLink( nat, self.switches[ 0 ] )
274
            # set the default route on hosts
285
            # Set the default route on hosts
275 286
            natIP = nat.params[ 'ip' ].split('/')[ 0 ]
276 287
            for host in self.hosts:
277 288
                if host.inNamespace:
......
486 497
            info( '*** Stopping %i terms\n' % len( self.terms ) )
487 498
            self.stopXterms()
488 499
        info( '*** Stopping %i switches\n' % len( self.switches ) )
489
        for swclass, switches in groupby( sorted( self.switches, key=type ), type ):
500
        for swclass, switches in groupby(
501
                sorted( self.switches, key=type ), type ):
490 502
            if hasattr( swclass, 'batchShutdown' ):
491 503
                swclass.batchShutdown( switches )
492 504
        for switch in self.switches:
......
521 533
        if hosts is None:
522 534
            hosts = self.hosts
523 535
        poller = select.poll()
524
        Node = hosts[ 0 ]  # so we can call class method fdToNode
536
        h1 = hosts[ 0 ]  # so we can call class method fdToNode
525 537
        for host in hosts:
526 538
            poller.register( host.stdout )
527 539
        while True:
528 540
            ready = poller.poll( timeoutms )
529 541
            for fd, event in ready:
530
                host = Node.fdToNode( fd )
542
                host = h1.fdToNode( fd )
531 543
                if event & select.POLLIN:
532 544
                    line = host.readline()
533 545
                    if line is not None:
......
574 586
                    if timeout:
575 587
                        opts = '-W %s' % timeout
576 588
                    if dest.intfs:
577
                        result = node.cmd( 'ping -c1 %s %s' % (opts, dest.IP()) )
589
                        result = node.cmd( 'ping -c1 %s %s' %
590
                                           (opts, dest.IP()) )
578 591
                        sent, received = self._parsePing( result )
579 592
                    else:
580 593
                        sent, received = 0, 0
......
699 712

  
700 713
    # XXX This should be cleaned up
701 714

  
702
    def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', format=None,
715
    def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', fmt=None,
703 716
               seconds=5):
704 717
        """Run iperf between two hosts.
705
           hosts: list of hosts; if None, uses opposite hosts
718
           hosts: list of hosts; if None, uses first and last hosts
706 719
           l4Type: string, one of [ TCP, UDP ]
707 720
           udpBw: bandwidth target for UDP test
708
           format: iperf format argument if any
721
           fmt: iperf format argument if any
709 722
           seconds: iperf time to transmit
710 723
           returns: two-element array of [ server, client ] speeds
711 724
           note: send() is buffered, so client rate can be much higher than
......
729 742
            bwArgs = '-b ' + udpBw + ' '
730 743
        elif l4Type != 'TCP':
731 744
            raise Exception( 'Unexpected l4 type: %s' % l4Type )
732
        if format:
733
          iperfArgs += '-f %s ' %format
745
        if fmt:
746
            iperfArgs += '-f %s ' % fmt
734 747
        server.sendCmd( iperfArgs + '-s', printPid=True )
735 748
        servout = ''
736 749
        while server.lastPid is None:
......
755 768
    def runCpuLimitTest( self, cpu, duration=5 ):
756 769
        """run CPU limit test with 'while true' processes.
757 770
        cpu: desired CPU fraction of each host
758
        duration: test duration in seconds
771
        duration: test duration in seconds (integer)
759 772
        returns a single list of measured CPU fractions as floats.
760 773
        """
761 774
        cores = int( quietRun( 'nproc' ) )
......
776 789
        # get the initial cpu time for each host
777 790
        for host in hosts:
778 791
            outputs[ host ] = []
779
            with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host, 'r' ) as f:
792
            with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' %
793
                       host, 'r' ) as f:
780 794
                time[ host ] = float( f.read() )
781
        for _ in range( 5 ):
795
        for _ in range( duration ):
782 796
            sleep( 1 )
783 797
            for host in hosts:
784
                with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' % host, 'r' ) as f:
798
                with open( '/sys/fs/cgroup/cpuacct/%s/cpuacct.usage' %
799
                           host, 'r' ) as f:
785 800
                    readTime = float( f.read() )
786 801
                outputs[ host ].append( ( ( readTime - time[ host ] )
787 802
                                        / 1000000000 ) / cores * 100 )
mininet/node.py
189 189
        """Internal method: spawn and return a process
190 190
            cmd: command to run (list)
191 191
            params: parameters to Popen()"""
192
        # Leave this is as an instance method for now
193
        assert self
192 194
        return Popen( cmd, **params )
193 195

  
194 196
    def cleanup( self ):
......
240 242
                os.killpg( self.shell.pid, signal.SIGHUP )
241 243
        self.cleanup()
242 244

  
243
    def stop( self ):
244
        "Stop node."
245
    def stop( self, deleteIntfs=False ):
246
        """Stop node.
247
           deleteIntfs: delete interfaces? (False)"""
248
        if deleteIntfs:
249
            self.deleteIntfs()
245 250
        self.terminate()
246 251

  
247 252
    def waitReadable( self, timeoutms=None ):
......
324 329
        log = info if verbose else debug
325 330
        output = ''
326 331
        while self.waiting:
327
            data = self.monitor()
332
            data = self.monitor( findPid=findPid )
328 333
            output += data
329 334
            log( data )
330 335
        return output
......
421 426
            warn( '*** defaultIntf: warning:', self.name,
422 427
                  'has no interfaces\n' )
423 428

  
424
    def intf( self, intf='' ):
429
    def intf( self, intf=None ):
425 430
        """Return our interface object with given string name,
426 431
           default intf if name is falsy (None, empty string, etc).
427 432
           or the input intf arg.
......
682 687
            if int( self.cgroupGet( 'rt_runtime_us', 'cpu' ) ) <= 0:
683 688
                mncmd += [ '-r', str( self.rtprio ) ]
684 689
            else:
685
                debug( '*** error: not enough cpu time available for %s.' % self.name,
686
                      'Using cfs scheduler for subprocess\n' )
690
                debug( '*** error: not enough cpu time available for %s.' %
691
                       self.name, 'Using cfs scheduler for subprocess\n' )
687 692
        return Host.popen( self, *args, mncmd=mncmd, **kwargs )
688 693

  
689 694
    def cleanup( self ):
......
698 703
        "Check (Ubuntu,Debian) kernel config for CONFIG_RT_GROUP_SCHED for RT"
699 704
        if not cls._rtGroupSched:
700 705
            release = quietRun( 'uname -r' ).strip('\r\n')
701
            output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s' % release )
706
            output = quietRun( 'grep CONFIG_RT_GROUP_SCHED /boot/config-%s' %
707
                               release )
702 708
            if output == '# CONFIG_RT_GROUP_SCHED is not set\n':
703
                error( '\n*** error: please enable RT_GROUP_SCHED in your kernel\n' )
709
                error( '\n*** error: please enable RT_GROUP_SCHED'
710
                       'in your kernel\n' )
704 711
                exit( 1 )
705 712
            cls._rtGroupSched = True
706 713

  
......
755 762
            sched = self.sched
756 763
        if sched == 'rt':
757 764
            if not f or f < 0:
758
                raise Exception( 'Please set a positive CPU fraction for sched=rt\n' )
759
                return
765
                raise Exception( 'Please set a positive CPU fraction'
766
                                 ' for sched=rt\n' )
760 767
            pstr, qstr, period, quota = self.rtInfo( f )
761 768
        elif sched == 'cfs':
762 769
            pstr, qstr, period, quota = self.cfsInfo( f )
......
881 888

  
882 889
    def connected( self ):
883 890
        "Is the switch connected to a controller? (override this method)"
884
        return False and self  # satisfy pylint
891
        raise NotImplementedError( "connected() needs to be implemented in"
892
                                   " Switch subclass %s" % self.__class__ )
885 893

  
886 894
    def __repr__( self ):
887 895
        "More informative string representation"
......
890 898
        return '<%s %s: %s pid=%s> ' % (
891 899
            self.__class__.__name__, self.name, intfs, self.pid )
892 900

  
901

  
893 902
class UserSwitch( Switch ):
894 903
    "User-space switch."
895 904

  
......
982 991
                    self.TCReapply( intf )
983 992

  
984 993
    def stop( self, deleteIntfs=True ):
985
        "Stop OpenFlow reference user datapath."
994
        """Stop OpenFlow reference user datapath.
995
           deleteIntfs: delete interfaces? (True)"""
986 996
        self.cmd( 'kill %ofdatapath' )
987 997
        self.cmd( 'kill %ofprotocol' )
988 998
        if deleteIntfs:
......
1033 1043
        self.execed = False
1034 1044

  
1035 1045
    def stop( self, deleteIntfs=True ):
1036
        "Terminate kernel datapath."
1046
        """Terminate kernel datapath."
1047
           deleteIntfs: delete interfaces? (True)"""
1037 1048
        quietRun( 'ovs-dpctl del-dp ' + self.dp )
1038 1049
        self.cmd( 'kill %ovs-openflowd' )
1039 1050
        if deleteIntfs:
......
1075 1086
                   'You may wish to try '
1076 1087
                   '"service openvswitch-switch start".\n' )
1077 1088
            exit( 1 )
1078
        info = quietRun( 'ovs-vsctl --version' )
1079
        cls.OVSVersion =  findall( '\d+\.\d+', info )[ 0 ]
1089
        version = quietRun( 'ovs-vsctl --version' )
1090
        cls.OVSVersion =  findall( r'\d+\.\d+', version )[ 0 ]
1080 1091

  
1081 1092
    @classmethod
1082 1093
    def isOldOVS( cls ):
1094
        "Is OVS ersion < 1.10?"
1083 1095
        return ( StrictVersion( cls.OVSVersion ) <
1084 1096
             StrictVersion( '1.10' ) )
1085 1097

  
......
1186 1198

  
1187 1199

  
1188 1200
    def stop( self, deleteIntfs=True ):
1189
        "Terminate OVS switch."
1201
        """Terminate OVS switch.
1202
           deleteIntfs: delete interfaces? (True)"""
1190 1203
        self.cmd( 'ovs-vsctl del-br', self )
1191 1204
        if self.datapath == 'user':
1192 1205
            self.cmd( 'ip link del', self )
......
1255 1268
        self.cmd( ' '.join(args) + ' >' + logfile + ' 2>&1 </dev/null &' )
1256 1269

  
1257 1270
    def stop( self, deleteIntfs=True ):
1258
        "Terminate IVS switch."
1271
        """Terminate IVS switch.
1272
           deleteIntfs: delete interfaces? (True)"""
1259 1273
        self.cmd( 'kill %ivs' )
1260 1274
        self.cmd( 'wait' )
1261 1275
        if deleteIntfs:
......
1276 1290
        return self.cmd( 'ovs-ofctl ' + ' '.join( args ) +
1277 1291
                         ' tcp:127.0.0.1:%i' % self.listenPort )
1278 1292

  
1293
    def connected( self ):
1294
        "For now, return True since we can't tell if we're connected"
1295
        return True
1296

  
1279 1297

  
1280 1298
class Controller( Node ):
1281 1299
    """A Controller is a Node that is running (or has execed?) an
......
1323 1341
                  ' 1>' + cout + ' 2>' + cout + ' &' )
1324 1342
        self.execed = False
1325 1343

  
1326
    def stop( self ):
1344
    def stop( self, *args, **kwargs ):
1327 1345
        "Stop controller."
1328 1346
        self.cmd( 'kill %' + self.command )
1329 1347
        self.cmd( 'wait %' + self.command )
1330
        self.terminate()
1348
        super( Controller, self ).stop( *args, **kwargs )
1331 1349

  
1332 1350
    def IP( self, intf=None ):
1333 1351
        "Return IP address of the Controller"
......
1343 1361
            self.__class__.__name__, self.name,
1344 1362
            self.IP(), self.port, self.pid )
1345 1363
    @classmethod
1346
    def isAvailable( self ):
1364
    def isAvailable( cls ):
1365
        "Is controller available?"
1347 1366
        return quietRun( 'which controller' )
1348 1367

  
1349 1368
class OVSController( Controller ):
......
1353 1372
            command = 'test-controller'
1354 1373
        Controller.__init__( self, name, command=command, **kwargs )
1355 1374
    @classmethod
1356
    def isAvailable( self ):
1357
        return quietRun( 'which ovs-controller' ) or quietRun( 'which test-controller' )
1375
    def isAvailable( cls ):
1376
        return ( quietRun( 'which ovs-controller' ) or
1377
                 quietRun( 'which test-controller' ) )
1358 1378

  
1359 1379
class NOX( Controller ):
1360 1380
    "Controller to run a NOX application."
......
1432 1452
                  " at %s:%d\n" % ( self.ip, self.port ) )
1433 1453

  
1434 1454

  
1435
DefaultControllers = [ Controller, OVSController ]
1455
DefaultControllers = ( Controller, OVSController )
1436 1456

  
1437 1457
def findController( controllers=DefaultControllers ):
1438 1458
    "Return first available controller from list, if any"
......
1446 1466
    if not controller:
1447 1467
        raise Exception( 'Could not find a default OpenFlow controller' )
1448 1468
    return controller( name, **kwargs )
1449

  
mininet/nodelib.py
33 33
        else:
34 34
            return True
35 35

  
36
    def start( self, controllers ):
36
    def start( self, _controllers ):
37 37
        "Start Linux bridge"
38 38
        self.cmd( 'ifconfig', self, 'down' )
39 39
        self.cmd( 'brctl delbr', self )
......
62 62

  
63 63

  
64 64
class NAT( Node ):
65
    """NAT: Provides connectivity to external network"""
65
    "NAT: Provides connectivity to external network"
66 66

  
67
    def __init__( self, name, inetIntf=None, subnet='10.0/8', localIntf=None, **params):
67
    def __init__( self, name, inetIntf=None, subnet='10.0/8',
68
                  localIntf=None, **params):
69
        """Start NAT/forwarding between Mininet and external network
70
           inetIntf: interface for internet access
71
           subnet: Mininet subnet (default 10.0/8)="""
68 72
        super( NAT, self ).__init__( name, **params )
69 73

  
70
        """Start NAT/forwarding between Mininet and external network
71
        inetIntf: interface for internet access
72
        subnet: Mininet subnet (default 10.0/8)="""
73 74
        self.inetIntf = inetIntf if inetIntf else self.getGatewayIntf()
74 75
        self.subnet = subnet
75 76
        self.localIntf = localIntf
76 77

  
77 78
    def config( self, **params ):
78
        super( NAT, self).config( **params )
79 79
        """Configure the NAT and iptables"""
80
        super( NAT, self).config( **params )
80 81

  
81 82
        if not self.localIntf:
82 83
            self.localIntf =  self.defaultIntf()
......
94 95
        self.cmd( 'iptables -P FORWARD DROP' )
95 96

  
96 97
        # Configure NAT
97
        self.cmd( 'iptables -I FORWARD -i', self.localIntf, '-d', self.subnet, '-j DROP' )
98
        self.cmd( 'iptables -A FORWARD -i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
99
        self.cmd( 'iptables -A FORWARD -i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' )
100
        self.cmd( 'iptables -t nat -A POSTROUTING -o ', self.inetIntf, '-s', self.subnet, '-j MASQUERADE' )
98
        self.cmd( 'iptables -I FORWARD',
99
                  '-i', self.localIntf, '-d', self.subnet, '-j DROP' )
100
        self.cmd( 'iptables -A FORWARD',
101
                  '-i', self.localIntf, '-s', self.subnet, '-j ACCEPT' )
102
        self.cmd( 'iptables -A FORWARD',
103
                  '-i', self.inetIntf, '-d', self.subnet, '-j ACCEPT' )
104
        self.cmd( 'iptables -t nat -A POSTROUTING',
105
                  '-o', self.inetIntf, '-s', self.subnet, '-j MASQUERADE' )
101 106

  
102 107
        # Instruct the kernel to perform forwarding
103 108
        self.cmd( 'sysctl net.ipv4.ip_forward=1' )
......
116 121
        # hopefully this won't disconnect you
117 122
        self.cmd( 'service network-manager restart' )
118 123

  
119
    def getGatewayIntf( self ):
124
    def getGatewayIntf( self, fallback='eth0' ):
125
        """Return gateway interface name
126
           fallback: default device to fall back to"""
120 127
        routes = self.cmd( 'ip route show' )
121
        match = re.search('default via \S+ dev (\S+)', routes )
128
        match = re.search( r'default via \S+ dev (\S+)', routes )
122 129
        if match:
123 130
            return match.group( 1 )
124 131
        else:
125
            warn( 'There is no default route set. Using eth0 as gateway interface...\n' )
126
            return 'eth0'
132
            warn( 'There is no default route set.',
133
                  'Using', fallback, 'as gateway interface...\n' )
134
            return fallback
127 135

  
128 136
    def terminate( self ):
129 137
        """Stop NAT/forwarding between Mininet and external network"""
......
136 144
        self.cmd( 'sysctl net.ipv4.ip_forward=0' )
137 145

  
138 146
        super( NAT, self ).terminate()
139

  
mininet/topo.py
111 111
        self.hopts = params.pop( 'hopts', {} )
112 112
        self.sopts = params.pop( 'sopts', {} )
113 113
        self.lopts = params.pop( 'lopts', {} )
114
        self.ports = {}  # ports[src][dst][sport] is port on dst that connects to src
114
        # ports[src][dst][sport] is port on dst that connects to src
115
        self.ports = {}
115 116
        self.build( *args, **params )
116 117

  
117 118
    def build( self, *args, **params ):
......
187 188
           withKeys: return link keys
188 189
           withInfo: return link info
189 190
           returns: list of ( src, dst [,key, info ] )"""
190
        for src, dst, key, info in self.g.edges_iter( data=True, keys=True ):
191
        for _src, _dst, key, info in self.g.edges_iter( data=True, keys=True ):
191 192
            node1, node2 = info[ 'node1' ], info[ 'node2' ]
192 193
            if withKeys:
193 194
                if withInfo:
......
207 208
           withInfo: return link info
208 209
           returns: list of ( src, dst [,key, info ] )"""
209 210
        links = list( self.iterLinks( withKeys, withInfo ) )
210
        if not sorted:
211
        if not sort:
211 212
            return links
212 213
        # Ignore info when sorting
213 214
        tupleSize = 3 if withKeys else 2
......
287 288
        return sorted( items, key=natural )
288 289

  
289 290

  
291
# Our idiom defines additional parameters in build(param...)
292
# pylint: disable=arguments-differ, attribute-defined-outside-init
293

  
290 294
class SingleSwitchTopo( Topo ):
291 295
    "Single switch connected to k hosts."
292 296

  
293
    def build( self, k=2, **opts ):
297
    def build( self, k=2, **_opts ):
294 298
        "k: number of hosts"
295 299
        self.k = k
296 300
        switch = self.addSwitch( 's1' )
......
317 321
class LinearTopo( Topo ):
318 322
    "Linear topology of k switches, with n hosts per switch."
319 323

  
320
    def build( self, k=2, n=1, **opts):
324
    def build( self, k=2, n=1, **_opts):
321 325
        """k: number of switches
322 326
           n: number of hosts per switch"""
323 327
        self.k = k
......
340 344
            if lastSwitch:
341 345
                self.addLink( switch, lastSwitch )
342 346
            lastSwitch = switch
347

  
348
# pylint: enable=arguments-differ, attribute-defined-outside-init
mininet/topolib.py
3 3
from mininet.topo import Topo
4 4
from mininet.net import Mininet
5 5

  
6
# The build() method is expected to do both of these things:
7
# pylint: disable=attribute-defined-outside-init, arguments-differ
8

  
6 9
class TreeTopo( Topo ):
7 10
    "Topology for a tree network with a given depth and fanout."
8 11

  
......
53 56
                loc = '%dx%d' % ( i + 1, j + 1 )
54 57
                # dpid cannot be zero for OVS
55 58
                dpid = ( i + 1 ) * 256 + ( j + 1 )
56
                switch = switches[ i, j ] = self.addSwitch( 's' + loc, dpid='%016x' % dpid )
59
                switch = switches[ i, j ] = self.addSwitch(
60
                    's' + loc, dpid='%016x' % dpid )
57 61
                host = hosts[ i, j ] = self.addHost( 'h' + loc )
58 62
                self.addLink( host, switch )
59 63
        # Connect switches
......
65 69
                self.addLink( sw1, sw2 )
66 70
                self.addLink( sw1, sw3 )
67 71

  
68

  
69

  
72
# pylint: enable=attribute-defined-outside-init, arguments-differ
mininet/util.py
25 25
    return check_call( cmd.split( ' ' ) )
26 26

  
27 27
# pylint doesn't understand explicit type checking
28
# pylint: disable-msg=E1103
28
# pylint: disable=E1103
29 29

  
30 30
def oldQuietRun( *cmd ):
31 31
    """Run a command, routing stderr to stdout, and return the output.
......
119 119
    "Run a command and return merged stdout and stderr"
120 120
    return errRun( cmd, stderr=STDOUT, **kwargs )[ 0 ]
121 121

  
122
# pylint: enable-msg=E1103
123
# pylint: disable-msg=E1101
122
# pylint: enable=E1103
123
# pylint: disable=E1101
124 124

  
125 125
def isShellBuiltin( cmd ):
126 126
    "Return True if cmd is a bash builtin."
......
133 133

  
134 134
isShellBuiltin.builtIns = None
135 135

  
136
# pylint: enable-msg=E1101
136
# pylint: enable=E1101
137 137

  
138 138
# Interface management
139 139
#
......
148 148
# live in the root namespace and thus do not have to be
149 149
# explicitly moved.
150 150

  
151
def makeIntfPair( intf1, intf2, addr1=None, addr2=None, run=quietRun ):
151
def makeIntfPair( intf1, intf2, addr1=None, addr2=None, runCmd=quietRun ):
152 152
    """Make a veth pair connecting intf1 and intf2.
153 153
       intf1: string, interface
154 154
       intf2: string, interface
155
       node: node to run on or None (default)
155
       runCmd: function to run shell commands (quietRun)
156 156
       returns: ip link add result"""
157 157
    # Delete any old interfaces with the same names
158
    run( 'ip link del ' + intf1 )
159
    run( 'ip link del ' + intf2 )
158
    runCmd( 'ip link del ' + intf1 )
159
    runCmd( 'ip link del ' + intf2 )
160 160
    # Create new pair
161 161
    if addr1 is None and addr2 is None:
162 162
        cmd = 'ip link add name ' + intf1 + ' type veth peer name ' + intf2
163 163
    else:
164 164
        cmd = ( 'ip link add name ' + intf1 + ' address ' + addr1 +
165 165
                ' type veth peer name ' + intf2 + ' address ' + addr2 )
166
    cmdOutput = run( cmd )
166
    cmdOutput = runCmd( cmd )
167 167
    if cmdOutput == '':
168 168
        return True
169 169
    else:
......
202 202
        return False
203 203
    return True
204 204

  
205
def moveIntf( intf, dstNode, srcNode=None, printError=True,
205
def moveIntf( intf, dstNode, printError=True,
206 206
             retries=3, delaySecs=0.001 ):
207 207
    """Move interface to node, retrying on failure.
208 208
       intf: string, interface
......
296 296
def ipParse( ip ):
297 297
    "Parse an IP address and return an unsigned int."
298 298
    args = [ int( arg ) for arg in ip.split( '.' ) ]
299
    while ( len(args) < 4 ):
299
    while len(args) < 4:
300 300
        args.append( 0 )
301 301
    return ipNum( *args )
302 302

  
......
427 427
        sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 )
428 428
        #Increase number of PTYs for nodes
429 429
        sysctlTestAndSet( 'kernel.pty.max', 20000 )
430
    except:
430
    except Exception:
431 431
        warn( "*** Error setting resource limits. "
432 432
              "Mininet's performance may be affected.\n" )
433 433

  
......
545 545
def waitListening( client=None, server='127.0.0.1', port=80, timeout=None ):
546 546
    """Wait until server is listening on port.
547 547
       returns True if server is listening"""
548
    run = ( client.cmd if client else
548
    runCmd = ( client.cmd if client else
549 549
                partial( quietRun, shell=True ) )
550
    if not run( 'which telnet' ):
550
    if not runCmd( 'which telnet' ):
551 551
        raise Exception('Could not find telnet' )
552 552
    serverIP = server if isinstance( server, basestring ) else server.IP()
553 553
    cmd = ( 'sh -c "echo A | telnet -e A %s %s"' %

Also available in: Unified diff