ndn: Add GUI
Change-Id: I7336bbb04121166d064b76cbad9f760c3dd16c2d
diff --git a/bin/minindnedit b/bin/minindnedit
index c0ff708..70e0dce 100755
--- a/bin/minindnedit
+++ b/bin/minindnedit
@@ -1,7 +1,7 @@
#!/usr/bin/python
"""
-MiniCCNxEdit: a simple network editor for MiniCCNx
+MiniNDNEdit: a simple network editor for MiniNDN
Based on miniedit by:
Bob Lantz, April 2010
@@ -18,7 +18,7 @@
from Tkinter import *
from ttk import Notebook
from tkMessageBox import showinfo, showerror, showwarning
-from subprocess import call
+from subprocess import call, Popen
import tkFont
import csv
import tkFileDialog
@@ -28,6 +28,7 @@
from distutils.version import StrictVersion
import os
import sys
+import threading
from functools import partial
import pdb
@@ -52,11 +53,14 @@
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.topolib import TreeTopo
-print 'MiniCCNxEdit running...' #+VERSION
+print 'MiniNDNEdit running...' #+VERSION
MININET_VERSION = re.sub(r'[^\d\.]', '', VERSION)
if StrictVersion(MININET_VERSION) > StrictVersion('2.0'):
from mininet.node import IVSSwitch
+
+from ndn.gui import NfdFrame, NlsrFrame
+
TOPODEF = 'none'
TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
'linear': LinearTopo,
@@ -72,6 +76,16 @@
'rt': custom( CPULimitedHost, sched='rt' ),
'cfs': custom( CPULimitedHost, sched='cfs' ) }
+def runMiniNdn(window, template):
+ # Hide window
+ window.withdraw()
+
+ proc = Popen("sudo minindn %s" % template, shell=True)
+ proc.wait()
+
+ # Restore window
+ window.deiconify()
+
class LegacyRouter( Node ):
def __init__( self, name, inNamespace=True, **params ):
@@ -135,8 +149,17 @@
n = Notebook(self.rootFrame)
self.propFrame = Frame(n)
self.fibFrame = Frame(n)
+
+ # NDN
+ self.nfdFrame = NfdFrame(n)
+ self.nlsrFrame = NlsrFrame(n)
+
n.add(self.propFrame, text='Properties')
n.add(self.fibFrame, text='FIB Entries')
+
+ n.add(self.nfdFrame, text=self.nfdFrame.frameLabel)
+ n.add(self.nlsrFrame, text=self.nlsrFrame.frameLabel)
+
n.pack()
### TAB 1
@@ -221,7 +244,10 @@
'mem': self.memEntry.get(),
'hostname':self.hostnameEntry.get(),
'startCommand':self.startEntry.get(),
- 'fibEntries':fibEntries}
+ 'fibEntries':fibEntries,
+ 'nlsr': self.nlsrFrame.getValues()
+ }
+
self.result = results
class VerticalScrolledTable(LabelFrame):
@@ -391,15 +417,15 @@
class MiniEdit( Frame ):
- "A simple network editor for MiniCCNx."
+ "A simple network editor for MiniNDN."
- def __init__( self, parent=None, cheight=600, cwidth=1000, template_file='miniccnx.conf' ):
+ def __init__( self, parent=None, cheight=600, cwidth=1000, template_file='minindn.conf' ):
self.template_file = template_file
Frame.__init__( self, parent )
self.action = None
- self.appName = 'MiniccnxEdit'
+ self.appName = 'MiniNDNEdit'
self.fixedFont = tkFont.Font ( family="DejaVu Sans Mono", size="14" )
# Style
@@ -425,8 +451,8 @@
self.images = miniEditImages()
self.buttons = {}
self.active = None
- self.tools = ( 'Select', 'Host', 'LegacyRouter', 'NetLink' )
- self.customColors = { 'LegacyRouter': 'darkGreen', 'Host': 'blue' }
+ self.tools = ( 'Select', 'Host', 'NetLink' )
+ #self.customColors = { 'LegacyRouter': 'darkGreen', 'Host': 'blue' }
self.toolbar = self.createToolbar()
# Layout
@@ -508,6 +534,7 @@
fileMenu.add_command( label="Open", font=font, command=self.loadTopology )
fileMenu.add_command( label="Save", font=font, command=self.saveTopology )
fileMenu.add_command( label="Generate", font=font, command=self.doGenerate )
+ fileMenu.add_command( label="Run", font=font, command=self.doRun )
fileMenu.add_separator()
fileMenu.add_command( label='Quit', command=self.quit, font=font )
@@ -519,7 +546,7 @@
# Application menu
appMenu = Menu( mbar, tearoff=False )
mbar.add_cascade( label=self.appName, font=font, menu=appMenu )
- appMenu.add_command( label='About Mini-CCNx', command=self.about,
+ appMenu.add_command( label='About Mini-NDN', command=self.about,
font=font)
#appMenu.add_separator()
#appMenu.add_command( label='Quit', command=self.quit, font=font )
@@ -618,7 +645,7 @@
# Spacer
Label( toolbar, text='' ).pack()
- # abaixo copiado Mini-CCNx para criar botao Generate
+ # abaixo copiado Mini-NDN para criar botao Generate
for cmd, color in [ ( 'Generate', 'darkGreen' ) ]:
doCmd = getattr( self, 'do' + cmd )
@@ -628,7 +655,7 @@
return toolbar
- def doGenerate( self ): #COPIA Mini-CCNx - GERA TEMPLATE
+ def doGenerate( self ): #COPIA Mini-NDN - GERA TEMPLATE
"Generate template."
self.activate( 'Select' )
for tool in self.tools:
@@ -645,6 +672,19 @@
b=Button(toplevel, text="Ok", width=5, command=toplevel.destroy)
b.pack(side='bottom', padx=0,pady=0)
+ def doRun( self ):
+ "Use current configuration to generate a template and run the topology"
+
+ # Generate temporary template file
+ old_template_file = self.template_file
+ self.template_file = "/tmp/tmp.conf"
+ self.doGenerate()
+
+ thread = threading.Thread(target=runMiniNdn, args=(self.master, self.template_file))
+ thread.start()
+
+ self.template_file = old_template_file
+
def parseFibEntries ( self, fibEntries ):
"Parse FIB Entries for write"
result=''
@@ -655,17 +695,17 @@
return result
- def buildTemplate( self ): #COPIA Mini-CCNx para criar Template
+ def buildTemplate( self ): #COPIA Mini-NDN para criar Template
"Generate template"
template = open(self.template_file, 'w')
# hosts
- template.write('[hosts]\n')
+ template.write('[nodes]\n')
for widget in self.widgetToItem:
name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
- #print self.hostOpts[name]
+ print self.hostOpts[name]
if 'Host' in tags:
hOpts=self.hostOpts[name]
template.write(name + ': ')
@@ -684,10 +724,22 @@
if 'fibEntries' in hOpts:
customFib = self.parseFibEntries(hOpts['fibEntries'])
template.write(customFib)
+ if 'nlsr' in hOpts:
+ values = hOpts['nlsr']
+
+ template.write('hyperbolic-state=' + values['hyperbolic-state'] + ' ')
+ template.write('radius=' + values['radius'] + ' ')
+ template.write('angle=' + values['angle'] + ' ')
+ template.write('network=' + values['network'] + ' ')
+ template.write('router=' + values['router'] + ' ')
+ template.write('site=' + values['site'] + ' ')
+ template.write('log-level=' + values['log-level'] + ' ')
+ template.write('max-faces-per-prefix=' + values['max-faces-per-prefix'] + ' ')
+
template.write('\n')
# switches/routers
- template.write('[routers]\n')
+ #template.write('[routers]\n')
for router in self.routerOpts.values():
@@ -735,7 +787,7 @@
if 'loss' in linkopts:
template.write('loss=' + repr(linkopts['loss']) + ' ' )
if 'delay' in linkopts:
- template.write('delay=' + str(linkopts['delay']))
+ template.write('delay=' + str(linkopts['delay'])+ 'ms' )
template.write('\n')
@@ -778,7 +830,7 @@
c = self.canvas
myFormats = [
- ('Miniccnx Topology','*.mnccnx'),
+ ('MiniNDN Topology','*.mnndn'),
('All Files','*'),
]
f = tkFileDialog.askopenfile(filetypes=myFormats, mode='rb')
@@ -788,7 +840,7 @@
loadedTopology = self.convertJsonUnicode(json.load(f))
# Load hosts
- hosts = loadedTopology['hosts']
+ hosts = loadedTopology['nodes']
for host in hosts:
nodeNum = host['number']
hostname = 'h'+nodeNum
@@ -800,6 +852,7 @@
host['opts']['nodeNum'] = int(nodeNum)
x = host['x']
y = host['y']
+
self.addNode('Host', nodeNum, float(x), float(y), name=hostname)
# Fix JSON converting tuple to list when saving
@@ -875,7 +928,7 @@
def saveTopology( self ):
"Save command."
myFormats = [
- ('Miniccnx Topology','*.mnccnx'),
+ ('MiniNDN Topology','*.mnndn'),
('All Files','*'),
]
@@ -1004,11 +1057,10 @@
def clearPopups(self):
print 'Entrou funcao clear_popups'
-
- if isHostPopup == True:
- print 'Hostpopup = true'
- self.hostPopup.unpost
- isHostPopup = False
+ if isHostPopup == True:
+ print 'Hostpopup = true'
+ self.hostPopup.unpost
+ isHostPopup = False
#if isRouterPopup == True
#if isLinkPopup == True
@@ -1211,9 +1263,9 @@
# For now, don't allow hosts to be directly linked
stags = self.canvas.gettags( self.widgetToItem[ source ] )
dtags = self.canvas.gettags( target )
- if (('Host' in stags and 'Host' in dtags)):
- self.releaseNetLink( event )
- return
+ #if (('Host' in stags and 'Host' in dtags)):
+ #self.releaseNetLink( event )
+ #return
# Set link type
linkType='data'
@@ -1237,12 +1289,14 @@
bg = 'white'
about = Toplevel( bg='white' )
about.title( 'About' )
- info = self.appName + ': a simple network editor for MiniCCNx - based on Miniedit'
+ info = self.appName + ': a simple network editor for MiniNDN - based on Miniedit'
warning = 'Development version - not entirely functional!'
#version = 'MiniEdit '+MINIEDIT_VERSION
- author = 'Carlos Cabral, Jan 2013'
- author2 = 'Caio Elias, Nov 2014'
- author3 = 'Originally by: Bob Lantz <rlantz@cs>, April 2010'
+ author = 'Vince Lehman, Jan 2015'
+ author2 = 'Ashlesh Gawande, Jan 2015'
+ author3 = 'Carlos Cabral, Jan 2013'
+ author4 = 'Caio Elias, Nov 2014'
+ author5 = 'Originally by: Bob Lantz <rlantz@cs>, April 2010'
enhancements = 'Enhancements by: Gregory Gee, Since July 2013'
www = 'http://gregorygee.wordpress.com/category/miniedit/'
line1 = Label( about, text=info, font='Helvetica 10 bold', bg=bg )
@@ -1250,11 +1304,14 @@
line3 = Label( about, text=author, font='Helvetica 9', bg=bg )
line4 = Label( about, text=author2, font='Helvetica 9', bg=bg )
line5 = Label( about, text=author3, font='Helvetica 9', bg=bg )
- line6 = Label( about, text=enhancements, font='Helvetica 9', bg=bg )
- line7 = Entry( about, font='Helvetica 9', bg=bg, width=len(www), justify=CENTER )
+ line6 = Label( about, text=author4, font='Helvetica 9', bg=bg )
+ line7 = Label( about, text=author5, font='Helvetica 9', bg=bg )
+ line8 = Label( about, text=enhancements, font='Helvetica 9', bg=bg )
+ line9 = Entry( about, font='Helvetica 9', bg=bg, width=len(www), justify=CENTER )
- line7.insert(0, www)
- line7.configure(state='readonly')
+
+ line9.insert(0, www)
+ line9.configure(state='readonly')
line1.pack( padx=20, pady=10 )
line2.pack(pady=10 )
line3.pack(pady=10 )
@@ -1262,6 +1319,8 @@
line5.pack(pady=10 )
line6.pack(pady=10 )
line7.pack(pady=10 )
+ line8.pack(pady=10 )
+ line9.pack(pady=10 )
hide = ( lambda about=about: about.withdraw() )
self.aboutBox = about
# Hide on close rather than destroying window
@@ -1304,6 +1363,9 @@
newHostOpts['cache'] = hostBox.result['cache']
if len(hostBox.result['fibEntries']) > 0:
newHostOpts['fibEntries'] = hostBox.result['fibEntries']
+
+ newHostOpts['nlsr'] = hostBox.nlsrFrame.getValues()
+
self.hostOpts[name] = newHostOpts
print 'New host details for ' + name + ' = ' + str(newHostOpts)
@@ -1456,12 +1518,12 @@
else:
raise Exception( 'Custom file name not found' )
- desc = ( "The %prog utility creates Miniccnx network from the\n"
+ desc = ( "The %prog utility creates Minindn network from the\n"
"command line. It can create parametrized topologies,\n"
- "invoke the Miniccnx CLI, and run tests." )
+ "invoke the Minindn CLI, and run tests." )
usage = ( '%prog [options] [template_file]\n'
- '\nIf no template_file is given, generated template will be written to the file miniccnx.conf in the current directory.\n'
+ '\nIf no template_file is given, generated template will be written to the file minindn.conf in the current directory.\n'
'Type %prog -h for details)' )
opts = OptionParser( description=desc, usage=usage )