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