Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
mininet
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Olaf Bergmann
mininet
Commits
ab1fb093
Commit
ab1fb093
authored
14 years ago
by
Bob Lantz
Browse files
Options
Downloads
Patches
Plain Diff
Added output hook and graph.
parent
2a554ae3
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
examples/consoles.py
+207
-16
207 additions, 16 deletions
examples/consoles.py
with
207 additions
and
16 deletions
examples/consoles.py
+
207
−
16
View file @
ab1fb093
...
...
@@ -5,12 +5,30 @@
This demo shows how to monitor a set of nodes by using
Node
'
s monitor() and Tkinter
'
s createfilehandler().
We monitor nodes in a couple of ways:
- First, each individual node is monitored, and its output is added
to its console window
- Second, each time a console window gets iperf output, it is parsed
and accumulated. Once we have output for all consoles, a bar is
added to the bandwidth graph.
The consoles also support limited interaction:
- Pressing
"
return
"
in a console will send a command to it
- Pressing the console
'
s title button will open up an xterm
Bob Lantz, April 2010
"""
import
re
from
Tkinter
import
*
from
mininet.log
import
setLogLevel
from
mininet.log
import
setLogLevel
,
info
from
mininet.topolib
import
TreeNet
from
mininet.term
import
makeTerms
,
cleanUpScreens
from
mininet.util
import
quietRun
...
...
@@ -45,7 +63,9 @@ def __init__( self, parent, net, node, height=10, width=32, title='Node' ):
self
.
text
=
self
.
makeWidgets
(
)
self
.
bindEvents
()
self
.
sendCmd
(
'
export TERM=dumb
'
)
self
.
outputHook
=
None
def
makeWidgets
(
self
):
"
Make a label, a text area, and a scroll bar.
"
...
...
@@ -85,7 +105,9 @@ def append( self, text ):
self
.
text
.
insert
(
'
end
'
,
text
)
self
.
text
.
mark_set
(
'
insert
'
,
'
end
'
)
self
.
text
.
see
(
'
insert
'
)
if
self
.
outputHook
:
self
.
outputHook
(
self
,
text
)
def
handleKey
(
self
,
event
):
"
If it
'
s an interactive command, send it to the node.
"
char
=
event
.
char
...
...
@@ -122,7 +144,11 @@ def handleReadable( self, file=None, mask=None, timeoutms=None ):
if
not
self
.
node
.
waiting
:
# Print prompt
self
.
append
(
self
.
prompt
)
def
waiting
(
self
):
"
Are we waiting for output?
"
return
self
.
node
.
waiting
def
waitOutput
(
self
):
"
Wait for any remaining output.
"
while
self
.
node
.
waiting
:
...
...
@@ -133,7 +159,124 @@ def waitOutput( self ):
def
clear
(
self
):
"
Clear all of our text.
"
self
.
text
.
delete
(
'
1.0
'
,
'
end
'
)
class
Graph
(
Frame
):
"
Graph that we can add bars to over time.
"
def
__init__
(
self
,
parent
=
None
,
bg
=
'
white
'
,
gheight
=
200
,
gwidth
=
500
,
barwidth
=
10
,
ymax
=
3.5
,):
Frame
.
__init__
(
self
,
parent
)
self
.
bg
=
bg
self
.
gheight
=
gheight
self
.
gwidth
=
gwidth
self
.
barwidth
=
barwidth
self
.
ymax
=
float
(
ymax
)
self
.
xpos
=
0
# Create everything
self
.
title
=
self
.
graph
=
None
self
.
createWidgets
()
self
.
updateScrollRegions
()
self
.
yview
(
'
moveto
'
,
'
1.0
'
)
def
scale
(
self
):
"
Create a and return a new canvas with scale markers.
"
height
=
float
(
self
.
gheight
)
width
=
25
ymax
=
self
.
ymax
scale
=
Canvas
(
self
,
width
=
width
,
height
=
height
,
background
=
self
.
bg
)
fill
=
'
red
'
# Draw scale line
scale
.
create_line
(
width
-
1
,
height
,
width
-
1
,
0
,
fill
=
fill
)
# Draw ticks and numbers
for
y
in
range
(
0
,
int
(
ymax
+
1
)
):
ypos
=
height
*
(
1
-
float
(
y
)
/
ymax
)
scale
.
create_line
(
width
,
ypos
,
width
-
10
,
ypos
,
fill
=
fill
)
scale
.
create_text
(
10
,
ypos
,
text
=
str
(
y
),
fill
=
fill
)
return
scale
def
updateScrollRegions
(
self
):
"
Update graph and scale scroll regions.
"
ofs
=
20
height
=
self
.
gheight
+
ofs
self
.
graph
.
configure
(
scrollregion
=
(
0
,
-
ofs
,
self
.
xpos
*
self
.
barwidth
,
height
)
)
self
.
scale
.
configure
(
scrollregion
=
(
0
,
-
ofs
,
0
,
height
)
)
def
yview
(
self
,
*
args
):
"
Scroll both scale and graph.
"
self
.
graph
.
yview
(
*
args
)
self
.
scale
.
yview
(
*
args
)
def
createWidgets
(
self
):
"
Create initial widget set.
"
# Objects
title
=
Label
(
self
,
text
=
"
Bandwidth (Gb/s)
"
,
bg
=
self
.
bg
)
width
=
self
.
gwidth
height
=
self
.
gheight
scale
=
self
.
scale
()
graph
=
Canvas
(
self
,
width
=
width
,
height
=
height
,
background
=
self
.
bg
)
xbar
=
Scrollbar
(
self
,
orient
=
'
horizontal
'
,
command
=
graph
.
xview
)
ybar
=
Scrollbar
(
self
,
orient
=
'
vertical
'
,
command
=
self
.
yview
)
graph
.
configure
(
xscrollcommand
=
xbar
.
set
,
yscrollcommand
=
ybar
.
set
,
scrollregion
=
(
0
,
0
,
width
,
height
)
)
scale
.
configure
(
yscrollcommand
=
ybar
.
set
)
# Layout
title
.
grid
(
row
=
0
,
columnspan
=
3
,
sticky
=
N
+
E
+
W
)
scale
.
grid
(
row
=
1
,
column
=
0
,
sticky
=
N
+
S
+
E
+
W
)
graph
.
grid
(
row
=
1
,
column
=
1
,
sticky
=
N
+
S
+
E
+
W
)
ybar
.
grid
(
row
=
1
,
column
=
2
,
sticky
=
N
+
S
)
xbar
.
grid
(
row
=
2
,
column
=
0
,
columnspan
=
2
,
sticky
=
E
+
W
)
self
.
rowconfigure
(
1
,
weight
=
1
)
self
.
columnconfigure
(
1
,
weight
=
1
)
# Save for future reference
self
.
title
=
title
self
.
scale
=
scale
self
.
graph
=
graph
return
graph
def
addBar
(
self
,
yval
):
"
Add a new bar to our graph.
"
percent
=
yval
/
self
.
ymax
height
=
percent
*
self
.
gheight
c
=
self
.
graph
x0
=
self
.
xpos
*
self
.
barwidth
x1
=
x0
+
self
.
barwidth
y0
=
self
.
gheight
y1
=
(
1
-
percent
)
*
self
.
gheight
c
.
create_rectangle
(
x0
,
y0
,
x1
,
y1
,
fill
=
'
green
'
)
self
.
xpos
+=
1
self
.
updateScrollRegions
()
self
.
graph
.
xview
(
'
moveto
'
,
'
1.0
'
)
def
clear
(
self
):
"
Clear graph contents.
"
self
.
graph
.
delete
(
'
all
'
)
self
.
xpos
=
0
def
test
(
self
):
"
Add a bar for testing purposes.
"
ms
=
1000
if
self
.
xpos
<
10
:
self
.
addBar
(
self
.
xpos
/
10
*
self
.
ymax
)
self
.
after
(
ms
,
self
.
test
)
def
setTitle
(
self
,
text
):
"
Set graph title
"
self
.
title
.
configure
(
text
=
text
,
font
=
'
Helvetica 9 bold
'
)
class
ConsoleApp
(
Frame
):
menuStyle
=
{
'
font
'
:
'
Geneva 7 bold
'
}
...
...
@@ -159,11 +302,39 @@ def __init__( self, net, parent=None, width=4 ):
self
.
selected
=
None
self
.
select
(
'
hosts
'
)
self
.
cframe
.
pack
(
expand
=
True
,
fill
=
'
both
'
)
self
.
pack
(
expand
=
True
,
fill
=
'
both
'
)
cleanUpScreens
()
# Close window gracefully
Wm
.
wm_protocol
(
self
.
top
,
name
=
'
WM_DELETE_WINDOW
'
,
func
=
self
.
quit
)
# Initialize graph
graph
=
Graph
(
cframe
)
self
.
consoles
[
'
graph
'
]
=
Object
(
frame
=
graph
,
consoles
=
[
graph
]
)
self
.
graph
=
graph
self
.
graphVisible
=
False
self
.
updates
=
0
self
.
hostCount
=
len
(
self
.
consoles
[
'
hosts
'
].
consoles
)
self
.
bw
=
0
self
.
pack
(
expand
=
True
,
fill
=
'
both
'
)
def
updateGraph
(
self
,
console
,
output
):
"
Update our graph.
"
m
=
re
.
search
(
r
'
(\d+) Mbits/sec
'
,
output
)
if
not
m
:
return
self
.
updates
+=
1
self
.
bw
+=
.
001
*
float
(
m
.
group
(
1
)
)
if
self
.
updates
>=
self
.
hostCount
:
self
.
graph
.
addBar
(
self
.
bw
)
self
.
bw
=
0
self
.
updates
=
0
def
setOutputHook
(
self
,
fn
=
None
,
consoles
=
None
):
if
consoles
is
None
:
consoles
=
self
.
consoles
[
'
hosts
'
].
consoles
for
console
in
consoles
:
console
.
outputHook
=
fn
def
createConsoles
(
self
,
parent
,
nodes
,
width
,
title
):
"
Create a grid of consoles in a frame.
"
f
=
Frame
(
parent
)
...
...
@@ -194,7 +365,8 @@ def createMenuBar( self ):
buttons
=
[
(
'
Hosts
'
,
lambda
:
self
.
select
(
'
hosts
'
)
),
(
'
Switches
'
,
lambda
:
self
.
select
(
'
switches
'
)
),
(
'
Controllers
'
,
lambda
:
self
.
select
(
'
controllers
'
)
),
(
'
Controllers
'
,
lambda
:
self
.
select
(
'
controllers
'
)
),
(
'
Graph
'
,
lambda
:
self
.
select
(
'
graph
'
)
),
(
'
Ping
'
,
self
.
ping
),
(
'
Iperf
'
,
self
.
iperf
),
(
'
Interrupt
'
,
self
.
stop
),
...
...
@@ -208,13 +380,24 @@ def createMenuBar( self ):
return
f
def
clear
(
self
):
"
Clear
all consoles
.
"
"
Clear
selection
.
"
for
console
in
self
.
selected
.
consoles
:
console
.
clear
()
def
waiting
(
self
,
consoles
=
None
):
"
Are any of our hosts waiting for output?
"
if
consoles
is
None
:
consoles
=
self
.
consoles
[
'
hosts
'
].
consoles
for
console
in
consoles
:
if
console
.
waiting
():
return
True
return
False
def
ping
(
self
):
"
Tell each host to ping the next one.
"
consoles
=
self
.
consoles
[
'
hosts
'
].
consoles
if
self
.
waiting
(
consoles
):
return
count
=
len
(
consoles
)
i
=
0
for
console
in
consoles
:
...
...
@@ -225,7 +408,10 @@ def ping( self ):
def
iperf
(
self
):
"
Tell each host to iperf to the next one.
"
consoles
=
self
.
consoles
[
'
hosts
'
].
consoles
if
self
.
waiting
(
consoles
):
return
count
=
len
(
consoles
)
self
.
setOutputHook
(
self
.
updateGraph
)
for
console
in
consoles
:
console
.
node
.
cmd
(
'
iperf -sD
'
)
i
=
0
...
...
@@ -242,27 +428,32 @@ def stop( self, wait=True ):
if
wait
:
for
console
in
consoles
:
console
.
waitOutput
()
self
.
setOutputHook
(
None
)
# Shut down any iperfs that might still be running
quietRun
(
'
killall -9 iperf
'
)
def
quit
(
self
):
"
Stope everything and quit.
"
print
"
Quit
"
self
.
stop
(
wait
=
False
)
Frame
.
quit
(
self
)
def
reallyQuit
(
self
):
print
"
ReallyQuit
"
# Make it easier to construct and assign objects
def
assign
(
obj
,
**
kwargs
):
"
Set a bunch of fields in an object.
"
for
name
,
value
in
kwargs
.
items
():
setattr
(
obj
,
name
,
value
)
class
Object
(
object
):
"
Generic object you can stuff junk into.
"
def
__init__
(
self
,
**
kwargs
):
for
name
,
value
in
kwargs
.
items
():
setattr
(
self
,
name
,
value
)
assign
(
self
,
**
kwargs
)
if
__name__
==
'
__main__
'
:
setLogLevel
(
'
info
'
)
net
=
TreeNet
(
depth
=
2
,
fanout
=
2
)
net
=
TreeNet
(
depth
=
2
,
fanout
=
4
)
net
.
start
()
app
=
ConsoleApp
(
net
,
width
=
4
)
app
.
mainloop
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment