From f34429036800574328097bb957d6c493bd5d7260 Mon Sep 17 00:00:00 2001 From: Bob Lantz <rlantz@cs.stanford.edu> Date: Sun, 7 Jul 2013 15:27:49 -0700 Subject: [PATCH] Change API for more efficient remount and unmount. --- examples/bind.py | 72 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/examples/bind.py b/examples/bind.py index 142eec40..d4d28a44 100755 --- a/examples/bind.py +++ b/examples/bind.py @@ -7,17 +7,20 @@ """ from mininet.net import Mininet -from mininet.node import Host, Switch, Controller +from mininet.node import Host from mininet.cli import CLI from mininet.util import errFail, quietRun, errRun from mininet.topo import SingleSwitchTopo from mininet.log import setLogLevel, info, debug -from os.path import join, realpath +from os.path import realpath from functools import partial + # Utility functions for unmounting a tree +MNRUNDIR = realpath( '/var/run/mn' ) + def mountPoints(): "Return list of mounted file systems" mtab, _err, _ret = errFail( 'cat /proc/mounts' ) @@ -31,7 +34,7 @@ def mountPoints(): mounts.append( mount ) return mounts -def unmountAll( dir='/var/run/mn' ): +def unmountAll( dir=MNRUNDIR ): "Unmount all mounts under a directory tree" dir = realpath( dir ) # Find all mounts below dir @@ -53,11 +56,17 @@ def unmountAll( dir='/var/run/mn' ): class HostWithPrivateDirs( Host ): "Host with private directories" - mnRunDir = realpath( '/var/run/mn' ) + mnRunDir = MNRUNDIR def __init__(self, name, *args, **kwargs ): - "privateDirs: list of private directories" + """privateDirs: list of private directories + remounts: dirs to remount + unmount: unmount dirs in cleanup? (True) + Note: if unmount is False, you must call unmountAll() + manually.""" self.privateDirs = kwargs.pop( 'privateDirs', [] ) + self.remounts = kwargs.pop( 'remounts', [] ) + self.unmount = kwargs.pop( 'unmount', True ) Host.__init__( self, name, *args, **kwargs ) self.rundir = '%s/%s' % ( self.mnRunDir, name ) if self.privateDirs: @@ -86,19 +95,28 @@ def mountPrivateDirs( self ): errFail( 'mount -B %s %s' % ( privateDir, mountPoint) ) - def remountDirs( self, fstypes=[ 'nfs' ] ): - "Remount mounted file systems" - dirs = self.cmd( 'cat /proc/mounts' ).strip().split( '\n' ) + def mountDirs( self, dirs ): + "Mount a list of directories" + for dir in dirs: + mountpoint = self.root + dir + errFail( 'mount -B %s %s' % + ( dir, mountpoint ) ) + + @classmethod + def findRemounts( cls, fstypes=[ 'nfs' ] ): + """Identify mount points in /proc/mounts to remount + fstypes: file system types to match""" + dirs = quietRun( 'cat /proc/mounts' ).strip().split( '\n' ) + remounts = [] for dir in dirs: line = dir.split() mountpoint, fstype = line[ 1 ], line[ 2 ] # Don't re-remount directories!!! - if mountpoint.find( self.mnRunDir ) == 0: + if mountpoint.find( cls.mnRunDir ) == 0: continue if fstype in fstypes: - print "remounting:", mountpoint - errFail( 'mount -B %s %s' % ( - mountpoint, self.root + mountpoint ) ) + remounts.append( mountpoint ) + return remounts def createBindMounts( self ): """Create a chroot directory structure, @@ -113,7 +131,7 @@ def createBindMounts( self ): # Recursively mount / in private doort # note we'll remount /sys and /proc later errFail( 'mount -B / ' + self.root ) - self.remountDirs() + self.mountDirs( self.remounts ) self.mountPrivateDirs() def unmountBindMounts( self ): @@ -131,33 +149,45 @@ def popen( self, *args, **kwargs ): return Host.popen( self, *args, **kwargs ) def cleanup( self ): - "Clean up, then unmount bind mounts" + """Clean up, then unmount bind mounts + unmount: actually unmount bind mounts?""" # Wait for process to actually terminate self.shell.wait() Host.cleanup( self ) - self.unmountBindMounts() - errFail( 'rmdir ' + self.root ) + if self.unmount: + self.unmountBindMounts() + errFail( 'rmdir ' + self.root ) + + +# Convenience aliases + +findRemounts = HostWithPrivateDirs.findRemounts + # Sample usage def testHostWithPrivateDirs(): "Test bind mounts" - topo = SingleSwitchTopo( 2 ) + topo = SingleSwitchTopo( 10 ) + remounts = findRemounts( fstypes=[ 'nfs' ] ) privateDirs = [ '/var/log', '/var/run' ] - host = partial( HostWithPrivateDirs, privateDirs=privateDirs ) + host = partial( HostWithPrivateDirs, remounts=remounts, + privateDirs=privateDirs, unmount=False ) net = Mininet( topo=topo, host=host ) net.start() - print 'Private Directories:', privateDirs + info( 'Private Directories:', privateDirs, '\n' ) CLI( net ) net.stop() + # We do this all at once to save a bit of time + info( 'Unmounting host bind mounts...\n' ) + unmountAll() if __name__ == '__main__': unmountAll() setLogLevel( 'info' ) testHostWithPrivateDirs() - unmountAll() - + info( 'Done.\n') -- GitLab