diff --git a/bin/mn b/bin/mn index 3edfdad932513109590a19b55fe4677c7a8858bb..b2b2e0de715c6c0406e816fe28dbcc7e068878f5 100755 --- a/bin/mn +++ b/bin/mn @@ -151,6 +151,10 @@ class MininetRunner( object ): "Setup and validate environment." # set logging verbosity + if LEVELS[self.options.verbosity] > LEVELS['cliinfo']: + print ( '*** WARNING: selected verbosity level (%s) will hide CLI ' + 'output!\n' + 'Please restart Mininet with -v [debug, info, cliinfo].' ) lg.setLogLevel( self.options.verbosity ) # validate environment setup diff --git a/mininet/cli.py b/mininet/cli.py index ce2328ac1ee690e1300c55ce24eb994b467feb52..ab9a2c1db86f6b2fdd923f676ed0fa31e9d92cd5 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -38,7 +38,7 @@ from subprocess import call from cmd import Cmd -from mininet.log import info, warn +from mininet.log import info, warn, cliinfo class CLI( Cmd ): "Simple command-line interface to talk to nodes." @@ -84,16 +84,16 @@ def do_help( self, args ): def do_nodes( self, args ): "List all nodes." nodes = ' '.join( [ node.name for node in sorted( self.nodelist ) ] ) - info( 'available nodes are: \n%s\n' % nodes ) + cliinfo( 'available nodes are: \n%s\n' % nodes ) def do_net( self, args ): "List network connections." for switch in self.mn.switches: - info( switch.name, '<->' ) + cliinfo( switch.name, '<->' ) for intf in switch.intfs.values(): name = switch.connection[ intf ][ 1 ] - info( ' %s' % name ) - info( '\n' ) + cliinfo( ' %s' % name ) + cliinfo( '\n' ) def do_sh( self, args ): "Run an external shell command" @@ -128,7 +128,7 @@ def do_pingpair( self, args ): def do_iperf( self, args ): "Simple iperf TCP test between two hosts." - self.mn.iperf( verbose=True ) + self.mn.iperf() def do_iperfudp( self, args ): "Simple iperf UDP test between two hosts." @@ -138,13 +138,13 @@ def do_iperfudp( self, args ): def do_intfs( self, args ): "List interfaces." for node in self.nodelist: - info( '%s: %s\n' % + cliinfo( '%s: %s\n' % ( node.name, ' '.join( sorted( node.intfs.values() ) ) ) ) def do_dump( self, args ): "Dump node info." for node in self.nodelist: - info( '%s\n' % node ) + cliinfo( '%s\n' % node ) def do_exit( self, args ): "Exit" diff --git a/mininet/log.py b/mininet/log.py index f8ed653ef9bd0470a240d82a544a1a05b53ac2a4..5352345454d00b7cb62a4de57e9348dc3e99b63d 100644 --- a/mininet/log.py +++ b/mininet/log.py @@ -4,8 +4,15 @@ from logging import Logger import types +# Create a new loglevel, 'CLI info', which enables a Mininet user to see only +# the output of the commands they execute, plus any errors or warnings. This +# level is in between info and warning. CLI info-level commands should not be +# printed during regression tests. +CLIINFO = 25 + LEVELS = { 'debug': logging.DEBUG, 'info': logging.INFO, + 'cliinfo': CLIINFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'critical': logging.CRITICAL } @@ -119,6 +126,20 @@ def setLogLevel( self, levelname=None ): self.setLevel( level ) self.handlers[ 0 ].setLevel( level ) + # See /usr/lib/python2.5/logging/__init__.py; modified from warning() + def cliinfo( self, msg, *args, **kwargs ): + """Log 'msg % args' with severity 'CLIINFO'. + + To pass exception information, use the keyword argument exc_info + with a true value, e.g. + + logger.warning("Houston, we have a %s", "cli output", exc_info=1) + """ + if self.manager.disable >= CLIINFO: + return + if self.isEnabledFor( CLIINFO ): + apply( self._log, ( CLIINFO, msg, args ), kwargs ) + lg = MininetLogger() @@ -144,5 +165,6 @@ def newfn( *args ): setattr( newfn, '__doc__', fn.__doc__ ) return newfn -info, warn, error, debug = lg.info, lg.warn, lg.error, lg.debug = [ - makeListCompatible( f ) for f in lg.info, lg.warn, lg.error, lg.debug ] +info, cliinfo, warn, error, debug = lg.info, lg.cliinfo, lg.warn, lg.error, \ + lg.debug = [ makeListCompatible( f ) for f in lg.info, lg.cliinfo, lg.warn, + lg.error, lg.debug ] diff --git a/mininet/net.py b/mininet/net.py index a4ed8a57f07680462359e01172c8ea7554e1f36c..39720bbe470761c6b8326ff3437651fb8d8506e0 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -89,7 +89,7 @@ from time import sleep from mininet.cli import CLI -from mininet.log import info, error, debug +from mininet.log import info, error, debug, cliinfo from mininet.node import Host, UserSwitch, KernelSwitch, Controller from mininet.node import ControllerParams from mininet.util import quietRun, fixLimits @@ -402,9 +402,9 @@ def ping( self, hosts=None ): ploss = None if not hosts: hosts = self.hosts - info( '*** Ping: testing ping reachability\n' ) + cliinfo( '*** Ping: testing ping reachability\n' ) for node in hosts: - info( '%s -> ' % node.name ) + cliinfo( '%s -> ' % node.name ) for dest in hosts: if node != dest: result = node.cmd( 'ping -c1 ' + dest.IP() ) @@ -416,10 +416,10 @@ def ping( self, hosts=None ): node.cmdPrint( 'route' ) exit( 1 ) lost += sent - received - info( ( '%s ' % dest.name ) if received else 'X ' ) - info( '\n' ) + cliinfo( ( '%s ' % dest.name ) if received else 'X ' ) + cliinfo( '\n' ) ploss = 100 * lost / packets - info( "*** Results: %i%% dropped (%d/%d lost)\n" % + cliinfo( "*** Results: %i%% dropped (%d/%d lost)\n" % ( ploss, lost, packets ) ) return ploss @@ -446,21 +446,18 @@ def _parseIperf( iperfOutput ): else: raise Exception( 'could not parse iperf output: ' + iperfOutput ) - def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', - verbose=False ): + def iperf( self, hosts=None, l4Type='TCP', udpBw='10M' ): """Run iperf between two hosts. hosts: list of hosts; if None, uses opposite hosts l4Type: string, one of [ TCP, UDP ] - verbose: verbose printing returns: results two-element array of server and client speeds""" - log = info if verbose else debug if not hosts: hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ] else: assert len( hosts ) == 2 host0, host1 = hosts - log( '*** Iperf: testing ' + l4Type + ' bandwidth between ' ) - log( "%s and %s\n" % ( host0.name, host1.name ) ) + cliinfo( '*** Iperf: testing ' + l4Type + ' bandwidth between ' ) + cliinfo( "%s and %s\n" % ( host0.name, host1.name ) ) host0.cmd( 'killall -9 iperf' ) iperfArgs = 'iperf ' bwArgs = '' @@ -470,16 +467,16 @@ def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', elif l4Type != 'TCP': raise Exception( 'Unexpected l4 type: %s' % l4Type ) server = host0.cmd( iperfArgs + '-s &' ) - log( '%s\n' % server ) + debug( '%s\n' % server ) client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' + bwArgs ) - log( '%s\n' % client ) + debug( '%s\n' % client ) server = host0.cmd( 'killall -9 iperf' ) - log( '%s\n' % server ) + debug( '%s\n' % server ) result = [ self._parseIperf( server ), self._parseIperf( client ) ] if l4Type == 'UDP': result.insert( 0, udpBw ) - log( '*** Results: %s\n' % result ) + cliinfo( '*** Results: %s\n' % result ) return result def iperfUdp( self, udpBw='10M' ):