From 496b5f9ed0b6c7a7c02a67dbeb3c43172fc97478 Mon Sep 17 00:00:00 2001
From: Bob Lantz <rlantz@cs.stanford.edu>
Date: Fri, 5 Feb 2010 17:01:03 -0800
Subject: [PATCH] Moved CLI into its own file. Also, MininetCLI is now just
 'CLI'.

---
 mininet/cli.py | 181 +++++++++++++++++++++++++++++++++++++++++++++++++
 mininet/net.py | 140 +-------------------------------------
 2 files changed, 183 insertions(+), 138 deletions(-)
 create mode 100644 mininet/cli.py

diff --git a/mininet/cli.py b/mininet/cli.py
new file mode 100644
index 00000000..6a3b1107
--- /dev/null
+++ b/mininet/cli.py
@@ -0,0 +1,181 @@
+#!/usr/bin/python
+
+"""
+A simple command-line interface for Mininet.
+
+The Mininet CLI provides a simple control console which
+makes it easy to talk to nodes. For example, the command
+
+mininet> h27 ifconfig
+
+runs 'ifconfig' on host h27.
+
+Having a single console rather than, for example, an xterm for each
+node is particularly convenient for networks of any reasonable
+size.
+
+The CLI automatically substitutes IP addresses for node names,
+so commands like
+
+mininet> h0 ping -c1 h31
+
+should work correctly and allow host h0 to ping host h31.
+Note the '-c1' argument as per the Bugs/limitations section below!
+
+Several useful commands are provided, including the ability to
+list all nodes ('nodes'), to print out the network topology
+('net') and to check connectivity ('ping_all', 'ping_pair')
+and bandwidth ('iperf'.)
+
+Bugs/limitations:
+
+- Interactive commands are not supported at the moment;
+  notably, if you type 'ping h1', you can control-C it, but
+  it breaks the CLI and your network. ;-(
+  For now, we recommend limiting CLI use to non-interactive
+  commands which terminate in a reasonable amount of time.
+
+- We don't (yet) support command line history editing. This is
+  coming soon.
+
+"""
+
+from subprocess import call
+import sys
+
+from mininet.log import lg
+
+class CLI( object ):
+    "Simple command-line interface to talk to nodes."
+
+    cmds = [ '?', 'help', 'nodes', 'net', 'sh', 'ping_all', 'exit', \
+            'ping_pair', 'iperf', 'iperf_udp', 'intfs', 'dump' ]
+
+    def __init__( self, mininet ):
+        self.mn = mininet
+        self.nodemap = {} # map names to Node objects
+        for node in self.mn.nodes.values():
+            self.nodemap[ node.name ] = node
+        for cname, cnode in self.mn.controllers.iteritems():
+            self.nodemap[ cname ] = cnode
+        self.nodelist = self.nodemap.values()
+        self.run()
+
+    # Disable pylint "Unused argument: 'arg's'" messages.
+    # Each CLI function needs the same interface.
+    # pylint: disable-msg=W0613
+
+    # Commands
+    def help( self, args ):
+        "Semi-useful help for CLI."
+        helpStr = ( 'Available commands are:' + str( self.cmds ) + '\n'
+                   'You may also send a command to a node using:\n'
+                   '  <node> command {args}\n'
+                   'For example:\n'
+                   '  mininet> h0 ifconfig\n'
+                   '\n'
+                   'The interpreter automatically substitutes IP '
+                   'addresses\n'
+                   'for node names, so commands like\n'
+                   '  mininet> h0 ping -c1 h1\n'
+                   'should work.\n'
+                   '\n\n'
+                   'Interactive commands are not really supported yet,\n'
+                   'so please limit commands to ones that do not\n'
+                   'require user interaction and will terminate\n'
+                   'after a reasonable amount of time.\n' )
+        print( helpStr )
+
+    def nodes( self, args ):
+        "List all nodes."
+        nodes = ' '.join( [ node.name for node in sorted( self.nodelist ) ] )
+        lg.info( 'available nodes are: \n%s\n' % nodes )
+
+    def net( self, args ):
+        "List network connections."
+        for switchDpid in self.mn.topo.switches():
+            switch = self.mn.nodes[ switchDpid ]
+            lg.info( '%s <->', switch.name )
+            for intf in switch.intfs:
+                node = switch.connection[ intf ]
+                lg.info( ' %s' % node.name )
+            lg.info( '\n' )
+
+    def sh( self, args ):
+        "Run an external shell command"
+        call( [ 'sh', '-c' ] + args )
+
+    def pingAll( self, args ):
+        "Ping between all hosts."
+        self.mn.pingAll()
+
+    def pingPair( self, args ):
+        "Ping between first two hosts, useful for testing."
+        self.mn.pingPair()
+
+    def iperf( self, args ):
+        "Simple iperf TCP test between two hosts."
+        self.mn.iperf()
+
+    def iperfUdp( self, args ):
+        "Simple iperf UDP test between two hosts."
+        udpBw = args[ 0 ] if len( args ) else '10M'
+        self.mn.iperfUdp( udpBw )
+
+    def intfs( self, args ):
+        "List interfaces."
+        for node in self.mn.nodes.values():
+            lg.info( '%s: %s\n' % ( node.name, ' '.join( node.intfs ) ) )
+
+    def dump( self, args ):
+        "Dump node info."
+        for node in self.mn.nodes.values():
+            lg.info( '%s\n' % node )
+
+    # Re-enable pylint "Unused argument: 'arg's'" messages.
+    # pylint: enable-msg=W0613
+
+    def run( self ):
+        "Read and execute commands."
+        lg.warn( '*** Starting CLI:\n' )
+        while True:
+            lg.warn( 'mininet> ' )
+            inputLine = sys.stdin.readline()
+            if inputLine == '':
+                break
+            if inputLine[ -1 ] == '\n':
+                inputLine = inputLine[ :-1 ]
+            cmd = inputLine.split( ' ' )
+            first = cmd[ 0 ]
+            rest = cmd[ 1: ]
+            if first in self.cmds and hasattr( self, first ):
+                getattr( self, first )( rest )
+            elif first in self.nodemap and rest != []:
+                node = self.nodemap[ first ]
+                # Substitute IP addresses for node names in command
+                rest = [ self.nodemap[ arg ].IP()
+                    if arg in self.nodemap else arg
+                    for arg in rest ]
+                rest = ' '.join( rest )
+                # Interactive commands don't work yet, and
+                # there are still issues with control-c
+                lg.warn( '*** %s: running %s\n' % ( node.name, rest ) )
+                node.sendCmd( rest )
+                while True:
+                    try:
+                        done, data = node.monitor()
+                        lg.info( '%s\n' % data )
+                        if done:
+                            break
+                    except KeyboardInterrupt:
+                        node.sendInt()
+            elif first == '':
+                pass
+            elif first in [ 'exit', 'quit' ]:
+                break
+            elif first == '?':
+                self.help( rest )
+            else:
+                lg.error( 'CLI: unknown node or command: < %s >\n' % first )
+            #lg.info( '*** CLI: command complete\n' )
+        return 'exited by user command'
diff --git a/mininet/net.py b/mininet/net.py
index c8eb18c5..7a6bda5b 100755
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -52,10 +52,9 @@
 import os
 import re
 import signal
