Add new loglevel to display CLI output only
Also print warning if user chooses a loglevel that will hide CLI output.
This commit is contained in:
@@ -151,6 +151,10 @@ class MininetRunner( object ):
|
|||||||
"Setup and validate environment."
|
"Setup and validate environment."
|
||||||
|
|
||||||
# set logging verbosity
|
# 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 )
|
lg.setLogLevel( self.options.verbosity )
|
||||||
|
|
||||||
# validate environment setup
|
# validate environment setup
|
||||||
|
|||||||
+8
-8
@@ -38,7 +38,7 @@ Bugs/limitations:
|
|||||||
from subprocess import call
|
from subprocess import call
|
||||||
from cmd import Cmd
|
from cmd import Cmd
|
||||||
|
|
||||||
from mininet.log import info, warn
|
from mininet.log import info, warn, cliinfo
|
||||||
|
|
||||||
class CLI( Cmd ):
|
class CLI( Cmd ):
|
||||||
"Simple command-line interface to talk to nodes."
|
"Simple command-line interface to talk to nodes."
|
||||||
@@ -84,16 +84,16 @@ class CLI( Cmd ):
|
|||||||
def do_nodes( self, args ):
|
def do_nodes( self, args ):
|
||||||
"List all nodes."
|
"List all nodes."
|
||||||
nodes = ' '.join( [ node.name for node in sorted( self.nodelist ) ] )
|
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 ):
|
def do_net( self, args ):
|
||||||
"List network connections."
|
"List network connections."
|
||||||
for switch in self.mn.switches:
|
for switch in self.mn.switches:
|
||||||
info( switch.name, '<->' )
|
cliinfo( switch.name, '<->' )
|
||||||
for intf in switch.intfs.values():
|
for intf in switch.intfs.values():
|
||||||
name = switch.connection[ intf ][ 1 ]
|
name = switch.connection[ intf ][ 1 ]
|
||||||
info( ' %s' % name )
|
cliinfo( ' %s' % name )
|
||||||
info( '\n' )
|
cliinfo( '\n' )
|
||||||
|
|
||||||
def do_sh( self, args ):
|
def do_sh( self, args ):
|
||||||
"Run an external shell command"
|
"Run an external shell command"
|
||||||
@@ -128,7 +128,7 @@ class CLI( Cmd ):
|
|||||||
|
|
||||||
def do_iperf( self, args ):
|
def do_iperf( self, args ):
|
||||||
"Simple iperf TCP test between two hosts."
|
"Simple iperf TCP test between two hosts."
|
||||||
self.mn.iperf( verbose=True )
|
self.mn.iperf()
|
||||||
|
|
||||||
def do_iperfudp( self, args ):
|
def do_iperfudp( self, args ):
|
||||||
"Simple iperf UDP test between two hosts."
|
"Simple iperf UDP test between two hosts."
|
||||||
@@ -138,13 +138,13 @@ class CLI( Cmd ):
|
|||||||
def do_intfs( self, args ):
|
def do_intfs( self, args ):
|
||||||
"List interfaces."
|
"List interfaces."
|
||||||
for node in self.nodelist:
|
for node in self.nodelist:
|
||||||
info( '%s: %s\n' %
|
cliinfo( '%s: %s\n' %
|
||||||
( node.name, ' '.join( sorted( node.intfs.values() ) ) ) )
|
( node.name, ' '.join( sorted( node.intfs.values() ) ) ) )
|
||||||
|
|
||||||
def do_dump( self, args ):
|
def do_dump( self, args ):
|
||||||
"Dump node info."
|
"Dump node info."
|
||||||
for node in self.nodelist:
|
for node in self.nodelist:
|
||||||
info( '%s\n' % node )
|
cliinfo( '%s\n' % node )
|
||||||
|
|
||||||
def do_exit( self, args ):
|
def do_exit( self, args ):
|
||||||
"Exit"
|
"Exit"
|
||||||
|
|||||||
+24
-2
@@ -4,8 +4,15 @@ import logging
|
|||||||
from logging import Logger
|
from logging import Logger
|
||||||
import types
|
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,
|
LEVELS = { 'debug': logging.DEBUG,
|
||||||
'info': logging.INFO,
|
'info': logging.INFO,
|
||||||
|
'cliinfo': CLIINFO,
|
||||||
'warning': logging.WARNING,
|
'warning': logging.WARNING,
|
||||||
'error': logging.ERROR,
|
'error': logging.ERROR,
|
||||||
'critical': logging.CRITICAL }
|
'critical': logging.CRITICAL }
|
||||||
@@ -119,6 +126,20 @@ class MininetLogger( Logger, object ):
|
|||||||
self.setLevel( level )
|
self.setLevel( level )
|
||||||
self.handlers[ 0 ].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()
|
lg = MininetLogger()
|
||||||
|
|
||||||
@@ -144,5 +165,6 @@ def makeListCompatible( fn ):
|
|||||||
setattr( newfn, '__doc__', fn.__doc__ )
|
setattr( newfn, '__doc__', fn.__doc__ )
|
||||||
return newfn
|
return newfn
|
||||||
|
|
||||||
info, warn, error, debug = lg.info, lg.warn, lg.error, lg.debug = [
|
info, cliinfo, warn, error, debug = lg.info, lg.cliinfo, lg.warn, lg.error, \
|
||||||
makeListCompatible( f ) for f in lg.info, lg.warn, lg.error, lg.debug ]
|
lg.debug = [ makeListCompatible( f ) for f in lg.info, lg.cliinfo, lg.warn,
|
||||||
|
lg.error, lg.debug ]
|
||||||
|
|||||||
+13
-16
@@ -89,7 +89,7 @@ import signal
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from mininet.cli import CLI
|
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 Host, UserSwitch, KernelSwitch, Controller
|
||||||
from mininet.node import ControllerParams
|
from mininet.node import ControllerParams
|
||||||
from mininet.util import quietRun, fixLimits
|
from mininet.util import quietRun, fixLimits
|
||||||
@@ -402,9 +402,9 @@ class Mininet( object ):
|
|||||||
ploss = None
|
ploss = None
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hosts = self.hosts
|
hosts = self.hosts
|
||||||
info( '*** Ping: testing ping reachability\n' )
|
cliinfo( '*** Ping: testing ping reachability\n' )
|
||||||
for node in hosts:
|
for node in hosts:
|
||||||
info( '%s -> ' % node.name )
|
cliinfo( '%s -> ' % node.name )
|
||||||
for dest in hosts:
|
for dest in hosts:
|
||||||
if node != dest:
|
if node != dest:
|
||||||
result = node.cmd( 'ping -c1 ' + dest.IP() )
|
result = node.cmd( 'ping -c1 ' + dest.IP() )
|
||||||
@@ -416,10 +416,10 @@ class Mininet( object ):
|
|||||||
node.cmdPrint( 'route' )
|
node.cmdPrint( 'route' )
|
||||||
exit( 1 )
|
exit( 1 )
|
||||||
lost += sent - received
|
lost += sent - received
|
||||||
info( ( '%s ' % dest.name ) if received else 'X ' )
|
cliinfo( ( '%s ' % dest.name ) if received else 'X ' )
|
||||||
info( '\n' )
|
cliinfo( '\n' )
|
||||||
ploss = 100 * lost / packets
|
ploss = 100 * lost / packets
|
||||||
info( "*** Results: %i%% dropped (%d/%d lost)\n" %
|
cliinfo( "*** Results: %i%% dropped (%d/%d lost)\n" %
|
||||||
( ploss, lost, packets ) )
|
( ploss, lost, packets ) )
|
||||||
return ploss
|
return ploss
|
||||||
|
|
||||||
@@ -446,21 +446,18 @@ class Mininet( object ):
|
|||||||
else:
|
else:
|
||||||
raise Exception( 'could not parse iperf output: ' + iperfOutput )
|
raise Exception( 'could not parse iperf output: ' + iperfOutput )
|
||||||
|
|
||||||
def iperf( self, hosts=None, l4Type='TCP', udpBw='10M',
|
def iperf( self, hosts=None, l4Type='TCP', udpBw='10M' ):
|
||||||
verbose=False ):
|
|
||||||
"""Run iperf between two hosts.
|
"""Run iperf between two hosts.
|
||||||
hosts: list of hosts; if None, uses opposite hosts
|
hosts: list of hosts; if None, uses opposite hosts
|
||||||
l4Type: string, one of [ TCP, UDP ]
|
l4Type: string, one of [ TCP, UDP ]
|
||||||
verbose: verbose printing
|
|
||||||
returns: results two-element array of server and client speeds"""
|
returns: results two-element array of server and client speeds"""
|
||||||
log = info if verbose else debug
|
|
||||||
if not hosts:
|
if not hosts:
|
||||||
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
hosts = [ self.hosts[ 0 ], self.hosts[ -1 ] ]
|
||||||
else:
|
else:
|
||||||
assert len( hosts ) == 2
|
assert len( hosts ) == 2
|
||||||
host0, host1 = hosts
|
host0, host1 = hosts
|
||||||
log( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
cliinfo( '*** Iperf: testing ' + l4Type + ' bandwidth between ' )
|
||||||
log( "%s and %s\n" % ( host0.name, host1.name ) )
|
cliinfo( "%s and %s\n" % ( host0.name, host1.name ) )
|
||||||
host0.cmd( 'killall -9 iperf' )
|
host0.cmd( 'killall -9 iperf' )
|
||||||
iperfArgs = 'iperf '
|
iperfArgs = 'iperf '
|
||||||
bwArgs = ''
|
bwArgs = ''
|
||||||
@@ -470,16 +467,16 @@ class Mininet( object ):
|
|||||||
elif l4Type != 'TCP':
|
elif l4Type != 'TCP':
|
||||||
raise Exception( 'Unexpected l4 type: %s' % l4Type )
|
raise Exception( 'Unexpected l4 type: %s' % l4Type )
|
||||||
server = host0.cmd( iperfArgs + '-s &' )
|
server = host0.cmd( iperfArgs + '-s &' )
|
||||||
log( '%s\n' % server )
|
debug( '%s\n' % server )
|
||||||
client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' +
|
client = host1.cmd( iperfArgs + '-t 5 -c ' + host0.IP() + ' ' +
|
||||||
bwArgs )
|
bwArgs )
|
||||||
log( '%s\n' % client )
|
debug( '%s\n' % client )
|
||||||
server = host0.cmd( 'killall -9 iperf' )
|
server = host0.cmd( 'killall -9 iperf' )
|
||||||
log( '%s\n' % server )
|
debug( '%s\n' % server )
|
||||||
result = [ self._parseIperf( server ), self._parseIperf( client ) ]
|
result = [ self._parseIperf( server ), self._parseIperf( client ) ]
|
||||||
if l4Type == 'UDP':
|
if l4Type == 'UDP':
|
||||||
result.insert( 0, udpBw )
|
result.insert( 0, udpBw )
|
||||||
log( '*** Results: %s\n' % result )
|
cliinfo( '*** Results: %s\n' % result )
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def iperfUdp( self, udpBw='10M' ):
|
def iperfUdp( self, udpBw='10M' ):
|
||||||
|
|||||||
Reference in New Issue
Block a user