$OpenBSD: patch-mininet_clean_py,v 1.1.1.1 2017/08/21 18:47:12 akoshibe Exp $

Index: mininet/clean.py
--- mininet/clean.py.orig
+++ mininet/clean.py
@@ -9,7 +9,7 @@ code), this script may be used to get rid of unwanted 
 It may also get rid of 'false positives', but hopefully
 nothing irreplaceable!
 """
-
+from os import uname
 from subprocess import ( Popen, PIPE, check_output as co,
                          CalledProcessError )
 import time
@@ -17,27 +17,114 @@ import time
 from mininet.log import info
 from mininet.term import cleanUpScreens
 
-
 def sh( cmd ):
     "Print a command and send it to the shell"
     info( cmd + '\n' )
     return Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ]
 
-def killprocs( pattern ):
+def _coPids( pattern ):
+    try:
+        return co( [ 'pgrep', '-f', pattern ] )
+    except CalledProcessError:
+        return ''
+
+def _popenPids( pattern ):
+    try:
+        p1 = Popen( [ 'ps' ], stdout=PIPE )
+        pids = co( [ 'awk', '/%s/{print $1}' % pattern ], stdin=p1.stdout )
+        p1.stdout.close()
+        return pids
+    except CalledProcessError:
+        return ''
+
+def killprocs( pidsFunc, pattern ):
     "Reliably terminate processes matching a pattern (including args)"
     sh( 'pkill -9 -f %s' % pattern )
     # Make sure they are gone
     while True:
-        try:
-            pids = co( [ 'pgrep', '-f', pattern ] )
-        except CalledProcessError:
-            pids = ''
+        pids = pidsFunc( pattern )
         if pids:
             sh( 'pkill -9 -f %s' % pattern )
             time.sleep( .5 )
         else:
             break
 
+def killnodes( pidsFunc, pattern='[m]ininet' ):
+    "kill processes representing nodes"
+    killprocs( pidsFunc, pattern )
+    nodes = sh( 'jls name' ).split('\n')
+    for node in nodes:
+        if 'mininet:' in node:
+            sh( 'jail -r %s 2>/dev/null' % node )
+
+def _iplinkClean( listCmd=None ):
+    """ link cleanup using 'ip link' """
+    links = sh( "ip link show | "
+                "egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
+                ).splitlines()
+    # Delete blocks of links
+    n = 1000  # chunk size
+    for i in range( 0, len( links ), n ):
+        cmd = ';'.join( 'ip link del %s' % link
+                         for link in links[ i : i + n ] )
+        sh( '( %s ) 2> /dev/null' % cmd )
+
+    if 'tap9' in sh( 'ip link show' ):
+        info( "*** Removing tap9 - assuming it's from cluster edition\n" )
+        sh( 'ip link del tap9' )
+
+def _ifClean( listCmd ):
+    links = sh( listCmd ).splitlines()
+    # Delete blocks of links
+    n = 1000  # chunk size
+    for i in range( 0, len( links ), n ):
+        cmd = ';'.join( 'ifconfig %s destroy' % link
+                         for link in links[ i : i + n ] )
+        sh( '( %s ) 2> /dev/null' % cmd )
+
+def _ifcfgClean( listCmd ):
+    """ link cleanup with 'ifconfig'"""
+    _ifClean( listCmd )
+    if 'tap9' in sh( 'ifconfig' ):
+        info( "*** Removing tap9 - assuming it's from cluster edition\n" )
+        sh( 'ifconfig tap9 destroy' )
+
+def _ifcfgCleanLo( listCmd ):
+    """ link cleanup with 'ifconfig' that assumes formattable listCmd
+        that takes an interface unit name (see args for OpenBSD)"""
+    _ifClean( listCmd % 'switch' )
+    _ifcfgClean( listCmd % 'pair' )
+
+    los = sh( listCmd % 'lo' ).splitlines()
+    n = 256  # chunk size - can only have 256 max, per rdomain(4)
+    for i in range( 1, len( los ), n ):
+        cmd = ';'.join( 'ifconfig %s rdomain 0 destroy' % lo
+                         for lo in los[ i : i + n ] )
+        sh( '( %s ) 2> /dev/null' % cmd )
+
+
+platform = uname()[ 0 ]
+if platform == 'FreeBSD':
+    cleanLinks = _ifcfgClean
+    args       = "ifconfig -l | egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
+    pidsFunc   = _popenPids
+    cleanNodes = killnodes
+    zkill_cmd = ( 'killall -9 ping mnexec ryu-manager' )
+elif platform == 'Linux':
+    cleanLinks, args = _iplinkClean, None
+    pidsFunc   = _coPids
+    cleanNodes = killprocs
+    zkill_cmd = ( 'killall -9 controller ofprotocol ofdatapath ping nox_core'
+                'lt-nox_core ovs-openflowd ovs-controller'
+                'ovs-testcontroller udpbwtest mnexec ivs ryu-manager' )
+else: # OpenBSD
+    cleanLinks = _ifcfgCleanLo
+    args = "ifconfig %s | sed -n 's|\(^[a-z]\{1,\}[0-9]\{1,\}\):.*|\\1| p'"
+    pidsFunc   = _coPids
+    cleanNodes = killprocs
+    zkill_cmd = ( 'pkill -9 ping mnexec switchd' )
+
+
 class Cleanup( object ):
     "Wrapper for cleanup()"
 
@@ -50,19 +137,16 @@ class Cleanup( object ):
 
         info( "*** Removing excess controllers/ofprotocols/ofdatapaths/"
               "pings/noxes\n" )
-        zombies = ( 'controller ofprotocol ofdatapath ping nox_core'
-                    'lt-nox_core ovs-openflowd ovs-controller'
-                    'ovs-testcontroller udpbwtest mnexec ivs ryu-manager' )
         # Note: real zombie processes can't actually be killed, since they
         # are already (un)dead. Then again,
         # you can't connect to them either, so they're mostly harmless.
         # Send SIGTERM first to give processes a chance to shutdown cleanly.
-        sh( 'killall ' + zombies + ' 2> /dev/null' )
+        sh( zkill_cmd + ' 2> /dev/null' )
         time.sleep( 1 )
-        sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
+        sh( zkill_cmd + ' 2> /dev/null' )
 
         # And kill off sudo mnexec
-        sh( 'pkill -9 -f "sudo mnexec"')
+        sh( 'pkill -9 -f "mnexec"')
 
         info( "*** Removing junk from /tmp\n" )
         sh( 'rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log' )
@@ -88,26 +172,14 @@ class Cleanup( object ):
             sh( 'ovs-vsctl del-br ' + dp )
 
         info( "*** Removing all links of the pattern foo-ethX\n" )
-        links = sh( "ip link show | "
-                    "egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
-                    ).splitlines()
-        # Delete blocks of links
-        n = 1000  # chunk size
-        for i in range( 0, len( links ), n ):
-            cmd = ';'.join( 'ip link del %s' % link
-                             for link in links[ i : i + n ] )
-            sh( '( %s ) 2> /dev/null' % cmd )
+        cleanLinks( args )
 
-        if 'tap9' in sh( 'ip link show' ):
-            info( "*** Removing tap9 - assuming it's from cluster edition\n" )
-            sh( 'ip link del tap9' )
-
         info( "*** Killing stale mininet node processes\n" )
-        killprocs( 'mininet:' )
+        cleanNodes( pidsFunc, '[m]ininet:' )
 
         info( "*** Shutting down stale tunnels\n" )
-        killprocs( 'Tunnel=Ethernet' )
-        killprocs( '.ssh/mn')
+        killprocs( pidsFunc, '[T]unnel=Ethernet' )
+        killprocs( pidsFunc, '.ssh\/mn' )
         sh( 'rm -f ~/.ssh/mn/*' )
 
         # Call any additional cleanup code if necessary