-from subprocess import call
-import sys
 from time import sleep
 
+from mininet.cli import CLI
 from mininet.log import lg
 from mininet.node import KernelSwitch, OVSKernelSwitch
 from mininet.util import quietRun, fixLimits
@@ -490,141 +489,6 @@ def iperfUdp( self, udpBw='10M' ):
     def interact( self ):
         "Start network and run our simple CLI."
         self.start()
-        result = MininetCLI( self )
+        result = CLI( self )
         self.stop()
         return result
-
-
-class MininetCLI( object ):
-    "Simple command-line interface to talk to nodes."
-    cmds = [ '?', 'help', 'nodes', 'net', 'sh', 'ping_all', 'exit', \
-            'ping_pair', 'iperf', 'iperf_udp', 'intfs', 'dump' ]
-
-    def __init__( self, mininet ):
-        self.mn = mininet
-        self.nodemap = {} # map names to Node objects
-        for node in self.mn.nodes.values():
-            self.nodemap[ node.name ] = node
-        for cname, cnode in self.mn.controllers.iteritems():
-            self.nodemap[ cname ] = cnode
-        self.nodelist = self.nodemap.values()
-        self.run()
-
-    # Disable pylint "Unused argument: 'arg's'" messages.
-    # Each CLI function needs the same interface.
-    # pylint: disable-msg=W0613
-
-    # Commands
-    def help( self, args ):
-        "Semi-useful help for CLI."
-        helpStr = ( 'Available commands are:' + str( self.cmds ) + '\n'
-                   'You may also send a command to a node using:\n'
-                   '  <node> command {args}\n'
-                   'For example:\n'
-                   '  mininet> h0 ifconfig\n'
-                   '\n'
-                   'The interpreter automatically substitutes IP '
-                   'addresses\n'
-                   'for node names, so commands like\n'
-                   '  mininet> h0 ping -c1 h1\n'
-                   'should work.\n'
-                   '\n\n'
-                   'Interactive commands are not really supported yet,\n'
-                   'so please limit commands to ones that do not\n'
-                   'require user interaction and will terminate\n'
-                   'after a reasonable amount of time.\n' )
-        print( helpStr )
-
-    def nodes( self, args ):
-        "List all nodes."
-        nodes = ' '.join( [ node.name for node in sorted( self.nodelist ) ] )
-        lg.info( 'available nodes are: \n%s\n' % nodes )
-
-    def net( self, args ):
-        "List network connections."
-        for switchDpid in self.mn.topo.switches():
-            switch = self.mn.nodes[ switchDpid ]
-            lg.info( '%s <->', switch.name )
-            for intf in switch.intfs:
-                node = switch.connection[ intf ]
-                lg.info( ' %s' % node.name )
-            lg.info( '\n' )
-
-    def sh( self, args ):
-        "Run an external shell command"
-        call( [ 'sh', '-c' ] + args )
-
-    def pingAll( self, args ):
-        "Ping between all hosts."
-        self.mn.pingAll()
-
-    def pingPair( self, args ):
-        "Ping between first two hosts, useful for testing."
-        self.mn.pingPair()
-
-    def iperf( self, args ):
-        "Simple iperf TCP test between two hosts."
-        self.mn.iperf()
-
-    def iperfUdp( self, args ):
-        "Simple iperf UDP test between two hosts."
-        udpBw = args[ 0 ] if len( args ) else '10M'
-        self.mn.iperfUdp( udpBw )
-
-    def intfs( self, args ):
-        "List interfaces."
-        for node in self.mn.nodes.values():
-            lg.info( '%s: %s\n' % ( node.name, ' '.join( node.intfs ) ) )
-
-    def dump( self, args ):
-        "Dump node info."
-        for node in self.mn.nodes.values():
-            lg.info( '%s\n' % node )
-
-    # Re-enable pylint "Unused argument: 'arg's'" messages.
-    # pylint: enable-msg=W0613
-
-    def run( self ):
-        "Read and execute commands."
-        lg.warn( '*** Starting CLI:\n' )
-        while True:
-            lg.warn( 'mininet> ' )
-            inputLine = sys.stdin.readline()
-            if inputLine == '':
-                break
-            if inputLine[ -1 ] == '\n':
-                inputLine = inputLine[ :-1 ]
-            cmd = inputLine.split( ' ' )
-            first = cmd[ 0 ]
-            rest = cmd[ 1: ]
-            if first in self.cmds and hasattr( self, first ):
-                getattr( self, first )( rest )
-            elif first in self.nodemap and rest != []:
-                node = self.nodemap[ first ]
-                # Substitute IP addresses for node names in command
-                rest = [ self.nodemap[ arg ].IP()
-                    if arg in self.nodemap else arg
-                    for arg in rest ]
-                rest = ' '.join( rest )
-                # Interactive commands don't work yet, and
-                # there are still issues with control-c
-                lg.warn( '*** %s: running %s\n' % ( node.name, rest ) )
-                node.sendCmd( rest )
-                while True:
-                    try:
-                        done, data = node.monitor()
-                        lg.info( '%s\n' % data )
-                        if done:
-                            break
-                    except KeyboardInterrupt:
-                        node.sendInt()
-            elif first == '':
-                pass
-            elif first in [ 'exit', 'quit' ]:
-                break
-            elif first == '?':
-                self.help( rest )
-            else:
-                lg.error( 'CLI: unknown node or command: < %s >\n' % first )
-            #lg.info( '*** CLI: command complete\n' )
-        return 'exited by user command'
-- 
GitLab