Add net.delNode(), net.delLink() and associated methods
This makes the mid-level net.add*() API symmetric. You can now delete hosts, switches, controllers and links using a new net.del*() API, as well as del net[ 'nodename' ].
This commit is contained in:
+6
-4
@@ -202,6 +202,8 @@ class Intf( object ):
|
|||||||
# if self.node.inNamespace:
|
# if self.node.inNamespace:
|
||||||
# Link may have been dumped into root NS
|
# Link may have been dumped into root NS
|
||||||
# quietRun( 'ip link del ' + self.name )
|
# quietRun( 'ip link del ' + self.name )
|
||||||
|
self.node.delIntf( self )
|
||||||
|
self.link = None
|
||||||
|
|
||||||
def status( self ):
|
def status( self ):
|
||||||
"Return intf status as a string"
|
"Return intf status as a string"
|
||||||
@@ -471,10 +473,10 @@ class Link( object ):
|
|||||||
def delete( self ):
|
def delete( self ):
|
||||||
"Delete this link"
|
"Delete this link"
|
||||||
self.intf1.delete()
|
self.intf1.delete()
|
||||||
# We only need to delete one side, though this doesn't seem to
|
self.intf1 = None
|
||||||
# cost us much and might help subclasses.
|
self.intf2.delete()
|
||||||
# self.intf2.delete()
|
self.intf2 = None
|
||||||
|
|
||||||
def stop( self ):
|
def stop( self ):
|
||||||
"Override to stop and clean up link as needed"
|
"Override to stop and clean up link as needed"
|
||||||
self.delete()
|
self.delete()
|
||||||
|
|||||||
+59
-5
@@ -226,6 +226,24 @@ class Mininet( object ):
|
|||||||
self.nameToNode[ name ] = h
|
self.nameToNode[ name ] = h
|
||||||
return h
|
return h
|
||||||
|
|
||||||
|
def delNode( self, node, nodes=None):
|
||||||
|
"""Delete node
|
||||||
|
node: node to delete
|
||||||
|
nodes: optional list to delete from (e.g. self.hosts)"""
|
||||||
|
if nodes is None:
|
||||||
|
nodes = ( self.hosts if node in self.hosts else
|
||||||
|
( self.switches if node in self.switches else
|
||||||
|
( self.controllers if node in self.controllers else
|
||||||
|
[] ) ) )
|
||||||
|
node.stop( deleteIntfs=True )
|
||||||
|
node.terminate()
|
||||||
|
nodes.remove( node )
|
||||||
|
del self.nameToNode[ node.name ]
|
||||||
|
|
||||||
|
def delHost( self, host ):
|
||||||
|
"Delete a host"
|
||||||
|
self.delNode( host, nodes=self.hosts )
|
||||||
|
|
||||||
def addSwitch( self, name, cls=None, **params ):
|
def addSwitch( self, name, cls=None, **params ):
|
||||||
"""Add switch.
|
"""Add switch.
|
||||||
name: name of switch to add
|
name: name of switch to add
|
||||||
@@ -244,6 +262,10 @@ class Mininet( object ):
|
|||||||
self.nameToNode[ name ] = sw
|
self.nameToNode[ name ] = sw
|
||||||
return sw
|
return sw
|
||||||
|
|
||||||
|
def delSwitch( self, switch ):
|
||||||
|
"Delete a switch"
|
||||||
|
self.delNode( switch, nodes=self.switches )
|
||||||
|
|
||||||
def addController( self, name='c0', controller=None, **params ):
|
def addController( self, name='c0', controller=None, **params ):
|
||||||
"""Add controller.
|
"""Add controller.
|
||||||
controller: Controller class"""
|
controller: Controller class"""
|
||||||
@@ -265,6 +287,12 @@ class Mininet( object ):
|
|||||||
self.nameToNode[ name ] = controller_new
|
self.nameToNode[ name ] = controller_new
|
||||||
return controller_new
|
return controller_new
|
||||||
|
|
||||||
|
def delController( self, controller ):
|
||||||
|
"""Delete a controller
|
||||||
|
Warning - does not reconfigure switches, so they
|
||||||
|
may still attempt to connect to it!"""
|
||||||
|
self.delNode( controller )
|
||||||
|
|
||||||
def addNAT( self, name='nat0', connect=True, inNamespace=False,
|
def addNAT( self, name='nat0', connect=True, inNamespace=False,
|
||||||
**params):
|
**params):
|
||||||
"""Add a NAT to the Mininet network
|
"""Add a NAT to the Mininet network
|
||||||
@@ -303,9 +331,13 @@ class Mininet( object ):
|
|||||||
|
|
||||||
# Even more convenient syntax for node lookup and iteration
|
# Even more convenient syntax for node lookup and iteration
|
||||||
def __getitem__( self, key ):
|
def __getitem__( self, key ):
|
||||||
"""net [ name ] operator: Return node(s) with given name(s)"""
|
"net[ name ] operator: Return node with given name"
|
||||||
return self.nameToNode[ key ]
|
return self.nameToNode[ key ]
|
||||||
|
|
||||||
|
def __delitem__( self, key ):
|
||||||
|
"del net[ name ] operator - delete node with given name"
|
||||||
|
self.delNode( self.nameToNode[ key ] )
|
||||||
|
|
||||||
def __iter__( self ):
|
def __iter__( self ):
|
||||||
"return iterator over node names"
|
"return iterator over node names"
|
||||||
for node in chain( self.hosts, self.switches, self.controllers ):
|
for node in chain( self.hosts, self.switches, self.controllers ):
|
||||||
@@ -367,6 +399,30 @@ class Mininet( object ):
|
|||||||
self.links.append( link )
|
self.links.append( link )
|
||||||
return link
|
return link
|
||||||
|
|
||||||
|
def delLink( self, link ):
|
||||||
|
"Remove a link from this network"
|
||||||
|
link.delete()
|
||||||
|
self.links.remove( link )
|
||||||
|
|
||||||
|
def linksBetween( self, node1, node2 ):
|
||||||
|
"Return Links between node1 and node2"
|
||||||
|
return [ link for link in self.links
|
||||||
|
if ( node1, node2 ) in (
|
||||||
|
( link.intf1.node, link.intf2.node ),
|
||||||
|
( link.intf2.node, link.intf1.node ) ) ]
|
||||||
|
|
||||||
|
def delLinkBetween( self, node1, node2, index=0, allLinks=False ):
|
||||||
|
"""Delete link(s) between node1 and node2
|
||||||
|
index: index of link to delete if multiple links (0)
|
||||||
|
allLinks: ignore index and delete all such links (False)
|
||||||
|
returns: deleted link(s)"""
|
||||||
|
links = self.linksBetween( node1, node2 )
|
||||||
|
if not allLinks:
|
||||||
|
links = [ links[ index ] ]
|
||||||
|
for link in links:
|
||||||
|
self.delLink( link )
|
||||||
|
return links
|
||||||
|
|
||||||
def configHosts( self ):
|
def configHosts( self ):
|
||||||
"Configure a set of hosts."
|
"Configure a set of hosts."
|
||||||
for host in self.hosts:
|
for host in self.hosts:
|
||||||
@@ -840,10 +896,8 @@ class Mininet( object ):
|
|||||||
elif dst not in self.nameToNode:
|
elif dst not in self.nameToNode:
|
||||||
error( 'dst not in network: %s\n' % dst )
|
error( 'dst not in network: %s\n' % dst )
|
||||||
else:
|
else:
|
||||||
if isinstance( src, basestring ):
|
src = self.nameToNode[ src ]
|
||||||
src = self.nameToNode[ src ]
|
dst = self.nameToNode[ dst ]
|
||||||
if isinstance( dst, basestring ):
|
|
||||||
dst = self.nameToNode[ dst ]
|
|
||||||
connections = src.connectionsTo( dst )
|
connections = src.connectionsTo( dst )
|
||||||
if len( connections ) == 0:
|
if len( connections ) == 0:
|
||||||
error( 'src and dst not connected: %s %s\n' % ( src, dst) )
|
error( 'src and dst not connected: %s %s\n' % ( src, dst) )
|
||||||
|
|||||||
@@ -431,6 +431,15 @@ class Node( object ):
|
|||||||
debug( 'moving', intf, 'into namespace for', self.name, '\n' )
|
debug( 'moving', intf, 'into namespace for', self.name, '\n' )
|
||||||
moveIntfFn( intf.name, self )
|
moveIntfFn( intf.name, self )
|
||||||
|
|
||||||
|
def delIntf( self, intf ):
|
||||||
|
"""Remove interface from Node's known interfaces
|
||||||
|
Note: to fully delete interface, call intf.delete() instead"""
|
||||||
|
port = self.ports.get( intf )
|
||||||
|
if port is not None:
|
||||||
|
del self.intfs[ port ]
|
||||||
|
del self.ports[ intf ]
|
||||||
|
del self.nameToIntf[ intf.name ]
|
||||||
|
|
||||||
def defaultIntf( self ):
|
def defaultIntf( self ):
|
||||||
"Return interface for lowest port"
|
"Return interface for lowest port"
|
||||||
ports = self.intfs.keys()
|
ports = self.intfs.keys()
|
||||||
|
|||||||
Reference in New Issue
Block a user