CustomConstructor -> CustomClass, which calls specialClass
specialClass is an analog of functools.partial but for classes. We can now use it instead of partial() in mn, so that Mininet can introspect on the actual base class. Fixes #488
This commit is contained in:
@@ -33,7 +33,7 @@ from mininet.nodelib import LinuxBridge
|
|||||||
from mininet.link import Link, TCLink, OVSLink
|
from mininet.link import Link, TCLink, OVSLink
|
||||||
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
|
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
|
||||||
from mininet.topolib import TreeTopo, TorusTopo
|
from mininet.topolib import TreeTopo, TorusTopo
|
||||||
from mininet.util import customConstructor, splitArgs
|
from mininet.util import customClass, specialClass, splitArgs
|
||||||
from mininet.util import buildTopo
|
from mininet.util import buildTopo
|
||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@@ -69,8 +69,8 @@ SWITCHES = { 'user': UserSwitch,
|
|||||||
|
|
||||||
HOSTDEF = 'proc'
|
HOSTDEF = 'proc'
|
||||||
HOSTS = { 'proc': Host,
|
HOSTS = { 'proc': Host,
|
||||||
'rt': partial( CPULimitedHost, sched='rt' ),
|
'rt': specialClass( CPULimitedHost, defaults=dict( sched='rt' ) ),
|
||||||
'cfs': partial( CPULimitedHost, sched='cfs' ) }
|
'cfs': specialClass( CPULimitedHost, defaults=dict( sched='cfs' ) ) }
|
||||||
|
|
||||||
CONTROLLERDEF = 'default'
|
CONTROLLERDEF = 'default'
|
||||||
CONTROLLERS = { 'ref': Controller,
|
CONTROLLERS = { 'ref': Controller,
|
||||||
@@ -311,10 +311,10 @@ class MininetRunner( object ):
|
|||||||
self.options.switch )
|
self.options.switch )
|
||||||
|
|
||||||
topo = buildTopo( TOPOS, self.options.topo )
|
topo = buildTopo( TOPOS, self.options.topo )
|
||||||
switch = customConstructor( SWITCHES, self.options.switch )
|
switch = customClass( SWITCHES, self.options.switch )
|
||||||
host = customConstructor( HOSTS, self.options.host )
|
host = customClass( HOSTS, self.options.host )
|
||||||
controller = customConstructor( CONTROLLERS, self.options.controller )
|
controller = customClass( CONTROLLERS, self.options.controller )
|
||||||
link = customConstructor( LINKS, self.options.link )
|
link = customClass( LINKS, self.options.link )
|
||||||
|
|
||||||
if self.validate:
|
if self.validate:
|
||||||
self.validate( self.options )
|
self.validate( self.options )
|
||||||
|
|||||||
+38
-25
@@ -523,43 +523,56 @@ def splitArgs( argstr ):
|
|||||||
kwargs[ key ] = makeNumeric( val )
|
kwargs[ key ] = makeNumeric( val )
|
||||||
return fn, args, kwargs
|
return fn, args, kwargs
|
||||||
|
|
||||||
def customConstructor( constructors, argStr ):
|
def customClass( classes, argStr ):
|
||||||
"""Return custom constructor based on argStr
|
"""Return customized class based on argStr
|
||||||
The args and key/val pairs in argsStr will be automatically applied
|
The args and key/val pairs in argStr will be automatically applied
|
||||||
when the generated constructor is later used.
|
when the generated class is later used.
|
||||||
"""
|
"""
|
||||||
cname, newargs, kwargs = splitArgs( argStr )
|
cname, args, kwargs = splitArgs( argStr )
|
||||||
constructor = constructors.get( cname, None )
|
cls = classes.get( cname, None )
|
||||||
|
|
||||||
if not constructor:
|
if not cname:
|
||||||
raise Exception( "error: %s is unknown - please specify one of %s" %
|
raise Exception( "error: %s is unknown - please specify one of %s" %
|
||||||
( cname, constructors.keys() ) )
|
( cname, constructors.keys() ) )
|
||||||
|
if not args and not kwargs:
|
||||||
|
return cls
|
||||||
|
|
||||||
if not newargs and not kwargs:
|
return specialClass( cls, append=args, defaults=kwargs )
|
||||||
return constructor
|
|
||||||
|
|
||||||
if not isinstance( constructor, type ):
|
def specialClass( cls, prepend=None, append=None,
|
||||||
raise Exception( "error: invalid arguments %s" % argStr )
|
defaults=None, override=None ):
|
||||||
|
"""Like functools.partial, but it returns a class
|
||||||
|
prepend: arguments to prepend to argument list
|
||||||
|
append: arguments to append to argument list
|
||||||
|
defaults: default values for keyword arguments
|
||||||
|
override: keyword arguments to override"""
|
||||||
|
|
||||||
# Return a customized subclass
|
if prepend is None:
|
||||||
cls = constructor
|
prepend = []
|
||||||
|
|
||||||
|
if append is None:
|
||||||
|
append = []
|
||||||
|
|
||||||
|
if defaults is None:
|
||||||
|
defaults = {}
|
||||||
|
|
||||||
|
if override is None:
|
||||||
|
override = {}
|
||||||
|
|
||||||
class CustomClass( cls ):
|
class CustomClass( cls ):
|
||||||
"Customized subclass, useful for Node, Link, and other classes"
|
"Customized subclass with preset args/params"
|
||||||
def __init__( self, name, *args, **params ):
|
def __init__( self, *args, **params ):
|
||||||
params = params.copy()
|
newparams = defaults.copy()
|
||||||
params.update( kwargs )
|
newparams.update( params )
|
||||||
if not newargs:
|
newparams.update( override )
|
||||||
cls.__init__( self, name, *args, **params )
|
cls.__init__( self, *( list( prepend ) + list( args ) +
|
||||||
return
|
list( append ) ),
|
||||||
if args:
|
**newparams )
|
||||||
warn( 'warning: %s replacing %s with %s\n' %
|
|
||||||
( constructor, args, newargs ) )
|
|
||||||
cls.__init__( self, name, *newargs, **params )
|
|
||||||
|
|
||||||
CustomClass.__name__ = '%s%s' % ( cls.__name__, kwargs )
|
CustomClass.__name__ = '%s%s' % ( cls.__name__, defaults )
|
||||||
return CustomClass
|
return CustomClass
|
||||||
|
|
||||||
|
|
||||||
def buildTopo( topos, topoStr ):
|
def buildTopo( topos, topoStr ):
|
||||||
"""Create topology from string with format (object, arg1, arg2,...).
|
"""Create topology from string with format (object, arg1, arg2,...).
|
||||||
input topos is a dict of topo names to constructors, possibly w/args.
|
input topos is a dict of topo names to constructors, possibly w/args.
|
||||||
|
|||||||
Reference in New Issue
Block a user