diff --git a/bin/mn b/bin/mn index d69b6b1..082a437 100755 --- a/bin/mn +++ b/bin/mn @@ -33,7 +33,7 @@ from mininet.nodelib import LinuxBridge from mininet.link import Link, TCLink, OVSLink from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo 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 functools import partial @@ -69,8 +69,8 @@ SWITCHES = { 'user': UserSwitch, HOSTDEF = 'proc' HOSTS = { 'proc': Host, - 'rt': partial( CPULimitedHost, sched='rt' ), - 'cfs': partial( CPULimitedHost, sched='cfs' ) } + 'rt': specialClass( CPULimitedHost, defaults=dict( sched='rt' ) ), + 'cfs': specialClass( CPULimitedHost, defaults=dict( sched='cfs' ) ) } CONTROLLERDEF = 'default' CONTROLLERS = { 'ref': Controller, @@ -311,10 +311,10 @@ class MininetRunner( object ): self.options.switch ) topo = buildTopo( TOPOS, self.options.topo ) - switch = customConstructor( SWITCHES, self.options.switch ) - host = customConstructor( HOSTS, self.options.host ) - controller = customConstructor( CONTROLLERS, self.options.controller ) - link = customConstructor( LINKS, self.options.link ) + switch = customClass( SWITCHES, self.options.switch ) + host = customClass( HOSTS, self.options.host ) + controller = customClass( CONTROLLERS, self.options.controller ) + link = customClass( LINKS, self.options.link ) if self.validate: self.validate( self.options ) diff --git a/mininet/util.py b/mininet/util.py index 517e0db..6755c6d 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -523,43 +523,56 @@ def splitArgs( argstr ): kwargs[ key ] = makeNumeric( val ) return fn, args, kwargs -def customConstructor( constructors, argStr ): - """Return custom constructor based on argStr - The args and key/val pairs in argsStr will be automatically applied - when the generated constructor is later used. +def customClass( classes, argStr ): + """Return customized class based on argStr + The args and key/val pairs in argStr will be automatically applied + when the generated class is later used. """ - cname, newargs, kwargs = splitArgs( argStr ) - constructor = constructors.get( cname, None ) + cname, args, kwargs = splitArgs( argStr ) + cls = classes.get( cname, None ) - if not constructor: + if not cname: raise Exception( "error: %s is unknown - please specify one of %s" % ( cname, constructors.keys() ) ) + if not args and not kwargs: + return cls - if not newargs and not kwargs: - return constructor + return specialClass( cls, append=args, defaults=kwargs ) - if not isinstance( constructor, type ): - raise Exception( "error: invalid arguments %s" % argStr ) +def specialClass( cls, prepend=None, append=None, + 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 - cls = constructor + if prepend is None: + prepend = [] + + if append is None: + append = [] + + if defaults is None: + defaults = {} + + if override is None: + override = {} class CustomClass( cls ): - "Customized subclass, useful for Node, Link, and other classes" - def __init__( self, name, *args, **params ): - params = params.copy() - params.update( kwargs ) - if not newargs: - cls.__init__( self, name, *args, **params ) - return - if args: - warn( 'warning: %s replacing %s with %s\n' % - ( constructor, args, newargs ) ) - cls.__init__( self, name, *newargs, **params ) + "Customized subclass with preset args/params" + def __init__( self, *args, **params ): + newparams = defaults.copy() + newparams.update( params ) + newparams.update( override ) + cls.__init__( self, *( list( prepend ) + list( args ) + + list( append ) ), + **newparams ) - CustomClass.__name__ = '%s%s' % ( cls.__name__, kwargs ) + CustomClass.__name__ = '%s%s' % ( cls.__name__, defaults ) return CustomClass + def buildTopo( topos, topoStr ): """Create topology from string with format (object, arg1, arg2,...). input topos is a dict of topo names to constructors, possibly w/args.