Change API for more efficient remount and unmount.

This commit is contained in:
Bob Lantz
2013-09-11 12:00:13 -07:00
committed by Brian O'Connor
parent 5ae8c936e7
commit f344290368
+51 -21
View File
@@ -7,17 +7,20 @@ This creates hosts with private directories as desired.
""" """
from mininet.net import Mininet from mininet.net import Mininet
from mininet.node import Host, Switch, Controller from mininet.node import Host
from mininet.cli import CLI from mininet.cli import CLI
from mininet.util import errFail, quietRun, errRun from mininet.util import errFail, quietRun, errRun
from mininet.topo import SingleSwitchTopo from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel, info, debug from mininet.log import setLogLevel, info, debug
from os.path import join, realpath from os.path import realpath
from functools import partial from functools import partial
# Utility functions for unmounting a tree # Utility functions for unmounting a tree
MNRUNDIR = realpath( '/var/run/mn' )
def mountPoints(): def mountPoints():
"Return list of mounted file systems" "Return list of mounted file systems"
mtab, _err, _ret = errFail( 'cat /proc/mounts' ) mtab, _err, _ret = errFail( 'cat /proc/mounts' )
@@ -31,7 +34,7 @@ def mountPoints():
mounts.append( mount ) mounts.append( mount )
return mounts return mounts
def unmountAll( dir='/var/run/mn' ): def unmountAll( dir=MNRUNDIR ):
"Unmount all mounts under a directory tree" "Unmount all mounts under a directory tree"
dir = realpath( dir ) dir = realpath( dir )
# Find all mounts below dir # Find all mounts below dir
@@ -53,11 +56,17 @@ def unmountAll( dir='/var/run/mn' ):
class HostWithPrivateDirs( Host ): class HostWithPrivateDirs( Host ):
"Host with private directories" "Host with private directories"
mnRunDir = realpath( '/var/run/mn' ) mnRunDir = MNRUNDIR
def __init__(self, name, *args, **kwargs ): 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.privateDirs = kwargs.pop( 'privateDirs', [] )
self.remounts = kwargs.pop( 'remounts', [] )
self.unmount = kwargs.pop( 'unmount', True )
Host.__init__( self, name, *args, **kwargs ) Host.__init__( self, name, *args, **kwargs )
self.rundir = '%s/%s' % ( self.mnRunDir, name ) self.rundir = '%s/%s' % ( self.mnRunDir, name )
if self.privateDirs: if self.privateDirs:
@@ -86,19 +95,28 @@ class HostWithPrivateDirs( Host ):
errFail( 'mount -B %s %s' % errFail( 'mount -B %s %s' %
( privateDir, mountPoint) ) ( privateDir, mountPoint) )
def remountDirs( self, fstypes=[ 'nfs' ] ): def mountDirs( self, dirs ):
"Remount mounted file systems" "Mount a list of directories"
dirs = self.cmd( 'cat /proc/mounts' ).strip().split( '\n' ) 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: for dir in dirs:
line = dir.split() line = dir.split()
mountpoint, fstype = line[ 1 ], line[ 2 ] mountpoint, fstype = line[ 1 ], line[ 2 ]
# Don't re-remount directories!!! # Don't re-remount directories!!!
if mountpoint.find( self.mnRunDir ) == 0: if mountpoint.find( cls.mnRunDir ) == 0:
continue continue
if fstype in fstypes: if fstype in fstypes:
print "remounting:", mountpoint remounts.append( mountpoint )
errFail( 'mount -B %s %s' % ( return remounts
mountpoint, self.root + mountpoint ) )
def createBindMounts( self ): def createBindMounts( self ):
"""Create a chroot directory structure, """Create a chroot directory structure,
@@ -113,7 +131,7 @@ class HostWithPrivateDirs( Host ):
# Recursively mount / in private doort # Recursively mount / in private doort
# note we'll remount /sys and /proc later # note we'll remount /sys and /proc later
errFail( 'mount -B / ' + self.root ) errFail( 'mount -B / ' + self.root )
self.remountDirs() self.mountDirs( self.remounts )
self.mountPrivateDirs() self.mountPrivateDirs()
def unmountBindMounts( self ): def unmountBindMounts( self ):
@@ -131,33 +149,45 @@ class HostWithPrivateDirs( Host ):
return Host.popen( self, *args, **kwargs ) return Host.popen( self, *args, **kwargs )
def cleanup( self ): 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 # Wait for process to actually terminate
self.shell.wait() self.shell.wait()
Host.cleanup( self ) Host.cleanup( self )
self.unmountBindMounts() if self.unmount:
errFail( 'rmdir ' + self.root ) self.unmountBindMounts()
errFail( 'rmdir ' + self.root )
# Convenience aliases
findRemounts = HostWithPrivateDirs.findRemounts
# Sample usage # Sample usage
def testHostWithPrivateDirs(): def testHostWithPrivateDirs():
"Test bind mounts" "Test bind mounts"
topo = SingleSwitchTopo( 2 ) topo = SingleSwitchTopo( 10 )
remounts = findRemounts( fstypes=[ 'nfs' ] )
privateDirs = [ '/var/log', '/var/run' ] 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 = Mininet( topo=topo, host=host )
net.start() net.start()
print 'Private Directories:', privateDirs info( 'Private Directories:', privateDirs, '\n' )
CLI( net ) CLI( net )
net.stop() net.stop()
# We do this all at once to save a bit of time
info( 'Unmounting host bind mounts...\n' )
unmountAll()
if __name__ == '__main__': if __name__ == '__main__':
unmountAll() unmountAll()
setLogLevel( 'info' ) setLogLevel( 'info' )
testHostWithPrivateDirs() testHostWithPrivateDirs()
unmountAll() info( 'Done.\n')