From 8e04a9f844437326288f498c8e358f41df40424f Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Fri, 9 Aug 2013 12:20:13 -0700 Subject: [PATCH 1/3] Replaced nodelist and nodemap in CLI with mn Updated Mininet to be more compliant with dict Fixes #182 --- mininet/cli.py | 53 +++++++++++++++++++++++++++----------------------- mininet/net.py | 16 +++++++++++++++ 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index a89051d..37f2932 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -43,13 +43,6 @@ class CLI( Cmd ): def __init__( self, mininet, stdin=sys.stdin, script=None ): self.mn = mininet - self.nodelist = self.mn.controllers + self.mn.switches + self.mn.hosts - self.nodemap = {} # map names to Node objects - for node in self.nodelist: - self.nodemap[ node.name ] = node - # Local variable bindings for py command - self.locals = { 'net': mininet } - self.locals.update( self.nodemap ) # Attempt to handle input self.stdin = stdin self.inPoller = poll() @@ -63,7 +56,7 @@ class CLI( Cmd ): while True: try: # Make sure no nodes are still waiting - for node in self.nodelist: + for node in self.mn.values(): while node.waiting: node.sendInt() node.monitor() @@ -78,6 +71,12 @@ class CLI( Cmd ): "Don't repeat last command when you hit return." pass + def locals( self ): + "Local variable bindings for py command" + locals = { 'net': self.mn } + locals.update( self.mn ) + return locals + # Disable pylint "Unused argument: 'arg's'" messages, as well as # "method could be a function" warning, since each CLI function # must have the same interface @@ -110,12 +109,14 @@ class CLI( Cmd ): def do_nodes( self, _line ): "List all nodes." - nodes = ' '.join( [ node.name for node in sorted( self.nodelist ) ] ) + # self.mn.values() + nodes = ' '.join( [ node.name for node in sorted( self.mn ) ] ) output( 'available nodes are: \n%s\n' % nodes ) def do_net( self, _line ): "List network connections." - dumpNodeConnections( self.nodelist ) + # self.mn.values() + dumpNodeConnections( self.mn ) def do_sh( self, line ): "Run an external shell command" @@ -128,7 +129,7 @@ class CLI( Cmd ): """Evaluate a Python expression. Node names may be used, e.g.: py h1.cmd('ls')""" try: - result = eval( line, globals(), self.locals ) + result = eval( line, globals(), self.locals() ) if not result: return elif isinstance( result, str ): @@ -145,7 +146,7 @@ class CLI( Cmd ): """Execute a Python statement. Node names may be used, e.g.: px print h1.cmd('ls')""" try: - exec( line, globals(), self.locals ) + exec( line, globals(), self.locals() ) except Exception, e: output( str( e ) + '\n' ) @@ -176,11 +177,12 @@ class CLI( Cmd ): hosts = [] err = False for arg in args: - if arg not in self.nodemap: + # self.mn.keys() + if arg not in self.mn: err = True error( "node '%s' not in network\n" % arg ) else: - hosts.append( self.nodemap[ arg ] ) + hosts.append( self.mn[ arg ] ) if not err: self.mn.iperf( hosts ) else: @@ -196,11 +198,11 @@ class CLI( Cmd ): hosts = [] err = False for arg in args[ 1:3 ]: - if arg not in self.nodemap: + if arg not in self.mn: err = True error( "node '%s' not in network\n" % arg ) else: - hosts.append( self.nodemap[ arg ] ) + hosts.append( self.mn[ arg ] ) if not err: self.mn.iperf( hosts, l4Type='UDP', udpBw=udpBw ) else: @@ -209,13 +211,15 @@ class CLI( Cmd ): def do_intfs( self, _line ): "List interfaces." - for node in self.nodelist: + # self.mn.values() + for node in self.mn: output( '%s: %s\n' % ( node.name, ','.join( node.intfNames() ) ) ) def do_dump( self, _line ): "Dump node info." - for node in self.nodelist: + # self.mn.values() + for node in self.mn: output( '%s\n' % repr( node ) ) def do_link( self, line ): @@ -235,10 +239,11 @@ class CLI( Cmd ): error( 'usage: %s node1 node2 ...\n' % term ) else: for arg in args: - if arg not in self.nodemap: + # self.mn.keys() + if arg not in self.mn: error( "node '%s' not in network\n" % arg ) else: - node = self.nodemap[ arg ] + node = self.mn[ arg ] self.mn.terms += makeTerms( [ node ], term = term ) def do_x( self, line ): @@ -329,11 +334,11 @@ class CLI( Cmd ): args = args[ :-1 ] rest = args.split( ' ' ) - if first in self.nodemap: - node = self.nodemap[ first ] + if first in self.mn: + node = self.mn[ first ] # Substitute IP addresses for node names in command - rest = [ self.nodemap[ arg ].defaultIntf().updateIP() - if arg in self.nodemap else arg + rest = [ self.mn[ arg ].defaultIntf().updateIP() + if arg in self.mn else arg for arg in rest ] rest = ' '.join( rest ) # Run cmd on node: diff --git a/mininet/net.py b/mininet/net.py index 05a5e96..f1877c5 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -236,8 +236,24 @@ class Mininet( object ): def __iter__( self ): "return iterator over nodes" + #or dow we want to iterate of the keys i.e. node.name like a dict return chain( self.hosts, self.switches, self.controllers ) + def __len__( self ): + return len( self.hosts ) + len( self.switches ) + len( self.controllers ) + + def __contains__( self, item ): + return item in self.keys() + + def keys( self ): + return [ node.name for node in self.__iter__() ] + + def values( self ): + return list( self.__iter__() ) + + def items( self ): + return zip( self.keys(), self.values() ) + def addLink( self, node1, node2, port1=None, port2=None, cls=None, **params ): """"Add a link from node1 to node2 From 9281719d74dc7a58205befe17a8a91fc2e8930aa Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Fri, 9 Aug 2013 17:07:39 -0700 Subject: [PATCH 2/3] Made net compliant with dict semantics and added function comments Fixed locals bug (now they are persisent across calls) --- mininet/cli.py | 27 +++++++++++---------------- mininet/net.py | 14 ++++++++++---- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/mininet/cli.py b/mininet/cli.py index 37f2932..5479a28 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -43,6 +43,8 @@ class CLI( Cmd ): def __init__( self, mininet, stdin=sys.stdin, script=None ): self.mn = mininet + # CLI locals for py commands + self.locals = { 'net': mininet } # Attempt to handle input self.stdin = stdin self.inPoller = poll() @@ -71,11 +73,10 @@ class CLI( Cmd ): "Don't repeat last command when you hit return." pass - def locals( self ): + def getLocals( self ): "Local variable bindings for py command" - locals = { 'net': self.mn } - locals.update( self.mn ) - return locals + self.locals.update( self.mn ) + return self.locals # Disable pylint "Unused argument: 'arg's'" messages, as well as # "method could be a function" warning, since each CLI function @@ -109,14 +110,12 @@ class CLI( Cmd ): def do_nodes( self, _line ): "List all nodes." - # self.mn.values() - nodes = ' '.join( [ node.name for node in sorted( self.mn ) ] ) + nodes = ' '.join( sorted( self.mn ) ) output( 'available nodes are: \n%s\n' % nodes ) def do_net( self, _line ): "List network connections." - # self.mn.values() - dumpNodeConnections( self.mn ) + dumpNodeConnections( self.mn.values() ) def do_sh( self, line ): "Run an external shell command" @@ -129,7 +128,7 @@ class CLI( Cmd ): """Evaluate a Python expression. Node names may be used, e.g.: py h1.cmd('ls')""" try: - result = eval( line, globals(), self.locals() ) + result = eval( line, globals(), self.getLocals() ) if not result: return elif isinstance( result, str ): @@ -146,7 +145,7 @@ class CLI( Cmd ): """Execute a Python statement. Node names may be used, e.g.: px print h1.cmd('ls')""" try: - exec( line, globals(), self.locals() ) + exec( line, globals(), self.getLocals() ) except Exception, e: output( str( e ) + '\n' ) @@ -177,7 +176,6 @@ class CLI( Cmd ): hosts = [] err = False for arg in args: - # self.mn.keys() if arg not in self.mn: err = True error( "node '%s' not in network\n" % arg ) @@ -211,15 +209,13 @@ class CLI( Cmd ): def do_intfs( self, _line ): "List interfaces." - # self.mn.values() - for node in self.mn: + for node in self.mn.values(): output( '%s: %s\n' % ( node.name, ','.join( node.intfNames() ) ) ) def do_dump( self, _line ): "Dump node info." - # self.mn.values() - for node in self.mn: + for node in self.mn.values(): output( '%s\n' % repr( node ) ) def do_link( self, line ): @@ -239,7 +235,6 @@ class CLI( Cmd ): error( 'usage: %s node1 node2 ...\n' % term ) else: for arg in args: - # self.mn.keys() if arg not in self.mn: error( "node '%s' not in network\n" % arg ) else: diff --git a/mininet/net.py b/mininet/net.py index f1877c5..beaf1bd 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -237,21 +237,27 @@ class Mininet( object ): def __iter__( self ): "return iterator over nodes" #or dow we want to iterate of the keys i.e. node.name like a dict - return chain( self.hosts, self.switches, self.controllers ) + for node in chain( self.hosts, self.switches, self.controllers ): + yield node.name def __len__( self ): + "returns number of nodes in net" return len( self.hosts ) + len( self.switches ) + len( self.controllers ) def __contains__( self, item ): + "returns True if net contains named node" return item in self.keys() def keys( self ): - return [ node.name for node in self.__iter__() ] - - def values( self ): + "return a list of all node names or net's keys" return list( self.__iter__() ) + def values( self ): + "return a list of all nodes or net's values" + return [ self[name] for name in self.__iter__() ] + def items( self ): + "return (key,value) tuple list for every node in net" return zip( self.keys(), self.values() ) def addLink( self, node1, node2, port1=None, port2=None, From 98cb33599f524061dfb1ef596b36811336a88ec5 Mon Sep 17 00:00:00 2001 From: Brian O'Connor Date: Fri, 9 Aug 2013 17:10:50 -0700 Subject: [PATCH 3/3] fixed comment in cli.py --- mininet/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mininet/cli.py b/mininet/cli.py index 5479a28..5de9beb 100644 --- a/mininet/cli.py +++ b/mininet/cli.py @@ -43,7 +43,7 @@ class CLI( Cmd ): def __init__( self, mininet, stdin=sys.stdin, script=None ): self.mn = mininet - # CLI locals for py commands + # Local variable bindings for py command self.locals = { 'net': mininet } # Attempt to handle input self.stdin = stdin