Enable --custom files to import ONOSCLI
Since --custom files are execed, subsequently importing them
actually creates duplicate classes. This wouldn't be a problem
except that we depend on isinstance(). As a workaround, we allow
the class name to match if isinstance() fails, assuming it will
be a class that is compatible with ONOSCluster or ONOSNode.
Example: env PYTHONPATH=. mn --custom onos.py,mytest.py
where mytest.py imports onos
Change-Id: Ib4cda82fbdd612420de1e113ab768e2f137d5213
diff --git a/tools/dev/mininet/onos.py b/tools/dev/mininet/onos.py
index 2fb6f94..3473434 100755
--- a/tools/dev/mininet/onos.py
+++ b/tools/dev/mininet/onos.py
@@ -210,6 +210,25 @@
return RenamedTopoCls( *args, **kwargs )
+# We accept objects that "claim" to be a particular class,
+# since the class definitions can be both execed (--custom) and
+# imported (in another custom file), which breaks isinstance().
+# In order for this to work properly, a class should not be
+# renamed so as to inappropriately omit or include the class
+# name text. Note that mininet.util.specialClass renames classes
+# by adding the specialized parameter names and values.
+
+def isONOSNode( obj ):
+ "Does obj claim to be some kind of ONOSNode?"
+ return ( isinstance( obj, ONOSNode) or
+ 'ONOSNode' in type( obj ).__name__ )
+
+def isONOSCluster( obj ):
+ "Does obj claim to be some kind of ONOSCluster?"
+ return ( isinstance( obj, ONOSCluster ) or
+ 'ONOSCluster' in type( obj ).__name__ )
+
+
class ONOSNode( Controller ):
"ONOS cluster node"
@@ -448,7 +467,7 @@
def nodes( self ):
"Return list of ONOS nodes"
- return [ h for h in self.net.hosts if isinstance( h, ONOSNode ) ]
+ return [ h for h in self.net.hosts if isONOSNode( h ) ]
def configPortForwarding( self, ports=[], action='A' ):
"""Start or stop port forwarding (any intf) for all nodes
@@ -471,7 +490,7 @@
"Connect to ONOSCluster"
self.controllers = controllers
assert ( len( controllers ) is 1 and
- isinstance( controllers[ 0 ], ONOSCluster ) )
+ isONOSCluster( controllers[ 0 ] ) )
clist = controllers[ 0 ].nodes()
return super( ONOSSwitchMixin, self ).start( clist )
@@ -517,7 +536,7 @@
def __init__( self, net, **kwargs ):
c0 = net.controllers[ 0 ]
- if isinstance( c0, ONOSCluster ):
+ if isONOSCluster( c0 ):
net = MininetFacade( net, cnet=c0.net )
OldCLI.__init__( self, net, **kwargs )
@@ -528,7 +547,7 @@
def do_onos( self, line ):
"Send command to ONOS CLI"
c0 = self.mn.controllers[ 0 ]
- if isinstance( c0, ONOSCluster ):
+ if isONOSCluster( c0 ):
# cmdLoop strips off command name 'onos'
if line.startswith( ':' ):
line = 'onos' + line
@@ -556,9 +575,9 @@
def do_status( self, line ):
"Return status of ONOS cluster(s)"
for c in self.mn.controllers:
- if isinstance( c, ONOSCluster ):
+ if isONOSCluster( c ):
for node in c.net.hosts:
- if isinstance( node, ONOSNode ):
+ if isONOSNode( node ):
errors, warnings = node.checkLog()
running = ( 'Running' if node.isRunning()
else 'Exited' )