Update to 2.1.0.8
This commit is contained in:
+372
-42
@@ -10,9 +10,10 @@ Bob Lantz, April 2010
|
||||
Gregory Gee, July 2013
|
||||
|
||||
Controller icon from http://semlabs.co.uk/
|
||||
OpenFlow icon from https://www.opennetworking.org/
|
||||
"""
|
||||
|
||||
MINIEDIT_VERSION = '2.1.0.7.1'
|
||||
MINIEDIT_VERSION = '2.1.0.8'
|
||||
|
||||
from optparse import OptionParser
|
||||
from Tkinter import *
|
||||
@@ -39,9 +40,9 @@ from mininet.util import ipStr, netParse, ipAdd, quietRun
|
||||
from mininet.util import buildTopo
|
||||
from mininet.term import makeTerm, cleanUpScreens
|
||||
from mininet.node import Controller, RemoteController, NOX, OVSController
|
||||
from mininet.node import CPULimitedHost, Host
|
||||
from mininet.node import OVSKernelSwitch, OVSSwitch
|
||||
from mininet.link import TCLink, Intf
|
||||
from mininet.node import CPULimitedHost, Host, Node
|
||||
from mininet.node import OVSKernelSwitch, OVSSwitch, UserSwitch
|
||||
from mininet.link import TCLink, Intf, Link
|
||||
from mininet.cli import CLI
|
||||
from mininet.moduledeps import moduleDeps, pathCheck
|
||||
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
|
||||
@@ -71,10 +72,49 @@ class InbandController( RemoteController ):
|
||||
"Overridden to do nothing."
|
||||
return
|
||||
|
||||
class CustomUserSwitch(UserSwitch):
|
||||
def __init__( self, name, dpopts='--no-slicing', **kwargs ):
|
||||
UserSwitch.__init__( self, name, **kwargs )
|
||||
self.switchIP = None
|
||||
|
||||
def getSwitchIP(self):
|
||||
return self.switchIP
|
||||
|
||||
def setSwitchIP(self, ip):
|
||||
self.switchIP = ip
|
||||
|
||||
def start( self, controllers ):
|
||||
# Call superclass constructor
|
||||
UserSwitch.start( self, controllers )
|
||||
# Set Switch IP address
|
||||
if (self.switchIP is not None):
|
||||
if not self.inNamespace:
|
||||
self.cmd( 'ifconfig', self, self.switchIP )
|
||||
else:
|
||||
self.cmd( 'ifconfig lo', self.switchIP )
|
||||
|
||||
class LegacyRouter( Node ):
|
||||
|
||||
def __init__( self, name, inNamespace=True, **params ):
|
||||
Node.__init__( self, name, inNamespace, **params )
|
||||
|
||||
def config( self, **_params ):
|
||||
if self.intfs:
|
||||
self.setParam( _params, 'setIP', ip='0.0.0.0' )
|
||||
r = Node.config( self, **_params )
|
||||
self.cmd('sysctl -w net.ipv4.ip_forward=1')
|
||||
return r
|
||||
|
||||
class LegacySwitch(OVSSwitch):
|
||||
|
||||
def __init__( self, name, **params ):
|
||||
OVSSwitch.__init__( self, name, failMode='standalone', **params )
|
||||
self.switchIP = None
|
||||
|
||||
class customOvs(OVSSwitch):
|
||||
|
||||
def __init__( self, name, failMode='secure', datapath='kernel', **params ):
|
||||
OVSSwitch.__init__( self, name, **params )
|
||||
OVSSwitch.__init__( self, name, failMode=failMode, datapath=datapath, **params )
|
||||
self.switchIP = None
|
||||
|
||||
def getSwitchIP(self):
|
||||
@@ -160,11 +200,15 @@ class PrefsDialog(tkSimpleDialog.Dialog):
|
||||
# Selection of switch type
|
||||
Label(self.leftfieldFrame, text="Default Switch:").grid(row=3, sticky=E)
|
||||
self.switchType = StringVar(self.leftfieldFrame)
|
||||
self.switchTypeMenu = OptionMenu(self.leftfieldFrame, self.switchType, "Open vSwitch", "Indigo Virtual Switch")
|
||||
self.switchTypeMenu = OptionMenu(self.leftfieldFrame, self.switchType, "Open vSwitch", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace")
|
||||
self.switchTypeMenu.grid(row=3, column=1, sticky=W)
|
||||
switchTypePref = self.prefValues['switchType']
|
||||
if switchTypePref == 'ivs':
|
||||
self.switchType.set("Indigo Virtual Switch")
|
||||
elif switchTypePref == 'userns':
|
||||
self.switchType.set("Userspace Switch inNamespace")
|
||||
elif switchTypePref == 'user':
|
||||
self.switchType.set("Userspace Switch")
|
||||
else:
|
||||
self.switchType.set("Open vSwitch")
|
||||
|
||||
@@ -299,6 +343,10 @@ class PrefsDialog(tkSimpleDialog.Dialog):
|
||||
self.ovsOk = False
|
||||
showerror(title="Error",
|
||||
message='MiniNet version 2.1+ required. You have '+VERSION+'.')
|
||||
elif sw == 'Userspace Switch':
|
||||
self.result['switchType'] = 'user'
|
||||
elif sw == 'Userspace Switch inNamespace':
|
||||
self.result['switchType'] = 'userns'
|
||||
else:
|
||||
self.result['switchType'] = 'ovs'
|
||||
|
||||
@@ -561,12 +609,16 @@ class SwitchDialog(CustomDialog):
|
||||
# Selection of switch type
|
||||
Label(self.fieldFrame, text="Switch Type:").grid(row=rowCount, sticky=E)
|
||||
self.switchType = StringVar(self.fieldFrame)
|
||||
self.switchTypeMenu = OptionMenu(self.fieldFrame, self.switchType, "Default", "Open vSwitch", "Indigo Virtual Switch")
|
||||
self.switchTypeMenu = OptionMenu(self.fieldFrame, self.switchType, "Default", "Open vSwitch", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace")
|
||||
self.switchTypeMenu.grid(row=rowCount, column=1, sticky=W)
|
||||
if 'switchType' in self.prefValues:
|
||||
switchTypePref = self.prefValues['switchType']
|
||||
if switchTypePref == 'ivs':
|
||||
self.switchType.set("Indigo Virtual Switch")
|
||||
elif switchTypePref == 'userns':
|
||||
self.switchType.set("Userspace Switch inNamespace")
|
||||
elif switchTypePref == 'user':
|
||||
self.switchType.set("Userspace Switch")
|
||||
elif switchTypePref == 'ovs':
|
||||
self.switchType.set("Open vSwitch")
|
||||
else:
|
||||
@@ -650,6 +702,10 @@ class SwitchDialog(CustomDialog):
|
||||
self.ovsOk = False
|
||||
showerror(title="Error",
|
||||
message='MiniNet version 2.1+ required. You have '+VERSION+'.')
|
||||
elif sw == 'Userspace Switch inNamespace':
|
||||
results['switchType'] = 'userns'
|
||||
elif sw == 'Userspace Switch':
|
||||
results['switchType'] = 'user'
|
||||
elif sw == 'Open vSwitch':
|
||||
results['switchType'] = 'ovs'
|
||||
else:
|
||||
@@ -881,11 +937,48 @@ class ControllerDialog(tkSimpleDialog.Dialog):
|
||||
else:
|
||||
self.result['controllerType'] = 'ovsc'
|
||||
|
||||
class ToolTip(object):
|
||||
|
||||
def __init__(self, widget):
|
||||
self.widget = widget
|
||||
self.tipwindow = None
|
||||
self.id = None
|
||||
self.x = self.y = 0
|
||||
|
||||
def showtip(self, text):
|
||||
"Display text in tooltip window"
|
||||
self.text = text
|
||||
if self.tipwindow or not self.text:
|
||||
return
|
||||
x, y, cx, cy = self.widget.bbox("insert")
|
||||
x = x + self.widget.winfo_rootx() + 27
|
||||
y = y + cy + self.widget.winfo_rooty() +27
|
||||
self.tipwindow = tw = Toplevel(self.widget)
|
||||
tw.wm_overrideredirect(1)
|
||||
tw.wm_geometry("+%d+%d" % (x, y))
|
||||
try:
|
||||
# For Mac OS
|
||||
tw.tk.call("::tk::unsupported::MacWindowStyle",
|
||||
"style", tw._w,
|
||||
"help", "noActivates")
|
||||
except TclError:
|
||||
pass
|
||||
label = Label(tw, text=self.text, justify=LEFT,
|
||||
background="#ffffe0", relief=SOLID, borderwidth=1,
|
||||
font=("tahoma", "8", "normal"))
|
||||
label.pack(ipadx=1)
|
||||
|
||||
def hidetip(self):
|
||||
tw = self.tipwindow
|
||||
self.tipwindow = None
|
||||
if tw:
|
||||
tw.destroy()
|
||||
|
||||
class MiniEdit( Frame ):
|
||||
|
||||
"A simple network editor for Mininet."
|
||||
|
||||
def __init__( self, parent=None, cheight=400, cwidth=800 ):
|
||||
def __init__( self, parent=None, cheight=600, cwidth=1000 ):
|
||||
|
||||
self.defaultIpBase='10.0.0.0/8'
|
||||
|
||||
@@ -941,7 +1034,7 @@ class MiniEdit( Frame ):
|
||||
self.images = miniEditImages()
|
||||
self.buttons = {}
|
||||
self.active = None
|
||||
self.tools = ( 'Select', 'Host', 'Switch', 'Link', 'Controller' )
|
||||
self.tools = ( 'Select', 'Host', 'Switch', 'LegacySwitch', 'LegacyRouter', 'NetLink', 'Controller' )
|
||||
self.customColors = { 'Switch': 'darkGreen', 'Host': 'blue' }
|
||||
self.toolbar = self.createToolbar()
|
||||
|
||||
@@ -957,7 +1050,7 @@ class MiniEdit( Frame ):
|
||||
|
||||
# Initialize node data
|
||||
self.nodeBindings = self.createNodeBindings()
|
||||
self.nodePrefixes = { 'Switch': 's', 'Host': 'h' , 'Controller': 'c'}
|
||||
self.nodePrefixes = { 'LegacyRouter': 'r', 'LegacySwitch': 's', 'Switch': 's', 'Host': 'h' , 'Controller': 'c'}
|
||||
self.widgetToItem = {}
|
||||
self.itemToWidget = {}
|
||||
|
||||
@@ -983,13 +1076,18 @@ class MiniEdit( Frame ):
|
||||
self.hostRunPopup.add_separator()
|
||||
self.hostRunPopup.add_command(label='Terminal', font=self.font, command=self.xterm )
|
||||
|
||||
self.legacyRouterRunPopup = Menu(self.top, tearoff=0)
|
||||
self.legacyRouterRunPopup.add_command(label='Router Options', font=self.font)
|
||||
self.legacyRouterRunPopup.add_separator()
|
||||
self.legacyRouterRunPopup.add_command(label='Terminal', font=self.font, command=self.xterm )
|
||||
|
||||
self.switchPopup = Menu(self.top, tearoff=0)
|
||||
self.switchPopup.add_command(label='Swtich Options', font=self.font)
|
||||
self.switchPopup.add_command(label='Switch Options', font=self.font)
|
||||
self.switchPopup.add_separator()
|
||||
self.switchPopup.add_command(label='Properties', font=self.font, command=self.switchDetails )
|
||||
|
||||
self.switchRunPopup = Menu(self.top, tearoff=0)
|
||||
self.switchRunPopup.add_command(label='Swtich Options', font=self.font)
|
||||
self.switchRunPopup.add_command(label='Switch Options', font=self.font)
|
||||
self.switchRunPopup.add_separator()
|
||||
self.switchRunPopup.add_command(label='List bridge details', font=self.font, command=self.listBridge )
|
||||
|
||||
@@ -1132,6 +1230,16 @@ class MiniEdit( Frame ):
|
||||
# Activate dynamic bindings
|
||||
self.active = toolName
|
||||
|
||||
|
||||
def createToolTip(self, widget, text):
|
||||
toolTip = ToolTip(widget)
|
||||
def enter(event):
|
||||
toolTip.showtip(text)
|
||||
def leave(event):
|
||||
toolTip.hidetip()
|
||||
widget.bind('<Enter>', enter)
|
||||
widget.bind('<Leave>', leave)
|
||||
|
||||
def createToolbar( self ):
|
||||
"Create and return our toolbar frame."
|
||||
|
||||
@@ -1143,6 +1251,7 @@ class MiniEdit( Frame ):
|
||||
b = Button( toolbar, text=tool, font=self.smallFont, command=cmd)
|
||||
if tool in self.images:
|
||||
b.config( height=35, image=self.images[ tool ] )
|
||||
self.createToolTip(b, str(tool))
|
||||
# b.config( compound='top' )
|
||||
b.pack( fill='x' )
|
||||
self.buttons[ tool ] = b
|
||||
@@ -1283,10 +1392,19 @@ class MiniEdit( Frame ):
|
||||
switch['opts']['nodeNum'] = int(nodeNum)
|
||||
x = switch['x']
|
||||
y = switch['y']
|
||||
self.addNode('Switch', nodeNum, float(x), float(y), name=hostname)
|
||||
if switch['opts']['switchType'] == "legacyRouter":
|
||||
self.addNode('LegacyRouter', nodeNum, float(x), float(y), name=hostname)
|
||||
icon = self.findWidgetByName(hostname)
|
||||
icon.bind('<Button-3>', self.do_legacyRouterPopup )
|
||||
elif switch['opts']['switchType'] == "legacySwitch":
|
||||
self.addNode('LegacySwitch', nodeNum, float(x), float(y), name=hostname)
|
||||
icon = self.findWidgetByName(hostname)
|
||||
icon.bind('<Button-3>', self.do_legacySwitchPopup )
|
||||
else:
|
||||
self.addNode('Switch', nodeNum, float(x), float(y), name=hostname)
|
||||
icon = self.findWidgetByName(hostname)
|
||||
icon.bind('<Button-3>', self.do_switchPopup )
|
||||
self.switchOpts[hostname] = switch['opts']
|
||||
icon = self.findWidgetByName(hostname)
|
||||
icon.bind('<Button-3>', self.do_switchPopup )
|
||||
|
||||
# create links to controllers
|
||||
if (int(loadedTopology['version']) > 1):
|
||||
@@ -1381,7 +1499,7 @@ class MiniEdit( Frame ):
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
x1, y1 = self.canvas.coords( self.widgetToItem[ widget ] )
|
||||
if 'Switch' in tags:
|
||||
if 'Switch' in tags or 'LegacySwitch' in tags or 'LegacyRouter' in tags:
|
||||
nodeNum = self.switchOpts[name]['nodeNum']
|
||||
nodeToSave = {'number':str(nodeNum),
|
||||
'x':str(x1),
|
||||
@@ -1449,8 +1567,8 @@ class MiniEdit( Frame ):
|
||||
f.write("\n")
|
||||
f.write("from mininet.net import Mininet\n")
|
||||
f.write("from mininet.node import Controller, RemoteController, OVSController\n")
|
||||
f.write("from mininet.node import CPULimitedHost, Host\n")
|
||||
f.write("from mininet.node import OVSKernelSwitch\n")
|
||||
f.write("from mininet.node import CPULimitedHost, Host, Node\n")
|
||||
f.write("from mininet.node import OVSKernelSwitch, UserSwitch\n")
|
||||
if StrictVersion(VERSION) > StrictVersion('2.0'):
|
||||
f.write("from mininet.node import IVSSwitch\n")
|
||||
f.write("from mininet.cli import CLI\n")
|
||||
@@ -1458,6 +1576,7 @@ class MiniEdit( Frame ):
|
||||
f.write("from mininet.link import TCLink, Intf\n")
|
||||
|
||||
inBandCtrl = False
|
||||
hasLegacySwitch = False
|
||||
for widget in self.widgetToItem:
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
@@ -1483,8 +1602,7 @@ class MiniEdit( Frame ):
|
||||
if len(self.appPrefs['dpctl']) > 0:
|
||||
f.write(" listenPort="+self.appPrefs['dpctl']+",\n")
|
||||
f.write(" build=False,\n")
|
||||
f.write(" ipBase='"+self.appPrefs['ipBase']+"',\n")
|
||||
f.write(" link=TCLink)\n")
|
||||
f.write(" ipBase='"+self.appPrefs['ipBase']+"')\n")
|
||||
f.write("\n")
|
||||
f.write(" info( '*** Adding controller\\n' )\n")
|
||||
for widget in self.widgetToItem:
|
||||
@@ -1519,6 +1637,11 @@ class MiniEdit( Frame ):
|
||||
for widget in self.widgetToItem:
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
if 'LegacyRouter' in tags:
|
||||
f.write(" "+name+" = net.addHost('"+name+"', cls=Node, ip='0.0.0.0')\n")
|
||||
f.write(" "+name+".cmd('sysctl -w net.ipv4.ip_forward=1')\n")
|
||||
if 'LegacySwitch' in tags:
|
||||
f.write(" "+name+" = net.addSwitch('"+name+"', cls=OVSKernelSwitch, failMode='standalone')\n")
|
||||
if 'Switch' in tags:
|
||||
opts = self.switchOpts[name]
|
||||
nodeNum = opts['nodeNum']
|
||||
@@ -1526,10 +1649,18 @@ class MiniEdit( Frame ):
|
||||
if opts['switchType'] == 'default':
|
||||
if self.appPrefs['switchType'] == 'ivs':
|
||||
f.write(", cls=IVSSwitch")
|
||||
elif self.appPrefs['switchType'] == 'user':
|
||||
f.write(", cls=UserSwitch")
|
||||
elif self.appPrefs['switchType'] == 'userns':
|
||||
f.write(", cls=UserSwitch, inNamespace=True")
|
||||
else:
|
||||
f.write(", cls=OVSKernelSwitch")
|
||||
elif opts['switchType'] == 'ivs':
|
||||
f.write(", cls=IVSSwitch")
|
||||
elif opts['switchType'] == 'user':
|
||||
f.write(", cls=UserSwitch")
|
||||
elif opts['switchType'] == 'userns':
|
||||
f.write(", cls=UserSwitch, inNamespace=True")
|
||||
else:
|
||||
f.write(", cls=OVSKernelSwitch")
|
||||
if 'dpctl' in opts:
|
||||
@@ -1625,7 +1756,7 @@ class MiniEdit( Frame ):
|
||||
f.write(" "+srcName+dstName+" = "+linkOpts+"\n")
|
||||
f.write(" net.addLink("+srcName+", "+dstName)
|
||||
if optsExist:
|
||||
f.write(", **"+srcName+dstName)
|
||||
f.write(", link=TCLink , **"+srcName+dstName)
|
||||
f.write(")\n")
|
||||
|
||||
f.write("\n")
|
||||
@@ -1641,7 +1772,7 @@ class MiniEdit( Frame ):
|
||||
for widget in self.widgetToItem:
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
if 'Switch' in tags:
|
||||
if 'Switch' in tags or 'LegacySwitch' in tags:
|
||||
opts = self.switchOpts[name]
|
||||
ctrlList = ",".join(opts['controllers'])
|
||||
f.write(" net.get('"+name+"').start(["+ctrlList+"])\n")
|
||||
@@ -1654,9 +1785,31 @@ class MiniEdit( Frame ):
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
if 'Switch' in tags:
|
||||
opts = self.switchOpts[name]
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
|
||||
if opts['switchType'] == 'default':
|
||||
if self.appPrefs['switchType'] == 'user':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
|
||||
elif self.appPrefs['switchType'] == 'userns':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig lo "+opts['switchIP']+"')\n")
|
||||
elif self.appPrefs['switchType'] == 'ovs':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
|
||||
elif opts['switchType'] == 'user':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
|
||||
elif opts['switchType'] == 'userns':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig lo "+opts['switchIP']+"')\n")
|
||||
elif opts['switchType'] == 'ovs':
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP'])>0):
|
||||
f.write(" "+name+".cmd('ifconfig "+name+" "+opts['switchIP']+"')\n")
|
||||
for widget in self.widgetToItem:
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
@@ -1769,6 +1922,21 @@ class MiniEdit( Frame ):
|
||||
self.switchOpts[name]['hostname']=name
|
||||
self.switchOpts[name]['switchType']='default'
|
||||
self.switchOpts[name]['controllers']=[]
|
||||
if 'LegacyRouter' == node:
|
||||
self.switchCount += 1
|
||||
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
||||
self.switchOpts[name] = {}
|
||||
self.switchOpts[name]['nodeNum']=self.switchCount
|
||||
self.switchOpts[name]['hostname']=name
|
||||
self.switchOpts[name]['switchType']='legacyRouter'
|
||||
if 'LegacySwitch' == node:
|
||||
self.switchCount += 1
|
||||
name = self.nodePrefixes[ node ] + str( self.switchCount )
|
||||
self.switchOpts[name] = {}
|
||||
self.switchOpts[name]['nodeNum']=self.switchCount
|
||||
self.switchOpts[name]['hostname']=name
|
||||
self.switchOpts[name]['switchType']='legacySwitch'
|
||||
self.switchOpts[name]['controllers']=[]
|
||||
if 'Host' == node:
|
||||
self.hostCount += 1
|
||||
name = self.nodePrefixes[ node ] + str( self.hostCount )
|
||||
@@ -1794,6 +1962,10 @@ class MiniEdit( Frame ):
|
||||
icon.links = {}
|
||||
if 'Switch' == node:
|
||||
icon.bind('<Button-3>', self.do_switchPopup )
|
||||
if 'LegacyRouter' == node:
|
||||
icon.bind('<Button-3>', self.do_legacyRouterPopup )
|
||||
if 'LegacySwitch' == node:
|
||||
icon.bind('<Button-3>', self.do_legacySwitchPopup )
|
||||
if 'Host' == node:
|
||||
icon.bind('<Button-3>', self.do_hostPopup )
|
||||
if 'Controller' == node:
|
||||
@@ -1807,11 +1979,19 @@ class MiniEdit( Frame ):
|
||||
"Add a new host to our canvas."
|
||||
self.newNode( 'Host', event )
|
||||
|
||||
def clickLegacyRouter( self, event ):
|
||||
"Add a new switch to our canvas."
|
||||
self.newNode( 'LegacyRouter', event )
|
||||
|
||||
def clickLegacySwitch( self, event ):
|
||||
"Add a new switch to our canvas."
|
||||
self.newNode( 'LegacySwitch', event )
|
||||
|
||||
def clickSwitch( self, event ):
|
||||
"Add a new switch to our canvas."
|
||||
self.newNode( 'Switch', event )
|
||||
|
||||
def dragLink( self, event ):
|
||||
def dragNetLink( self, event ):
|
||||
"Drag a link's endpoint to another node."
|
||||
if self.link is None:
|
||||
return
|
||||
@@ -1821,7 +2001,7 @@ class MiniEdit( Frame ):
|
||||
c = self.canvas
|
||||
c.coords( self.link, self.linkx, self.linky, x, y )
|
||||
|
||||
def releaseLink( self, _event ):
|
||||
def releaseNetLink( self, _event ):
|
||||
"Give up on the current link."
|
||||
if self.link is not None:
|
||||
self.canvas.delete( self.link )
|
||||
@@ -1858,7 +2038,7 @@ class MiniEdit( Frame ):
|
||||
|
||||
def clickNode( self, event ):
|
||||
"Node click handler."
|
||||
if self.active is 'Link':
|
||||
if self.active is 'NetLink':
|
||||
self.startLink( event )
|
||||
else:
|
||||
self.selectNode( event )
|
||||
@@ -1866,14 +2046,14 @@ class MiniEdit( Frame ):
|
||||
|
||||
def dragNode( self, event ):
|
||||
"Node drag handler."
|
||||
if self.active is 'Link':
|
||||
self.dragLink( event )
|
||||
if self.active is 'NetLink':
|
||||
self.dragNetLink( event )
|
||||
else:
|
||||
self.dragNodeAround( event )
|
||||
|
||||
def releaseNode( self, event ):
|
||||
"Node release handler."
|
||||
if self.active is 'Link':
|
||||
if self.active is 'NetLink':
|
||||
self.finishLink( event )
|
||||
|
||||
# Specific node handlers
|
||||
@@ -1980,16 +2160,20 @@ class MiniEdit( Frame ):
|
||||
dest = self.itemToWidget.get( target, None )
|
||||
if ( source is None or dest is None or source == dest
|
||||
or dest in source.links or source in dest.links ):
|
||||
self.releaseLink( event )
|
||||
self.releaseNetLink( event )
|
||||
return
|
||||
# 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) or
|
||||
('Controller' in stags and 'Host' in dtags) or
|
||||
('Controller' in dtags and 'LegacyRouter' in stags) or
|
||||
('Controller' in stags and 'LegacyRouter' in dtags) or
|
||||
('Controller' in dtags and 'LegacySwitch' in stags) or
|
||||
('Controller' in stags and 'LegacySwitch' in dtags) or
|
||||
('Controller' in dtags and 'Host' in stags) or
|
||||
('Controller' in stags and 'Host' in dtags) or
|
||||
('Controller' in stags and 'Controller' in dtags)):
|
||||
self.releaseLink( event )
|
||||
self.releaseNetLink( event )
|
||||
return
|
||||
|
||||
# Set link type
|
||||
@@ -2175,7 +2359,7 @@ class MiniEdit( Frame ):
|
||||
dest = linkDetail['dest']
|
||||
linkopts = linkDetail['linkOpts']
|
||||
linkBox = LinkDialog(self, title='Link Details', linkDefaults=linkopts)
|
||||
if linkBox.result:
|
||||
if linkBox.result is not None:
|
||||
linkDetail['linkOpts'] = linkBox.result
|
||||
print 'New link details = ' + str(linkBox.result)
|
||||
|
||||
@@ -2231,7 +2415,7 @@ class MiniEdit( Frame ):
|
||||
|
||||
if name not in self.net.nameToNode:
|
||||
return
|
||||
if 'Switch' in tags:
|
||||
if 'Switch' in tags or 'LegacySwitch' in tags:
|
||||
call(["xterm -T 'Bridge Details' -sb -sl 2000 -e 'ovs-vsctl list bridge " + name + "; read -p \"Press Enter to close\"' &"], shell=True)
|
||||
|
||||
def ovsShow( self, _ignore=None ):
|
||||
@@ -2309,6 +2493,7 @@ class MiniEdit( Frame ):
|
||||
for widget in self.widgetToItem:
|
||||
name = widget[ 'text' ]
|
||||
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
|
||||
#print name+' has '+str(tags)
|
||||
|
||||
if 'Switch' in tags:
|
||||
opts = self.switchOpts[name]
|
||||
@@ -2323,14 +2508,27 @@ class MiniEdit( Frame ):
|
||||
if opts['switchType'] == 'default':
|
||||
if self.appPrefs['switchType'] == 'ivs':
|
||||
switchClass = IVSSwitch
|
||||
elif self.appPrefs['switchType'] == 'user':
|
||||
switchClass = CustomUserSwitch
|
||||
elif self.appPrefs['switchType'] == 'userns':
|
||||
switchParms['inNamespace'] = True
|
||||
switchClass = CustomUserSwitch
|
||||
else:
|
||||
switchClass = customOvs
|
||||
elif opts['switchType'] == 'user':
|
||||
switchClass = CustomUserSwitch
|
||||
elif opts['switchType'] == 'userns':
|
||||
switchClass = CustomUserSwitch
|
||||
switchParms['inNamespace'] = True
|
||||
elif opts['switchType'] == 'ivs':
|
||||
switchClass = IVSSwitch
|
||||
else:
|
||||
switchClass = customOvs
|
||||
newSwitch = net.addSwitch( name , cls=switchClass, **switchParms)
|
||||
#if self.appPrefs['switchType'] == 'ovs':
|
||||
if switchClass == CustomUserSwitch:
|
||||
if ('switchIP' in opts):
|
||||
if (len(opts['switchIP']) > 0):
|
||||
newSwitch.setSwitchIP(opts['switchIP'])
|
||||
if switchClass == customOvs:
|
||||
newSwitch.setOpenFlowVersion(self.appPrefs['openFlowVersions'])
|
||||
if ('switchIP' in opts):
|
||||
@@ -2343,6 +2541,10 @@ class MiniEdit( Frame ):
|
||||
if self.checkIntf(extInterface):
|
||||
Intf( extInterface, node=newSwitch )
|
||||
|
||||
elif 'LegacySwitch' in tags:
|
||||
newSwitch = net.addSwitch( name , cls=LegacySwitch)
|
||||
elif 'LegacyRouter' in tags:
|
||||
newSwitch = net.addHost( name , cls=LegacyRouter)
|
||||
elif 'Host' in tags:
|
||||
opts = self.hostOpts[name]
|
||||
ip = None
|
||||
@@ -2357,8 +2559,11 @@ class MiniEdit( Frame ):
|
||||
ip = ipAdd(i=nodeNum, prefixLen=prefixLen, ipBaseNum=ipBaseNum)
|
||||
|
||||
# Create the correct host class
|
||||
hostCls = Host
|
||||
if 'cores' in opts or 'cpu' in opts:
|
||||
hostCls=CPULimitedHost
|
||||
newHost = net.addHost( name,
|
||||
cls=CPULimitedHost,
|
||||
cls=hostCls,
|
||||
ip=ip,
|
||||
defaultRoute=defaultRoute
|
||||
)
|
||||
@@ -2432,7 +2637,10 @@ class MiniEdit( Frame ):
|
||||
linkopts=link['linkOpts']
|
||||
srcName, dstName = src[ 'text' ], dst[ 'text' ]
|
||||
src, dst = net.nameToNode[ srcName ], net.nameToNode[ dstName ]
|
||||
net.addLink(src, dst, **linkopts)
|
||||
if linkopts:
|
||||
net.addLink(src, dst, cls=TCLink, **linkopts)
|
||||
else:
|
||||
net.addLink(src, dst)
|
||||
self.canvas.itemconfig(key, dash=())
|
||||
|
||||
|
||||
@@ -2445,7 +2653,6 @@ class MiniEdit( Frame ):
|
||||
net = Mininet( topo=None,
|
||||
listenPort=dpctl,
|
||||
build=False,
|
||||
link=TCLink,
|
||||
ipBase=self.appPrefs['ipBase'] )
|
||||
|
||||
self.buildNodes(net)
|
||||
@@ -2564,6 +2771,9 @@ class MiniEdit( Frame ):
|
||||
info( name + ' ')
|
||||
# Figure out what controllers will manage this switch
|
||||
self.net.get(name).start( switchControllers )
|
||||
if 'LegacySwitch' in tags:
|
||||
self.net.get(name).start( [] )
|
||||
info( name + ' ')
|
||||
info('\n')
|
||||
|
||||
self.postStartSetup()
|
||||
@@ -2599,6 +2809,15 @@ class MiniEdit( Frame ):
|
||||
# make sure to release the grab (Tk 8.0a1 only)
|
||||
self.controllerPopup.grab_release()
|
||||
|
||||
def do_legacyRouterPopup(self, event):
|
||||
# display the popup menu
|
||||
if ( self.net is not None ):
|
||||
try:
|
||||
self.legacyRouterRunPopup.tk_popup(event.x_root, event.y_root, 0)
|
||||
finally:
|
||||
# make sure to release the grab (Tk 8.0a1 only)
|
||||
self.legacyRouterRunPopup.grab_release()
|
||||
|
||||
def do_hostPopup(self, event):
|
||||
# display the popup menu
|
||||
if ( self.net is None ):
|
||||
@@ -2614,6 +2833,15 @@ class MiniEdit( Frame ):
|
||||
# make sure to release the grab (Tk 8.0a1 only)
|
||||
self.hostRunPopup.grab_release()
|
||||
|
||||
def do_legacySwitchPopup(self, event):
|
||||
# display the popup menu
|
||||
if ( self.net is not None ):
|
||||
try:
|
||||
self.switchRunPopup.tk_popup(event.x_root, event.y_root, 0)
|
||||
finally:
|
||||
# make sure to release the grab (Tk 8.0a1 only)
|
||||
self.switchRunPopup.grab_release()
|
||||
|
||||
def do_switchPopup(self, event):
|
||||
# display the popup menu
|
||||
if ( self.net is None ):
|
||||
@@ -2837,6 +3065,108 @@ def miniEditImages():
|
||||
'Select': BitmapImage(
|
||||
file='/usr/include/X11/bitmaps/left_ptr' ),
|
||||
|
||||
'Switch': PhotoImage( data=r"""
|
||||
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
|
||||
"""),
|
||||
|
||||
'LegacySwitch': PhotoImage( data=r"""
|
||||
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
|
||||
4BE2eIRYeHAEIBwBP0Y4Qn41YWRSCQgAOw==
|
||||
"""),
|
||||
|
||||
'LegacyRouter': PhotoImage( data=r"""
|
||||
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
|
||||
gGPLHwLwcMIo12Qxu0ABAQA7
|
||||
"""),
|
||||
|
||||
'Controller': PhotoImage( data=r"""
|
||||
R0lGODlhMAAwAPcAAAEBAWfNAYWFhcfHx+3t6/f390lJUaWlpfPz8/Hx72lpaZGRke/v77m5uc0B
|
||||
AeHh4e/v7WNjY3t7e5eXlyMjI4mJidPT0+3t7f///09PT7Ozs/X19fHx8ZWTk8HBwX9/fwAAAAAA
|
||||
@@ -2890,7 +3220,7 @@ def miniEditImages():
|
||||
C8cSBBAQADs=
|
||||
""" ),
|
||||
|
||||
'Switch': PhotoImage( data=r"""
|
||||
'OldSwitch': PhotoImage( data=r"""
|
||||
R0lGODlhIAAYAPcAMf//////zP//mf//Zv//M///AP/M///MzP/M
|
||||
mf/MZv/MM//MAP+Z//+ZzP+Zmf+ZZv+ZM/+ZAP9m//9mzP9mmf9m
|
||||
Zv9mM/9mAP8z//8zzP8zmf8zZv8zM/8zAP8A//8AzP8Amf8AZv8A
|
||||
@@ -2917,7 +3247,7 @@ def miniEditImages():
|
||||
6saLWLNq3cq1q9evYB0GBAA7
|
||||
""" ),
|
||||
|
||||
'Link': PhotoImage( data=r"""
|
||||
'NetLink': PhotoImage( data=r"""
|
||||
R0lGODlhFgAWAPcAMf//////zP//mf//Zv//M///AP/M///MzP/M
|
||||
mf/MZv/MM//MAP+Z//+ZzP+Zmf+ZZv+ZM/+ZAP9m//9mzP9mmf9m
|
||||
Zv9mM/9mAP8z//8zzP8zmf8zZv8zM/8zAP8A//8AzP8Amf8AZv8A
|
||||
|
||||
Reference in New Issue
Block a user