Statistics
| Branch: | Tag: | Revision:

mininet / mininet / clean.py @ 125e6697

History | View | Annotate | Download (4.25 KB)

1
"""
2
Mininet Cleanup
3
author: Bob Lantz (rlantz@cs.stanford.edu)
4

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!
11
"""
12

    
13
from subprocess import ( Popen, PIPE, check_output as co,
14
                         CalledProcessError )
15
import time
16

    
17
from mininet.log import info
18
from mininet.term import cleanUpScreens
19

    
20

    
21
def sh( cmd ):
22
    "Print a command and send it to the shell"
23
    info( cmd + '\n' )
24
    return Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ]
25

    
26
def killprocs( pattern ):
27
    "Reliably terminate processes matching a pattern (including args)"
28
    sh( 'pkill -9 -f %s' % pattern )
29
    # Make sure they are gone
30
    while True:
31
        try:
32
            pids = co( [ 'pgrep', '-f', pattern ] )
33
        except CalledProcessError:
34
            pids = ''
35
        if pids:
36
            sh( 'pkill -9 -f %s' % pattern )
37
            time.sleep( .5 )
38
        else:
39
            break
40

    
41
class Cleanup( object ):
42
    "Wrapper for cleanup()"
43

    
44
    callbacks = []
45

    
46
    @classmethod
47
    def cleanup( cls):
48
        """Clean up junk which might be left over from old runs;
49
           do fast stuff before slow dp and link removal!"""
50

    
51
        info( "*** Removing excess controllers/ofprotocols/ofdatapaths/"
52
              "pings/noxes\n" )
53
        zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core '
54
        zombies += 'ovs-openflowd ovs-controller udpbwtest mnexec ivs'
55
        # Note: real zombie processes can't actually be killed, since they
56
        # are already (un)dead. Then again,
57
        # you can't connect to them either, so they're mostly harmless.
58
        # Send SIGTERM first to give processes a chance to shutdown cleanly.
59
        sh( 'killall ' + zombies + ' 2> /dev/null' )
60
        time.sleep( 1 )
61
        sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
62

    
63
        # And kill off sudo mnexec
64
        sh( 'pkill -9 -f "sudo mnexec"')
65

    
66
        info( "*** Removing junk from /tmp\n" )
67
        sh( 'rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log' )
68

    
69
        info( "*** Removing old X11 tunnels\n" )
70
        cleanUpScreens()
71

    
72
        info( "*** Removing excess kernel datapaths\n" )
73
        dps = sh( "ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'"
74
                  ).splitlines()
75
        for dp in dps:
76
            if dp:
77
                sh( 'dpctl deldp ' + dp )
78

    
79
        info( "***  Removing OVS datapaths\n" )
80
        dps = sh("ovs-vsctl --timeout=1 list-br").strip().splitlines()
81
        if dps:
82
            sh( "ovs-vsctl " + " -- ".join( "--if-exists del-br " + dp
83
                                            for dp in dps if dp ) )
84
        # And in case the above didn't work...
85
        dps = sh( "ovs-vsctl --timeout=1 list-br" ).strip().splitlines()
86
        for dp in dps:
87
            sh( 'ovs-vsctl del-br ' + dp )
88

    
89
        info( "*** Removing all links of the pattern foo-ethX\n" )
90
        links = sh( "ip link show | "
91
                    "egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'"
92
                    ).splitlines()
93
        # Delete blocks of links
94
        n = 1000  # chunk size
95
        for i in xrange( 0, len( links ), n ):
96
            cmd = ';'.join( 'ip link del %s' % link
97
                             for link in links[ i : i + n ] )
98
            sh( '( %s ) 2> /dev/null' % cmd )
99

    
100
        if 'tap9' in sh( 'ip link show' ):
101
            info( "*** Removing tap9 - assuming it's from cluster edition\n" )
102
            sh( 'ip link del tap9' )
103

    
104
        info( "*** Killing stale mininet node processes\n" )
105
        killprocs( 'mininet:' )
106

    
107
        info( "*** Shutting down stale tunnels\n" )
108
        killprocs( 'Tunnel=Ethernet' )
109
        killprocs( '.ssh/mn')
110
        sh( 'rm -f ~/.ssh/mn/*' )
111

    
112
        # Call any additional cleanup code if necessary
113
        for callback in cls.callbacks:
114
            callback()
115

    
116
        info( "*** Cleanup complete.\n" )
117

    
118
    @classmethod
119
    def addCleanupCallback( cls, callback ):
120
        "Add cleanup callback"
121
        if callback not in cls.callbacks:
122
            cls.callbacks.append( callback )
123

    
124

    
125
cleanup = Cleanup.cleanup
126
addCleanupCallback = Cleanup.addCleanupCallback