Add pmonitor() to make it easy to monitor popen objects.

This commit is contained in:
Bob Lantz
2012-04-13 17:42:37 -07:00
parent 237a3c54cf
commit 50cebe6753
2 changed files with 68 additions and 16 deletions
+21 -15
View File
@@ -1,30 +1,36 @@
#!/usr/bin/python
"""
This example tests the Host.popen()/pexec() interface
This example monitors a number of hosts using host.popen() and
pmonitor()
"""
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.topo import SingleSwitchTopo
from mininet.log import setLogLevel
# from mininet.cli import CLI
from mininet.util import custom
from mininet.util import custom, pmonitor
def testpopen(sched='cfs'):
"Test popen() interface"
host = custom( CPULimitedHost, cpu=.2, sched=sched )
net = Mininet( SingleSwitchTopo( 2 ), host=host )
def monitorhosts( hosts=5, sched='cfs' ):
"Start a bunch of pings and monitor them using popen"
mytopo = SingleSwitchTopo( hosts )
cpu = .5 / hosts
myhost = custom( CPULimitedHost, cpu=cpu, sched=sched )
net = Mininet( topo=mytopo, host=myhost )
net.start()
h1 = net.get( 'h1' )
# CLI(net)
out, err, code = h1.pexec( 'ifconfig' )
print 'stdout:', out.strip()
print 'stderr:', err.strip()
print 'exit code:', code
# Start a bunch of pings
popens = {}
last = net.hosts[ -1 ]
for host in net.hosts:
popens[ host ] = host.popen( "ping -c5 %s" % last.IP() )
last = host
# Monitor them and print output
for host, line in pmonitor( popens ):
if host:
print "<%s>: %s" % ( host.name, line.strip() )
# Done
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
testpopen('rt')
testpopen('cfs')
monitorhosts( hosts=5 )
+47 -1
View File
@@ -1,11 +1,14 @@
"Utility functions for Mininet."
from mininet.log import output, info, error
from time import sleep
from resource import setrlimit, RLIMIT_NPROC, RLIMIT_NOFILE
from select import poll, POLLIN
from subprocess import call, check_call, Popen, PIPE, STDOUT
from mininet.log import output, info, error
import re
from fcntl import fcntl, F_GETFL, F_SETFL
from os import O_NONBLOCK
# Command execution support
@@ -300,6 +303,49 @@ def makeNumeric( s ):
else:
return s
# Popen support
def pmonitor(popens, timeoutms=500, readline=True,
readmax=1024 ):
"""Monitor dict of hosts to popen objects
a line at a time
timeoutms: timeout for poll()
readline: return single line of output
yields: host, line/output (if any)
terminates: when all EOFs received"""
poller = poll()
fdToHost = {}
for host, popen in popens.iteritems():
fd = popen.stdout.fileno()
fdToHost[ fd ] = host
poller.register( fd, POLLIN )
if not readline:
# Use non-blocking reads
flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
while True:
fds = poller.poll( timeoutms )
if fds:
for fd, _event in fds:
host = fdToHost[ fd ]
popen = popens[ host ]
if readline:
# Attempt to read a line of output
# This blocks until we receive a newline!
line = popen.stdout.readline()
else:
line = popen.stdout.read( readmax )
yield host, line
# Check for EOF
if not line:
popen.poll()
if popen.returncode is not None:
poller.unregister( fd )
del popens[ host ]
if not popens:
return
else:
yield None, ''
# Other stuff we use