3 author: Bob Lantz (rlantz@cs.stanford.edu)
5 Unfortunately, Mininet and OpenFlow (and the Linux kernel)
6 don't always clean up properly after themselves. Until they do
7 (or until cleanup functionality is integrated into the Python
8 code), this script may be used to get rid of unwanted garbage.
9 It may also get rid of 'false positives', but hopefully
10 nothing irreplaceable!
13 from subprocess import ( Popen, PIPE, check_output as co,
17 from mininet.log import info
18 from mininet.term import cleanUpScreens
19 from mininet.util import decode
22 "Print a command and send it to the shell"
24 result = Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ]
25 return decode( result )
27 def killprocs( pattern ):
28 "Reliably terminate processes matching a pattern (including args)"
29 sh( 'pkill -9 -f %s' % pattern )
30 # Make sure they are gone
33 pids = co( [ 'pgrep', '-f', pattern ] )
34 except CalledProcessError:
37 sh( 'pkill -9 -f %s' % pattern )
42 class Cleanup( object ):
43 "Wrapper for cleanup()"
49 """Clean up junk which might be left over from old runs;
50 do fast stuff before slow dp and link removal!"""
52 info( "*** Removing excess controllers/ofprotocols/ofdatapaths/"
54 zombies = ( 'controller ofprotocol ofdatapath ping nox_core'
55 'lt-nox_core ovs-openflowd ovs-controller'
56 'ovs-testcontroller udpbwtest mnexec ivs ryu-manager' )
57 # Note: real zombie processes can't actually be killed, since they
58 # are already (un)dead. Then again,
59 # you can't connect to them either, so they're mostly harmless.
60 # Send SIGTERM first to give processes a chance to shutdown cleanly.
61 sh( 'killall ' + zombies + ' 2> /dev/null' )
63 sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
65 # And kill off sudo mnexec
66 sh( 'pkill -9 -f "sudo mnexec"')
68 info( "*** Removing junk from /tmp\n" )
69 sh( 'rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log' )
71 info( "*** Removing old X11 tunnels\n" )
74 info( "*** Removing excess kernel datapaths\n" )
75 dps = sh( "ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'"
79 sh( 'dpctl deldp ' + dp )
80 info( "*** Removing OVS datapaths\n" )
81 dps = sh("ovs-vsctl --timeout=1 list-br").strip().splitlines()
83 sh( "ovs-vsctl " + " -- ".join( "--if-exists del-br " + dp
84 for dp in dps if dp ) )
85 # And in case the above didn't work...
86 dps = sh( "ovs-vsctl --timeout=1 list-br" ).strip().splitlines()
88 sh( 'ovs-vsctl del-br ' + dp )
90 info( "*** Removing all links of the pattern foo-ethX\n" )
91 links = sh( "ip link show | "
92 "egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
94 # Delete blocks of links
96 for i in range( 0, len( links ), n ):
97 cmd = ';'.join( 'ip link del %s' % link
98 for link in links[ i : i + n ] )
99 sh( '( %s ) 2> /dev/null' % cmd )
101 if 'tap9' in sh( 'ip link show' ):
102 info( "*** Removing tap9 - assuming it's from cluster edition\n" )
103 sh( 'ip link del tap9' )
105 info( "*** Killing stale mininet node processes\n" )
106 killprocs( 'mininet:' )
108 info( "*** Shutting down stale tunnels\n" )
109 killprocs( 'Tunnel=Ethernet' )
110 killprocs( '.ssh/mn')
111 sh( 'rm -f ~/.ssh/mn/*' )
113 # Call any additional cleanup code if necessary
114 for callback in cls.callbacks:
117 info( "*** Cleanup complete.\n" )
120 def addCleanupCallback( cls, callback ):
121 "Add cleanup callback"
122 if callback not in cls.callbacks:
123 cls.callbacks.append( callback )
126 cleanup = Cleanup.cleanup
127 addCleanupCallback = Cleanup.addCleanupCallback