Change API for more efficient remount and unmount.
This commit is contained in:
committed by
Brian O'Connor
parent
5ae8c936e7
commit
f344290368
+51
-21
@@ -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')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user