diff --git a/mininet/net.py b/mininet/net.py
index 1c932f9..8edaee3 100755
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -91,7 +91,7 @@ import re
import select
import signal
from time import sleep
-from itertools import chain
+from itertools import chain, groupby
from mininet.cli import CLI
from mininet.log import info, error, debug, output
@@ -408,10 +408,9 @@ class Mininet( object ):
info( '*** Stopping %i terms\n' % len( self.terms ) )
self.stopXterms()
info( '*** Stopping %i switches\n' % len( self.switches ) )
- if self.switches:
- swclass = type( self.switches[ 0 ] )
+ for swclass, switches in groupby( sorted( self.switches, key=type ), type ):
if hasattr( swclass, 'batchShutdown' ):
- swclass.batchShutdown( self.switches )
+ swclass.batchShutdown( switches )
for switch in self.switches:
info( switch.name + ' ' )
switch.stop()
diff --git a/mininet/node.py b/mininet/node.py
index 72c782a..568d986 100644
--- a/mininet/node.py
+++ b/mininet/node.py
@@ -856,6 +856,8 @@ class UserSwitch( Switch ):
'(openflow.org)' )
if self.listenPort:
self.opts += ' --listen=ptcp:%i ' % self.listenPort
+ else:
+ self.opts += ' --listen=punix:/tmp/%s.listen' % self.name
self.dpopts = dpopts
@classmethod
@@ -868,7 +870,7 @@ class UserSwitch( Switch ):
"Run dpctl command"
listenAddr = None
if not self.listenPort:
- listenAddr = 'unix:/tmp/' + self.name
+ listenAddr = 'unix:/tmp/%s.listen' % self.name
else:
listenAddr = 'tcp:127.0.0.1:%i' % self.listenPort
return self.cmd( 'dpctl ' + ' '.join( args ) +
@@ -1034,7 +1036,7 @@ class OVSSwitch( Switch ):
"Call ovs-vsctl del-br on all OVSSwitches in a list"
quietRun( 'ovs-vsctl ' +
' -- '.join( '--if-exists del-br %s' % s
- for s in switches if type(s) == cls ) )
+ for s in switches ) )
def dpctl( self, *args ):
"Run ovs-ofctl command"
@@ -1108,16 +1110,16 @@ class OVSSwitch( Switch ):
self.cmd( 'ovs-vsctl add-br', self )
for intf in self.intfList():
if not intf.IP():
- self.cmd('ovs-vsctl add-port', self, intf )
- cmd = ('ovs-vsctl set Bridge %s ' % self +
- 'other_config:datapath-id=%s ' % self.dpid +
- '-- set-fail-mode %s %s ' % ( self, self.failMode ) +
- '-- set-controller %s %s ' % ( self, clist ) )
+ self.cmd( 'ovs-vsctl add-port', self, intf )
+ cmd = ( 'ovs-vsctl set Bridge %s ' % self +
+ 'other_config:datapath-id=%s ' % self.dpid +
+ '-- set-fail-mode %s %s ' % ( self, self.failMode ) +
+ '-- set-controller %s %s ' % ( self, clist ) )
if not self.inband:
cmd += ( '-- set bridge %s '
'other-config:disable-in-band=true ' % self )
if self.datapath == 'user':
- cmd += '-- set bridge %s datapath_type=netdev ' % self
+ cmd += '-- set bridge %s datapath_type=netdev ' % self
# Reconnect quickly to controllers (1s vs. 15s max_backoff)
for uuid in self.controllerUUIDs():
if uuid.count( '-' ) != 4:
@@ -1144,8 +1146,9 @@ OVSKernelSwitch = OVSSwitch
class IVSSwitch(Switch):
"""IVS virtual switch"""
- def __init__( self, name, **kwargs ):
+ def __init__( self, name, verbose=True, **kwargs ):
Switch.__init__( self, name, **kwargs )
+ self.verbose = verbose
@classmethod
def setup( cls ):
@@ -1160,12 +1163,19 @@ class IVSSwitch(Switch):
'not be loaded. Try modprobe openvswitch.\n' )
exit( 1 )
+ @classmethod
+ def batchShutdown( cls, switches ):
+ "Kill each IVS switch, to be waited on later in stop()"
+ for switch in switches:
+ switch.cmd( 'kill %ivs' )
+
def start( self, controllers ):
"Start up a new IVS switch"
args = ['ivs']
args.extend( ['--name', self.name] )
args.extend( ['--dpid', self.dpid] )
- args.extend( ['--verbose'] )
+ if self.verbose:
+ args.extend( ['--verbose'] )
for intf in self.intfs.values():
if not intf.IP():
args.extend( ['-i', intf.name] )
diff --git a/mininet/util.py b/mininet/util.py
index b03e945..5cb27f4 100644
--- a/mininet/util.py
+++ b/mininet/util.py
@@ -273,7 +273,7 @@ def ipAdd( i, prefixLen=8, ipBaseNum=0x0a000000 ):
ipBaseNum: option base IP address as int
returns IP address as string"""
imax = 0xffffffff >> prefixLen
- assert i <= imax
+ assert i <= imax, 'Not enough IP addresses in the subnet'
mask = 0xffffffff ^ imax
ipnum = ( ipBaseNum & mask ) + i
return ipStr( ipnum )
@@ -281,6 +281,8 @@ def ipAdd( i, prefixLen=8, ipBaseNum=0x0a000000 ):
def ipParse( ip ):
"Parse an IP address and return an unsigned int."
args = [ int( arg ) for arg in ip.split( '.' ) ]
+ while ( len(args) < 4 ):
+ args.append( 0 )
return ipNum( *args )
def netParse( ipstr ):
@@ -290,6 +292,10 @@ def netParse( ipstr ):
if '/' in ipstr:
ip, pf = ipstr.split( '/' )
prefixLen = int( pf )
+ #if no prefix is specified, set the prefix to 24
+ else:
+ ip = ipstr
+ prefixLen = 24
return ipParse( ip ), prefixLen
def checkInt( s ):
diff --git a/util/vm/build.py b/util/vm/build.py
index 3e0daa7..be809ec 100755
--- a/util/vm/build.py
+++ b/util/vm/build.py
@@ -158,7 +158,7 @@ def depend():
run( 'sudo apt-get -y update' )
run( 'sudo apt-get install -y'
' kvm cloud-utils genisoimage qemu-kvm qemu-utils'
- ' e2fsprogs dnsmasq'
+ ' e2fsprogs dnsmasq curl'
' python-setuptools mtools zip' )
run( 'sudo easy_install pexpect' )
@@ -457,16 +457,16 @@ def boot( cow, kernel, initrd, logfile, memory=1024 ):
return vm
-def login( vm ):
+def login( vm, user='mininet', password='mininet' ):
"Log in to vm (pexpect object)"
log( '* Waiting for login prompt' )
vm.expect( 'login: ' )
log( '* Logging in' )
- vm.sendline( 'mininet' )
+ vm.sendline( user )
log( '* Waiting for password prompt' )
vm.expect( 'Password: ' )
log( '* Sending password' )
- vm.sendline( 'mininet' )
+ vm.sendline( password )
log( '* Waiting for login...' )
@@ -628,9 +628,9 @@ OVFTemplate = """
The nat network
-
-A Mininet Virtual Machine (%(name)s)
-mininet-vm
+
+%(vminfo)s (%(name)s)
+%(vmname)s
The kind of installed guest operating system
%(osname)s
@@ -640,10 +640,10 @@ OVFTemplate = """
-
hertz * 10^6
Number of Virtual CPUs
-1 virtual CPU(s)
+%(cpus)s virtual CPU(s)
1
3
-1
+%(cpus)s
-
byte * 2^20
@@ -694,19 +694,23 @@ OVFTemplate = """
"""
-def generateOVF( name, osname, osid, diskname, disksize, mem=1024 ):
+def generateOVF( name, osname, osid, diskname, disksize, mem=1024, cpus=1,
+ vmname='Mininet-VM', vminfo='A Mininet Virtual Machine' ):
"""Generate (and return) OVF file "name.ovf"
name: root name of OVF file to generate
osname: OS name for OVF (Ubuntu | Ubuntu 64-bit)
osid: OS ID for OVF (93 | 94 )
diskname: name of disk file
disksize: size of virtual disk in bytes
- mem: VM memory size in MB"""
+ mem: VM memory size in MB
+ cpus: # of virtual CPUs
+ vmname: Name for VM (default name when importing)
+ vmimfo: Brief description of VM for OVF"""
ovf = name + '.ovf'
filesize = stat( diskname )[ ST_SIZE ]
params = dict( osname=osname, osid=osid, diskname=diskname,
filesize=filesize, disksize=disksize, name=name,
- mem=mem )
+ mem=mem, cpus=cpus, vmname=vmname, vminfo=vminfo )
xmltext = OVFTemplate % params
with open( ovf, 'w+' ) as f:
f.write( xmltext )
@@ -781,6 +785,9 @@ def build( flavor='raring32server', tests=None, pre='', post='', memory=1024 ):
def runTests( vm, tests=None, pre='', post='', prompt=Prompt ):
"Run tests (list) in vm (pexpect object)"
+ if Branch:
+ checkOutBranch( vm, branch=Branch )
+ vm.expect( prompt )
if not tests:
tests = []
if pre:
@@ -811,8 +818,8 @@ def getMininetVersion( vm ):
return version
-def bootAndRunTests( image, tests=None, pre='', post='', prompt=Prompt,
- memory=1024, outputFile=None ):
+def bootAndRun( image, prompt=Prompt, memory=1024, outputFile=None,
+ runFunction=None, **runArgs ):
"""Boot and test VM
tests: list of tests to run
pre: command line to run in VM before tests
@@ -840,11 +847,9 @@ def bootAndRunTests( image, tests=None, pre='', post='', prompt=Prompt,
login( vm )
log( '* Waiting for prompt after login' )
vm.expect( prompt )
- if Branch:
- checkOutBranch( vm, branch=Branch )
- vm.expect( prompt )
- runTests( vm, tests=tests, pre=pre, post=post )
- # runTests eats its last prompt, but maybe it shouldn't...
+ # runFunction should begin with sendline and should eat its last prompt
+ if runFunction:
+ runFunction( vm, **runArgs )
log( '* Shutting down' )
vm.sendline( 'sudo shutdown -h now ' )
log( '* Waiting for shutdown' )
@@ -950,9 +955,8 @@ def parseArgs():
log( '* BUILD FAILED with exception: ', e )
exit( 1 )
for image in args.image:
- bootAndRunTests( image, tests=args.test, pre=args.run,
- post=args.post, memory=args.memory,
- outputFile=args.out )
+ bootAndRun( image, runFunction=runTests, tests=args.test, pre=args.run,
+ post=args.post, memory=args.memory, outputFile=args.out )
if not ( args.depend or args.list or args.clean or args.flavor
or args.image ):
parser.print_help()