108 lines
4.2 KiB
Python
108 lines
4.2 KiB
Python
#!/usr/bin/python
|
|
|
|
"CLI for Mininet Cluster Edition prototype demo"
|
|
|
|
from mininet.cli import CLI
|
|
from mininet.log import output, error
|
|
|
|
# pylint: disable=global-statement
|
|
nx, graphviz_layout, plt = None, None, None # Will be imported on demand
|
|
|
|
|
|
class ClusterCLI( CLI ):
|
|
"CLI with additional commands for Cluster Edition demo"
|
|
|
|
@staticmethod
|
|
def colorsFor( seq ):
|
|
"Return a list of background colors for a sequence"
|
|
colors = [ 'red', 'lightgreen', 'cyan', 'yellow', 'orange',
|
|
'magenta', 'pink', 'grey', 'brown',
|
|
'white' ]
|
|
slen, clen = len( seq ), len( colors )
|
|
reps = max( 1, slen / clen )
|
|
colors = colors * reps
|
|
colors = colors[ 0 : slen ]
|
|
return colors
|
|
|
|
def do_plot( self, _line ):
|
|
"Plot topology colored by node placement"
|
|
# Import networkx if needed
|
|
global nx, plt, graphviz_layout
|
|
if not nx:
|
|
try:
|
|
# pylint: disable=import-error,no-member
|
|
# pylint: disable=import-outside-toplevel
|
|
import networkx
|
|
nx = networkx # satisfy pylint
|
|
from matplotlib import pyplot
|
|
plt = pyplot # satisfy pylint
|
|
import pygraphviz
|
|
assert pygraphviz # silence pyflakes
|
|
# Networkx moved this around
|
|
if hasattr( nx, 'graphviz_layout' ):
|
|
graphviz_layout = nx.graphviz_layout
|
|
else:
|
|
graphviz_layout = nx.drawing.nx_agraph.graphviz_layout
|
|
# pylint: enable=import-error,no-member
|
|
except ImportError:
|
|
error( 'plot requires networkx, matplotlib and pygraphviz - '
|
|
'please install them and try again\n' )
|
|
return
|
|
# Make a networkx Graph
|
|
g = nx.Graph()
|
|
mn = self.mn
|
|
servers = getattr( mn, 'servers', [ 'localhost' ] )
|
|
hosts, switches = mn.hosts, mn.switches
|
|
nodes = hosts + switches
|
|
g.add_nodes_from( nodes )
|
|
links = [ ( link.intf1.node, link.intf2.node )
|
|
for link in self.mn.links ]
|
|
g.add_edges_from( links )
|
|
# Pick some shapes and colors
|
|
# shapes = hlen * [ 's' ] + slen * [ 'o' ]
|
|
color = dict( zip( servers, self.colorsFor( servers ) ) )
|
|
# Plot it!
|
|
pos = graphviz_layout( g )
|
|
opts = { 'ax': None, 'font_weight': 'bold',
|
|
'width': 2, 'edge_color': 'darkblue' }
|
|
hcolors = [ color[ getattr( h, 'server', 'localhost' ) ]
|
|
for h in hosts ]
|
|
scolors = [ color[ getattr( s, 'server', 'localhost' ) ]
|
|
for s in switches ]
|
|
nx.draw_networkx( g, pos=pos, nodelist=hosts, node_size=800,
|
|
label='host', node_color=hcolors, node_shape='s',
|
|
**opts )
|
|
nx.draw_networkx( g, pos=pos, nodelist=switches, node_size=1000,
|
|
node_color=scolors, node_shape='o', **opts )
|
|
# Get rid of axes, add title, and show
|
|
fig = plt.gcf()
|
|
ax = plt.gca()
|
|
ax.get_xaxis().set_visible( False )
|
|
ax.get_yaxis().set_visible( False )
|
|
fig.canvas.set_window_title( 'Mininet')
|
|
plt.title( 'Node Placement', fontweight='bold' )
|
|
plt.show()
|
|
|
|
def do_status( self, _line ):
|
|
"Report on node shell status"
|
|
nodes = self.mn.hosts + self.mn.switches
|
|
for node in nodes:
|
|
node.shell.poll()
|
|
exited = [ node for node in nodes
|
|
if node.shell.returncode is not None ]
|
|
if exited:
|
|
for node in exited:
|
|
output( '%s has exited with code %d\n'
|
|
% ( node, node.shell.returncode ) )
|
|
else:
|
|
output( 'All nodes are still running.\n' )
|
|
|
|
def do_placement( self, _line ):
|
|
"Describe node placement"
|
|
mn = self.mn
|
|
nodes = mn.hosts + mn.switches + mn.controllers
|
|
for server in mn.servers:
|
|
names = [ n.name for n in nodes if hasattr( n, 'server' )
|
|
and n.server == server ]
|
|
output( '%s: %s\n' % ( server, ' '.join( names ) ) )
|