Merge pull request #348 from ggee/miniedit2109

Update to MiniEdit 2.2.0.1
This commit is contained in:
lantz
2014-08-20 22:03:21 -05:00
+387 -111
View File
@@ -13,10 +13,11 @@ Controller icon from http://semlabs.co.uk/
OpenFlow icon from https://www.opennetworking.org/ OpenFlow icon from https://www.opennetworking.org/
""" """
MINIEDIT_VERSION = '2.1.0.8.1' MINIEDIT_VERSION = '2.2.0.1'
from optparse import OptionParser from optparse import OptionParser
from Tkinter import * from Tkinter import *
from ttk import Notebook
from tkMessageBox import showinfo, showerror, showwarning from tkMessageBox import showinfo, showerror, showwarning
from subprocess import call from subprocess import call
import tkFont import tkFont
@@ -28,6 +29,7 @@ import json
from distutils.version import StrictVersion from distutils.version import StrictVersion
import os import os
import sys import sys
from functools import partial
if 'PYTHONPATH' in os.environ: if 'PYTHONPATH' in os.environ:
sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
@@ -38,9 +40,10 @@ from mininet.log import info, error, debug, output, setLogLevel
from mininet.net import Mininet, VERSION from mininet.net import Mininet, VERSION
from mininet.util import ipStr, netParse, ipAdd, quietRun from mininet.util import ipStr, netParse, ipAdd, quietRun
from mininet.util import buildTopo from mininet.util import buildTopo
from mininet.util import custom, customConstructor
from mininet.term import makeTerm, cleanUpScreens from mininet.term import makeTerm, cleanUpScreens
from mininet.node import Controller, RemoteController, NOX, OVSController from mininet.node import Controller, RemoteController, NOX, OVSController
from mininet.node import CPULimitedHost, Host, Node from mininet.node import CPULimitedHost, Host, Node, HostWithPrivateDirs
from mininet.node import OVSKernelSwitch, OVSSwitch, UserSwitch from mininet.node import OVSKernelSwitch, OVSSwitch, UserSwitch
from mininet.link import TCLink, Intf, Link from mininet.link import TCLink, Intf, Link
from mininet.cli import CLI from mininet.cli import CLI
@@ -66,6 +69,40 @@ CONTROLLERS = { 'ref': Controller,
'nox': NOX, 'nox': NOX,
'remote': RemoteController, 'remote': RemoteController,
'none': lambda name: None } 'none': lambda name: None }
LINKDEF = 'default'
LINKS = { 'default': Link,
'tc': TCLink }
HOSTDEF = 'proc'
HOSTS = { 'proc': Host,
'rt': custom( CPULimitedHost, sched='rt' ),
'cfs': custom( CPULimitedHost, sched='cfs' ) }
class CPULimitedHostWithPrivateDirs( CPULimitedHost ):
"Host with private directories"
def __init__( self, name, sched='cfs', **kwargs ):
"privateDirs: list of private directory strings or tuples"
self.name = name
self.privateDirs = kwargs.pop( 'privateDirs', [] )
CPULimitedHost.__init__( self, name, sched, **kwargs )
self.mountPrivateDirs()
def mountPrivateDirs( self ):
"mount private directories"
for directory in self.privateDirs:
if isinstance( directory, tuple ):
# mount given private directory
privateDir = directory[ 1 ] % self.__dict__
mountPoint = directory[ 0 ]
self.cmd( 'mkdir -p %s' % privateDir )
self.cmd( 'mkdir -p %s' % mountPoint )
self.cmd( 'mount --bind %s %s' %
( privateDir, mountPoint ) )
else:
# mount temporary filesystem on directory
self.cmd( 'mkdir -p %s' % directory )
self.cmd( 'mount -n -t tmpfs tmpfs %s' % directory )
class InbandController( RemoteController ): class InbandController( RemoteController ):
@@ -124,35 +161,9 @@ class customOvs(OVSSwitch):
def setSwitchIP(self, ip): def setSwitchIP(self, ip):
self.switchIP = ip self.switchIP = ip
def getOpenFlowVersion(self):
return self.openFlowVersions
def setOpenFlowVersion(self, versions):
self.openFlowVersions = []
if versions['ovsOf10'] == '1':
self.openFlowVersions.append('OpenFlow10')
if versions['ovsOf11'] == '1':
self.openFlowVersions.append('OpenFlow11')
if versions['ovsOf12'] == '1':
self.openFlowVersions.append('OpenFlow12')
if versions['ovsOf13'] == '1':
self.openFlowVersions.append('OpenFlow13')
def configureOpenFlowVersion(self):
if not ( 'OpenFlow11' in self.openFlowVersions or
'OpenFlow12' in self.openFlowVersions or
'OpenFlow13' in self.openFlowVersions ):
return
protoList = ",".join(self.openFlowVersions)
print 'Configuring OpenFlow to '+protoList
self.cmd( 'ovs-vsctl -- set bridge', self, 'protocols='+protoList)
def start( self, controllers ): def start( self, controllers ):
# Call superclass constructor # Call superclass constructor
OVSSwitch.start( self, controllers ) OVSSwitch.start( self, controllers )
# Set OpenFlow Versions
self.configureOpenFlowVersion()
# Set Switch IP address # Set Switch IP address
if (self.switchIP is not None): if (self.switchIP is not None):
self.cmd( 'ifconfig', self, self.switchIP ) self.cmd( 'ifconfig', self, self.switchIP )
@@ -201,7 +212,7 @@ class PrefsDialog(tkSimpleDialog.Dialog):
# Selection of switch type # Selection of switch type
Label(self.leftfieldFrame, text="Default Switch:").grid(row=3, sticky=E) Label(self.leftfieldFrame, text="Default Switch:").grid(row=3, sticky=E)
self.switchType = StringVar(self.leftfieldFrame) self.switchType = StringVar(self.leftfieldFrame)
self.switchTypeMenu = OptionMenu(self.leftfieldFrame, self.switchType, "Open vSwitch", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace") self.switchTypeMenu = OptionMenu(self.leftfieldFrame, self.switchType, "Open vSwitch Kernel Mode", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace")
self.switchTypeMenu.grid(row=3, column=1, sticky=W) self.switchTypeMenu.grid(row=3, column=1, sticky=W)
switchTypePref = self.prefValues['switchType'] switchTypePref = self.prefValues['switchType']
if switchTypePref == 'ivs': if switchTypePref == 'ivs':
@@ -211,7 +222,7 @@ class PrefsDialog(tkSimpleDialog.Dialog):
elif switchTypePref == 'user': elif switchTypePref == 'user':
self.switchType.set("Userspace Switch") self.switchType.set("Userspace Switch")
else: else:
self.switchType.set("Open vSwitch") self.switchType.set("Open vSwitch Kernel Mode")
# Fields for OVS OpenFlow version # Fields for OVS OpenFlow version
@@ -431,36 +442,43 @@ class HostDialog(CustomDialog):
def body(self, master): def body(self, master):
self.rootFrame = master self.rootFrame = master
self.leftfieldFrame = Frame(self.rootFrame) n = Notebook(self.rootFrame)
self.leftfieldFrame.grid(row=0, column=0, sticky='nswe', columnspan=2) self.propFrame = Frame(n)
self.rightfieldFrame = Frame(self.rootFrame) self.vlanFrame = Frame(n)
self.rightfieldFrame.grid(row=0, column=2, sticky='nswe', columnspan=2) self.interfaceFrame = Frame(n)
self.mountFrame = Frame(n)
n.add(self.propFrame, text='Properties')
n.add(self.vlanFrame, text='VLAN Interfaces')
n.add(self.interfaceFrame, text='External Interfaces')
n.add(self.mountFrame, text='Private Directories')
n.pack()
### TAB 1
# Field for Hostname # Field for Hostname
Label(self.leftfieldFrame, text="Hostname:").grid(row=0, sticky=E) Label(self.propFrame, text="Hostname:").grid(row=0, sticky=E)
self.hostnameEntry = Entry(self.leftfieldFrame) self.hostnameEntry = Entry(self.propFrame)
self.hostnameEntry.grid(row=0, column=1) self.hostnameEntry.grid(row=0, column=1)
if 'hostname' in self.prefValues: if 'hostname' in self.prefValues:
self.hostnameEntry.insert(0, self.prefValues['hostname']) self.hostnameEntry.insert(0, self.prefValues['hostname'])
# Field for Switch IP # Field for Switch IP
Label(self.leftfieldFrame, text="IP Address:").grid(row=1, sticky=E) Label(self.propFrame, text="IP Address:").grid(row=1, sticky=E)
self.ipEntry = Entry(self.leftfieldFrame) self.ipEntry = Entry(self.propFrame)
self.ipEntry.grid(row=1, column=1) self.ipEntry.grid(row=1, column=1)
if 'ip' in self.prefValues: if 'ip' in self.prefValues:
self.ipEntry.insert(0, self.prefValues['ip']) self.ipEntry.insert(0, self.prefValues['ip'])
# Field for default route # Field for default route
Label(self.leftfieldFrame, text="Default Route:").grid(row=2, sticky=E) Label(self.propFrame, text="Default Route:").grid(row=2, sticky=E)
self.routeEntry = Entry(self.leftfieldFrame) self.routeEntry = Entry(self.propFrame)
self.routeEntry.grid(row=2, column=1) self.routeEntry.grid(row=2, column=1)
if 'defaultRoute' in self.prefValues: if 'defaultRoute' in self.prefValues:
self.routeEntry.insert(0, self.prefValues['defaultRoute']) self.routeEntry.insert(0, self.prefValues['defaultRoute'])
# Field for CPU # Field for CPU
Label(self.rightfieldFrame, text="Amount CPU:").grid(row=0, sticky=E) Label(self.propFrame, text="Amount CPU:").grid(row=3, sticky=E)
self.cpuEntry = Entry(self.rightfieldFrame) self.cpuEntry = Entry(self.propFrame)
self.cpuEntry.grid(row=0, column=1) self.cpuEntry.grid(row=3, column=1)
if 'cpu' in self.prefValues: if 'cpu' in self.prefValues:
self.cpuEntry.insert(0, str(self.prefValues['cpu'])) self.cpuEntry.insert(0, str(self.prefValues['cpu']))
# Selection of Scheduler # Selection of Scheduler
@@ -468,26 +486,40 @@ class HostDialog(CustomDialog):
sched = self.prefValues['sched'] sched = self.prefValues['sched']
else: else:
sched = 'host' sched = 'host'
self.schedVar = StringVar(self.rightfieldFrame) self.schedVar = StringVar(self.propFrame)
self.schedOption = OptionMenu(self.rightfieldFrame, self.schedVar, "host", "cfs", "rt") self.schedOption = OptionMenu(self.propFrame, self.schedVar, "host", "cfs", "rt")
self.schedOption.grid(row=0, column=2, sticky=W) self.schedOption.grid(row=3, column=2, sticky=W)
self.schedVar.set(sched) self.schedVar.set(sched)
# Selection of Cores # Selection of Cores
Label(self.rightfieldFrame, text="Cores:").grid(row=1, sticky=E) Label(self.propFrame, text="Cores:").grid(row=4, sticky=E)
self.coreEntry = Entry(self.rightfieldFrame) self.coreEntry = Entry(self.propFrame)
self.coreEntry.grid(row=1, column=1) self.coreEntry.grid(row=4, column=1)
if 'cores' in self.prefValues: if 'cores' in self.prefValues:
self.coreEntry.insert(1, self.prefValues['cores']) self.coreEntry.insert(1, self.prefValues['cores'])
# Start command
Label(self.propFrame, text="Start Command:").grid(row=5, sticky=E)
self.startEntry = Entry(self.propFrame)
self.startEntry.grid(row=5, column=1, sticky='nswe', columnspan=3)
if 'startCommand' in self.prefValues:
self.startEntry.insert(0, str(self.prefValues['startCommand']))
# Stop command
Label(self.propFrame, text="Stop Command:").grid(row=6, sticky=E)
self.stopEntry = Entry(self.propFrame)
self.stopEntry.grid(row=6, column=1, sticky='nswe', columnspan=3)
if 'stopCommand' in self.prefValues:
self.stopEntry.insert(0, str(self.prefValues['stopCommand']))
### TAB 2
# External Interfaces # External Interfaces
self.externalInterfaces = 0 self.externalInterfaces = 0
Label(self.rootFrame, text="External Interface:").grid(row=1, column=0, sticky=E) Label(self.interfaceFrame, text="External Interface:").grid(row=0, column=0, sticky=E)
self.b = Button( self.rootFrame, text='Add', command=self.addInterface) self.b = Button( self.interfaceFrame, text='Add', command=self.addInterface)
self.b.grid(row=1, column=1) self.b.grid(row=0, column=1)
self.interfaceFrame = VerticalScrolledTable(self.rootFrame, rows=0, columns=1, title='External Interfaces') self.interfaceFrame = VerticalScrolledTable(self.interfaceFrame, rows=0, columns=1, title='External Interfaces')
self.interfaceFrame.grid(row=2, column=0, sticky='nswe', columnspan=2) self.interfaceFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
self.tableFrame = self.interfaceFrame.interior self.tableFrame = self.interfaceFrame.interior
self.tableFrame.addRow(value=['Interface Name'], readonly=True) self.tableFrame.addRow(value=['Interface Name'], readonly=True)
@@ -499,14 +531,15 @@ class HostDialog(CustomDialog):
for externalInterface in externalInterfaces: for externalInterface in externalInterfaces:
self.tableFrame.addRow(value=[externalInterface]) self.tableFrame.addRow(value=[externalInterface])
### TAB 3
# VLAN Interfaces # VLAN Interfaces
self.vlanInterfaces = 0 self.vlanInterfaces = 0
Label(self.rootFrame, text="VLAN Interface:").grid(row=1, column=2, sticky=E) Label(self.vlanFrame, text="VLAN Interface:").grid(row=0, column=0, sticky=E)
self.vlanButton = Button( self.rootFrame, text='Add', command=self.addVlanInterface) self.vlanButton = Button( self.vlanFrame, text='Add', command=self.addVlanInterface)
self.vlanButton.grid(row=1, column=3) self.vlanButton.grid(row=0, column=1)
self.vlanFrame = VerticalScrolledTable(self.rootFrame, rows=0, columns=2, title='VLAN Interfaces') self.vlanFrame = VerticalScrolledTable(self.vlanFrame, rows=0, columns=2, title='VLAN Interfaces')
self.vlanFrame.grid(row=2, column=2, sticky='nswe', columnspan=2) self.vlanFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
self.vlanTableFrame = self.vlanFrame.interior self.vlanTableFrame = self.vlanFrame.interior
self.vlanTableFrame.addRow(value=['IP Address','VLAN ID'], readonly=True) self.vlanTableFrame.addRow(value=['IP Address','VLAN ID'], readonly=True)
@@ -516,6 +549,31 @@ class HostDialog(CustomDialog):
for vlanInterface in vlanInterfaces: for vlanInterface in vlanInterfaces:
self.vlanTableFrame.addRow(value=vlanInterface) self.vlanTableFrame.addRow(value=vlanInterface)
### TAB 4
# Private Directories
self.privateDirectories = 0
Label(self.mountFrame, text="Private Directory:").grid(row=0, column=0, sticky=E)
self.mountButton = Button( self.mountFrame, text='Add', command=self.addDirectory)
self.mountButton.grid(row=0, column=1)
self.mountFrame = VerticalScrolledTable(self.mountFrame, rows=0, columns=2, title='Directories')
self.mountFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
self.mountTableFrame = self.mountFrame.interior
self.mountTableFrame.addRow(value=['Mount','Persistent Directory'], readonly=True)
directoryList = []
if 'privateDirectory' in self.prefValues:
directoryList = self.prefValues['privateDirectory']
for privateDir in directoryList:
if isinstance( privateDir, tuple ):
self.mountTableFrame.addRow(value=privateDir)
else:
self.mountTableFrame.addRow(value=[privateDir,''])
def addDirectory( self ):
self.mountTableFrame.addRow()
def addVlanInterface( self ): def addVlanInterface( self ):
self.vlanTableFrame.addRow() self.vlanTableFrame.addRow()
@@ -534,6 +592,13 @@ class HostDialog(CustomDialog):
len(self.vlanTableFrame.get(row, 1)) > 0 and len(self.vlanTableFrame.get(row, 1)) > 0 and
row > 0): row > 0):
vlanInterfaces.append([self.vlanTableFrame.get(row, 0), self.vlanTableFrame.get(row, 1)]) vlanInterfaces.append([self.vlanTableFrame.get(row, 0), self.vlanTableFrame.get(row, 1)])
privateDirectories = []
for row in range(self.mountTableFrame.rows):
if (len(self.mountTableFrame.get(row, 0)) > 0 and row > 0):
if(len(self.mountTableFrame.get(row, 1)) > 0):
privateDirectories.append((self.mountTableFrame.get(row, 0), self.mountTableFrame.get(row, 1)))
else:
privateDirectories.append(self.mountTableFrame.get(row, 0))
results = {'cpu': self.cpuEntry.get(), results = {'cpu': self.cpuEntry.get(),
'cores':self.coreEntry.get(), 'cores':self.coreEntry.get(),
@@ -541,6 +606,9 @@ class HostDialog(CustomDialog):
'hostname':self.hostnameEntry.get(), 'hostname':self.hostnameEntry.get(),
'ip':self.ipEntry.get(), 'ip':self.ipEntry.get(),
'defaultRoute':self.routeEntry.get(), 'defaultRoute':self.routeEntry.get(),
'startCommand':self.startEntry.get(),
'stopCommand':self.stopEntry.get(),
'privateDirectory':privateDirectories,
'externalInterfaces':externalInterfaces, 'externalInterfaces':externalInterfaces,
'vlanInterfaces':vlanInterfaces} 'vlanInterfaces':vlanInterfaces}
self.result = results self.result = results
@@ -555,34 +623,35 @@ class SwitchDialog(CustomDialog):
def body(self, master): def body(self, master):
self.rootFrame = master self.rootFrame = master
self.leftfieldFrame = Frame(self.rootFrame)
self.rightfieldFrame = Frame(self.rootFrame)
self.leftfieldFrame.grid(row=0, column=0, sticky='nswe')
self.rightfieldFrame.grid(row=0, column=1, sticky='nswe')
rowCount = 0 rowCount = 0
externalInterfaces = [] externalInterfaces = []
if 'externalInterfaces' in self.prefValues: if 'externalInterfaces' in self.prefValues:
externalInterfaces = self.prefValues['externalInterfaces'] externalInterfaces = self.prefValues['externalInterfaces']
self.fieldFrame = Frame(self.rootFrame)
self.fieldFrame.grid(row=0, column=0, sticky='nswe')
# Field for Hostname # Field for Hostname
Label(self.fieldFrame, text="Hostname:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="Hostname:").grid(row=rowCount, sticky=E)
self.hostnameEntry = Entry(self.fieldFrame) self.hostnameEntry = Entry(self.leftfieldFrame)
self.hostnameEntry.grid(row=rowCount, column=1) self.hostnameEntry.grid(row=rowCount, column=1)
self.hostnameEntry.insert(0, self.prefValues['hostname']) self.hostnameEntry.insert(0, self.prefValues['hostname'])
rowCount+=1 rowCount+=1
# Field for DPID # Field for DPID
Label(self.fieldFrame, text="DPID:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="DPID:").grid(row=rowCount, sticky=E)
self.dpidEntry = Entry(self.fieldFrame) self.dpidEntry = Entry(self.leftfieldFrame)
self.dpidEntry.grid(row=rowCount, column=1) self.dpidEntry.grid(row=rowCount, column=1)
if 'dpid' in self.prefValues: if 'dpid' in self.prefValues:
self.dpidEntry.insert(0, self.prefValues['dpid']) self.dpidEntry.insert(0, self.prefValues['dpid'])
rowCount+=1 rowCount+=1
# Field for Netflow # Field for Netflow
Label(self.fieldFrame, text="Enable NetFlow:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="Enable NetFlow:").grid(row=rowCount, sticky=E)
self.nflow = IntVar() self.nflow = IntVar()
self.nflowButton = Checkbutton(self.fieldFrame, variable=self.nflow) self.nflowButton = Checkbutton(self.leftfieldFrame, variable=self.nflow)
self.nflowButton.grid(row=rowCount, column=1, sticky=W) self.nflowButton.grid(row=rowCount, column=1, sticky=W)
if 'netflow' in self.prefValues: if 'netflow' in self.prefValues:
if self.prefValues['netflow'] == '0': if self.prefValues['netflow'] == '0':
@@ -594,9 +663,9 @@ class SwitchDialog(CustomDialog):
rowCount+=1 rowCount+=1
# Field for sflow # Field for sflow
Label(self.fieldFrame, text="Enable sFlow:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="Enable sFlow:").grid(row=rowCount, sticky=E)
self.sflow = IntVar() self.sflow = IntVar()
self.sflowButton = Checkbutton(self.fieldFrame, variable=self.sflow) self.sflowButton = Checkbutton(self.leftfieldFrame, variable=self.sflow)
self.sflowButton.grid(row=rowCount, column=1, sticky=W) self.sflowButton.grid(row=rowCount, column=1, sticky=W)
if 'sflow' in self.prefValues: if 'sflow' in self.prefValues:
if self.prefValues['sflow'] == '0': if self.prefValues['sflow'] == '0':
@@ -608,9 +677,9 @@ class SwitchDialog(CustomDialog):
rowCount+=1 rowCount+=1
# Selection of switch type # Selection of switch type
Label(self.fieldFrame, text="Switch Type:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="Switch Type:").grid(row=rowCount, sticky=E)
self.switchType = StringVar(self.fieldFrame) self.switchType = StringVar(self.leftfieldFrame)
self.switchTypeMenu = OptionMenu(self.fieldFrame, self.switchType, "Default", "Open vSwitch", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace") self.switchTypeMenu = OptionMenu(self.leftfieldFrame, self.switchType, "Default", "Open vSwitch Kernel Mode", "Indigo Virtual Switch", "Userspace Switch", "Userspace Switch inNamespace")
self.switchTypeMenu.grid(row=rowCount, column=1, sticky=W) self.switchTypeMenu.grid(row=rowCount, column=1, sticky=W)
if 'switchType' in self.prefValues: if 'switchType' in self.prefValues:
switchTypePref = self.prefValues['switchType'] switchTypePref = self.prefValues['switchType']
@@ -621,7 +690,7 @@ class SwitchDialog(CustomDialog):
elif switchTypePref == 'user': elif switchTypePref == 'user':
self.switchType.set("Userspace Switch") self.switchType.set("Userspace Switch")
elif switchTypePref == 'ovs': elif switchTypePref == 'ovs':
self.switchType.set("Open vSwitch") self.switchType.set("Open vSwitch Kernel Mode")
else: else:
self.switchType.set("Default") self.switchType.set("Default")
else: else:
@@ -629,34 +698,49 @@ class SwitchDialog(CustomDialog):
rowCount+=1 rowCount+=1
# Field for Switch IP # Field for Switch IP
Label(self.fieldFrame, text="IP Address:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="IP Address:").grid(row=rowCount, sticky=E)
self.ipEntry = Entry(self.fieldFrame) self.ipEntry = Entry(self.leftfieldFrame)
self.ipEntry.grid(row=rowCount, column=1) self.ipEntry.grid(row=rowCount, column=1)
if 'switchIP' in self.prefValues: if 'switchIP' in self.prefValues:
self.ipEntry.insert(0, self.prefValues['switchIP']) self.ipEntry.insert(0, self.prefValues['switchIP'])
rowCount+=1 rowCount+=1
# Field for DPCTL port # Field for DPCTL port
Label(self.fieldFrame, text="DPCTL port:").grid(row=rowCount, sticky=E) Label(self.leftfieldFrame, text="DPCTL port:").grid(row=rowCount, sticky=E)
self.dpctlEntry = Entry(self.fieldFrame) self.dpctlEntry = Entry(self.leftfieldFrame)
self.dpctlEntry.grid(row=rowCount, column=1) self.dpctlEntry.grid(row=rowCount, column=1)
if 'dpctl' in self.prefValues: if 'dpctl' in self.prefValues:
self.dpctlEntry.insert(0, self.prefValues['dpctl']) self.dpctlEntry.insert(0, self.prefValues['dpctl'])
rowCount+=1 rowCount+=1
# External Interfaces # External Interfaces
Label(self.fieldFrame, text="External Interface:").grid(row=rowCount, sticky=E) Label(self.rightfieldFrame, text="External Interface:").grid(row=0, sticky=E)
self.b = Button( self.fieldFrame, text='Add', command=self.addInterface) self.b = Button( self.rightfieldFrame, text='Add', command=self.addInterface)
self.b.grid(row=rowCount, column=1) self.b.grid(row=0, column=1)
self.interfaceFrame = VerticalScrolledTable(self.rootFrame, rows=0, columns=1, title='External Interfaces') self.interfaceFrame = VerticalScrolledTable(self.rightfieldFrame, rows=0, columns=1, title='External Interfaces')
self.interfaceFrame.grid(row=2, column=0, sticky='nswe') self.interfaceFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
self.tableFrame = self.interfaceFrame.interior self.tableFrame = self.interfaceFrame.interior
# Add defined interfaces # Add defined interfaces
for externalInterface in externalInterfaces: for externalInterface in externalInterfaces:
self.tableFrame.addRow(value=[externalInterface]) self.tableFrame.addRow(value=[externalInterface])
rowCount+=1
self.commandFrame = Frame(self.rootFrame)
self.commandFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
self.commandFrame.columnconfigure(1, weight=1)
# Start command
Label(self.commandFrame, text="Start Command:").grid(row=0, column=0, sticky=W)
self.startEntry = Entry(self.commandFrame)
self.startEntry.grid(row=0, column=1, sticky='nsew')
if 'startCommand' in self.prefValues:
self.startEntry.insert(0, str(self.prefValues['startCommand']))
# Stop command
Label(self.commandFrame, text="Stop Command:").grid(row=1, column=0, sticky=W)
self.stopEntry = Entry(self.commandFrame)
self.stopEntry.grid(row=1, column=1, sticky='nsew')
if 'stopCommand' in self.prefValues:
self.stopEntry.insert(0, str(self.prefValues['stopCommand']))
def addInterface( self ): def addInterface( self ):
self.tableFrame.addRow() self.tableFrame.addRow()
@@ -692,6 +776,8 @@ class SwitchDialog(CustomDialog):
results = {'externalInterfaces':externalInterfaces, results = {'externalInterfaces':externalInterfaces,
'hostname':self.hostnameEntry.get(), 'hostname':self.hostnameEntry.get(),
'dpid':dpid, 'dpid':dpid,
'startCommand':self.startEntry.get(),
'stopCommand':self.stopEntry.get(),
'sflow':str(self.sflow.get()), 'sflow':str(self.sflow.get()),
'netflow':str(self.nflow.get()), 'netflow':str(self.nflow.get()),
'dpctl':self.dpctlEntry.get(), 'dpctl':self.dpctlEntry.get(),
@@ -707,7 +793,7 @@ class SwitchDialog(CustomDialog):
results['switchType'] = 'userns' results['switchType'] = 'userns'
elif sw == 'Userspace Switch': elif sw == 'Userspace Switch':
results['switchType'] = 'user' results['switchType'] = 'user'
elif sw == 'Open vSwitch': elif sw == 'Open vSwitch Kernel Mode':
results['switchType'] = 'ovs' results['switchType'] = 'ovs'
else: else:
results['switchType'] = 'default' results['switchType'] = 'default'
@@ -877,6 +963,7 @@ class ControllerDialog(tkSimpleDialog.Dialog):
def body(self, master): def body(self, master):
self.var = StringVar(master) self.var = StringVar(master)
self.protcolvar = StringVar(master)
rowCount=0 rowCount=0
# Field for Hostname # Field for Hostname
@@ -908,6 +995,20 @@ class ControllerDialog(tkSimpleDialog.Dialog):
self.var.set("OVS Controller") self.var.set("OVS Controller")
rowCount+=1 rowCount+=1
# Field for Controller Protcol
Label(master, text="Protocol:").grid(row=rowCount, sticky=E)
if 'controllerProtocol' in self.ctrlrValues:
controllerProtocol = self.ctrlrValues['controllerProtocol']
else:
controllerProtocol = 'tcp'
self.protcol = OptionMenu(master, self.protcolvar, "TCP", "SSL")
self.protcol.grid(row=rowCount, column=1, sticky=W)
if controllerProtocol == 'ssl':
self.protcolvar.set("SSL")
else:
self.protcolvar.set("TCP")
rowCount+=1
# Field for Remove Controller IP # Field for Remove Controller IP
remoteFrame= LabelFrame(master, text='Remote/In-Band Controller', padx=5, pady=5) remoteFrame= LabelFrame(master, text='Remote/In-Band Controller', padx=5, pady=5)
remoteFrame.grid(row=rowCount, column=0, columnspan=2, sticky=W) remoteFrame.grid(row=rowCount, column=0, columnspan=2, sticky=W)
@@ -921,14 +1022,11 @@ class ControllerDialog(tkSimpleDialog.Dialog):
return self.hostnameEntry # initial focus return self.hostnameEntry # initial focus
def apply(self): def apply(self):
hostname = self.hostnameEntry.get() self.result = { 'hostname': self.hostnameEntry.get(),
controllerType = self.var.get() 'remoteIP': self.e1.get(),
remoteIP = self.e1.get() 'remotePort': int(self.e2.get())}
controllerPort = int(self.e2.get())
self.result = { 'hostname': hostname,
'remoteIP': remoteIP,
'remotePort': controllerPort}
controllerType = self.var.get()
if controllerType == 'Remote Controller': if controllerType == 'Remote Controller':
self.result['controllerType'] = 'remote' self.result['controllerType'] = 'remote'
elif controllerType == 'In-Band Controller': elif controllerType == 'In-Band Controller':
@@ -937,6 +1035,11 @@ class ControllerDialog(tkSimpleDialog.Dialog):
self.result['controllerType'] = 'ref' self.result['controllerType'] = 'ref'
else: else:
self.result['controllerType'] = 'ovsc' self.result['controllerType'] = 'ovsc'
controllerProtocol = self.protcolvar.get()
if controllerProtocol == 'SSL':
self.result['controllerProtocol'] = 'ssl'
else:
self.result['controllerProtocol'] = 'tcp'
class ToolTip(object): class ToolTip(object):
@@ -1144,7 +1247,7 @@ class MiniEdit( Frame ):
fileMenu.add_command( label="New", font=font, command=self.newTopology ) fileMenu.add_command( label="New", font=font, command=self.newTopology )
fileMenu.add_command( label="Open", font=font, command=self.loadTopology ) fileMenu.add_command( label="Open", font=font, command=self.loadTopology )
fileMenu.add_command( label="Save", font=font, command=self.saveTopology ) fileMenu.add_command( label="Save", font=font, command=self.saveTopology )
fileMenu.add_command( label="Export", font=font, command=self.exportTopology ) fileMenu.add_command( label="Export Level 2 Script", font=font, command=self.exportScript )
fileMenu.add_separator() fileMenu.add_separator()
fileMenu.add_command( label='Quit', command=self.quit, font=font ) fileMenu.add_command( label='Quit', command=self.quit, font=font )
@@ -1305,6 +1408,17 @@ class MiniEdit( Frame ):
self.itemToWidget[ item ] = icon self.itemToWidget[ item ] = icon
icon.links = {} icon.links = {}
def convertJsonUnicode(self, input):
"Some part of Mininet don't like Unicode"
if isinstance(input, dict):
return {self.convertJsonUnicode(key): self.convertJsonUnicode(value) for key, value in input.iteritems()}
elif isinstance(input, list):
return [self.convertJsonUnicode(element) for element in input]
elif isinstance(input, unicode):
return input.encode('utf-8')
else:
return input
def loadTopology( self ): def loadTopology( self ):
"Load command." "Load command."
c = self.canvas c = self.canvas
@@ -1317,7 +1431,7 @@ class MiniEdit( Frame ):
if f == None: if f == None:
return return
self.newTopology() self.newTopology()
loadedTopology = eval(f.read()) loadedTopology = self.convertJsonUnicode(json.load(f))
# Load application preferences # Load application preferences
if 'application' in loadedTopology: if 'application' in loadedTopology:
@@ -1372,6 +1486,16 @@ class MiniEdit( Frame ):
x = host['x'] x = host['x']
y = host['y'] y = host['y']
self.addNode('Host', nodeNum, float(x), float(y), name=hostname) self.addNode('Host', nodeNum, float(x), float(y), name=hostname)
# Fix JSON converting tuple to list when saving
if 'privateDirectory' in host['opts']:
newDirList = []
for privateDir in host['opts']['privateDirectory']:
if isinstance( privateDir, list ):
newDirList.append((privateDir[0],privateDir[1]))
else:
newDirList.append(privateDir)
host['opts']['privateDirectory'] = newDirList
self.hostOpts[hostname] = host['opts'] self.hostOpts[hostname] = host['opts']
icon = self.findWidgetByName(hostname) icon = self.findWidgetByName(hostname)
icon.bind('<Button-3>', self.do_hostPopup ) icon.bind('<Button-3>', self.do_hostPopup )
@@ -1545,14 +1669,13 @@ class MiniEdit( Frame ):
try: try:
f = open(fileName, 'wb') f = open(fileName, 'wb')
#f.write(str(savingDictionary))
f.write(json.dumps(savingDictionary, sort_keys=True, indent=4, separators=(',', ': '))) f.write(json.dumps(savingDictionary, sort_keys=True, indent=4, separators=(',', ': ')))
except Exception as er: except Exception as er:
print er print er
finally: finally:
f.close() f.close()
def exportTopology( self ): def exportScript( self ):
"Export command." "Export command."
myFormats = [ myFormats = [
('Mininet Custom Topology','*.py'), ('Mininet Custom Topology','*.py'),
@@ -1575,6 +1698,7 @@ class MiniEdit( Frame ):
f.write("from mininet.cli import CLI\n") f.write("from mininet.cli import CLI\n")
f.write("from mininet.log import setLogLevel, info\n") f.write("from mininet.log import setLogLevel, info\n")
f.write("from mininet.link import TCLink, Intf\n") f.write("from mininet.link import TCLink, Intf\n")
f.write("from subprocess import call\n")
inBandCtrl = False inBandCtrl = False
hasLegacySwitch = False hasLegacySwitch = False
@@ -1613,6 +1737,10 @@ class MiniEdit( Frame ):
if 'Controller' in tags: if 'Controller' in tags:
opts = self.controllers[name] opts = self.controllers[name]
controllerType = opts['controllerType'] controllerType = opts['controllerType']
if 'controllerProtocol' in opts:
controllerProtocol = opts['controllerProtocol']
else:
controllerProtocol = 'tcp'
controllerIP = opts['remoteIP'] controllerIP = opts['remoteIP']
controllerPort = opts['remotePort'] controllerPort = opts['remotePort']
@@ -1630,6 +1758,7 @@ class MiniEdit( Frame ):
else: else:
f.write(" controller=Controller,\n") f.write(" controller=Controller,\n")
f.write(" protocol='"+controllerProtocol+"',\n")
f.write(" port="+str(controllerPort)+")\n") f.write(" port="+str(controllerPort)+")\n")
f.write("\n") f.write("\n")
@@ -1757,7 +1886,7 @@ class MiniEdit( Frame ):
f.write(" "+srcName+dstName+" = "+linkOpts+"\n") f.write(" "+srcName+dstName+" = "+linkOpts+"\n")
f.write(" net.addLink("+srcName+", "+dstName) f.write(" net.addLink("+srcName+", "+dstName)
if optsExist: if optsExist:
f.write(", link=TCLink , **"+srcName+dstName) f.write(", cls=TCLink , **"+srcName+dstName)
f.write(")\n") f.write(")\n")
f.write("\n") f.write("\n")
@@ -1780,7 +1909,7 @@ class MiniEdit( Frame ):
f.write("\n") f.write("\n")
f.write(" info( '*** Configuring switches\\n')\n") f.write(" info( '*** Post configure switches and hosts\\n')\n")
for widget in self.widgetToItem: for widget in self.widgetToItem:
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( self.widgetToItem[ widget ] )
@@ -1821,10 +1950,75 @@ class MiniEdit( Frame ):
for vlanInterface in opts['vlanInterfaces']: for vlanInterface in opts['vlanInterfaces']:
f.write(" "+name+".cmd('vconfig add "+name+"-eth0 "+vlanInterface[1]+"')\n") f.write(" "+name+".cmd('vconfig add "+name+"-eth0 "+vlanInterface[1]+"')\n")
f.write(" "+name+".cmd('ifconfig "+name+"-eth0."+vlanInterface[1]+" "+vlanInterface[0]+"')\n") f.write(" "+name+".cmd('ifconfig "+name+"-eth0."+vlanInterface[1]+" "+vlanInterface[0]+"')\n")
# Run User Defined Start Command
if ('startCommand' in opts):
f.write(" "+name+".cmdPrint('"+opts['startCommand']+"')\n")
if 'Switch' in tags:
opts = self.switchOpts[name]
# Run User Defined Start Command
if ('startCommand' in opts):
f.write(" "+name+".cmdPrint('"+opts['startCommand']+"')\n")
# Configure NetFlow
nflowValues = self.appPrefs['netflow']
if len(nflowValues['nflowTarget']) > 0:
nflowEnabled = False
nflowSwitches = ''
for widget in self.widgetToItem:
name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
if 'Switch' in tags:
opts = self.switchOpts[name]
if 'netflow' in opts:
if opts['netflow'] == '1':
nflowSwitches = nflowSwitches+' -- set Bridge '+name+' netflow=@MiniEditNF'
nflowEnabled=True
if nflowEnabled:
nflowCmd = 'ovs-vsctl -- --id=@MiniEditNF create NetFlow '+ 'target=\\\"'+nflowValues['nflowTarget']+'\\\" '+ 'active-timeout='+nflowValues['nflowTimeout']
if nflowValues['nflowAddId'] == '1':
nflowCmd = nflowCmd + ' add_id_to_interface=true'
else:
nflowCmd = nflowCmd + ' add_id_to_interface=false'
f.write(" \n")
f.write(" call('"+nflowCmd+nflowSwitches+"', shell=True)\n")
# Configure sFlow
sflowValues = self.appPrefs['sflow']
if len(sflowValues['sflowTarget']) > 0:
sflowEnabled = False
sflowSwitches = ''
for widget in self.widgetToItem:
name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
if 'Switch' in tags:
opts = self.switchOpts[name]
if 'sflow' in opts:
if opts['sflow'] == '1':
sflowSwitches = sflowSwitches+' -- set Bridge '+name+' sflow=@MiniEditSF'
sflowEnabled=True
if sflowEnabled:
sflowCmd = 'ovs-vsctl -- --id=@MiniEditSF create sFlow '+ 'target=\\\"'+sflowValues['sflowTarget']+'\\\" '+ 'header='+sflowValues['sflowHeader']+' '+ 'sampling='+sflowValues['sflowSampling']+' '+ 'polling='+sflowValues['sflowPolling']
f.write(" \n")
f.write(" call('"+sflowCmd+sflowSwitches+"', shell=True)\n")
f.write("\n") f.write("\n")
f.write(" CLI(net)\n") f.write(" CLI(net)\n")
for widget in self.widgetToItem:
name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
if 'Host' in tags:
opts = self.hostOpts[name]
# Run User Defined Stop Command
if ('stopCommand' in opts):
f.write(" "+name+".cmdPrint('"+opts['stopCommand']+"')\n")
if 'Switch' in tags:
opts = self.switchOpts[name]
# Run User Defined Stop Command
if ('stopCommand' in opts):
f.write(" "+name+".cmdPrint('"+opts['stopCommand']+"')\n")
f.write(" net.stop()\n") f.write(" net.stop()\n")
f.write("\n") f.write("\n")
f.write("if __name__ == '__main__':\n") f.write("if __name__ == '__main__':\n")
@@ -1948,6 +2142,7 @@ class MiniEdit( Frame ):
name = self.nodePrefixes[ node ] + str( self.controllerCount ) name = self.nodePrefixes[ node ] + str( self.controllerCount )
ctrlr = { 'controllerType': 'ref', ctrlr = { 'controllerType': 'ref',
'hostname': name, 'hostname': name,
'controllerProtocol': 'tcp',
'remoteIP': '127.0.0.1', 'remoteIP': '127.0.0.1',
'remotePort': 6633} 'remotePort': 6633}
self.controllers[name] = ctrlr self.controllers[name] = ctrlr
@@ -2272,6 +2467,10 @@ class MiniEdit( Frame ):
if hostBox.result: if hostBox.result:
newHostOpts = {'nodeNum':self.hostOpts[name]['nodeNum']} newHostOpts = {'nodeNum':self.hostOpts[name]['nodeNum']}
newHostOpts['sched'] = hostBox.result['sched'] newHostOpts['sched'] = hostBox.result['sched']
if len(hostBox.result['startCommand']) > 0:
newHostOpts['startCommand'] = hostBox.result['startCommand']
if len(hostBox.result['stopCommand']) > 0:
newHostOpts['stopCommand'] = hostBox.result['stopCommand']
if len(hostBox.result['cpu']) > 0: if len(hostBox.result['cpu']) > 0:
newHostOpts['cpu'] = float(hostBox.result['cpu']) newHostOpts['cpu'] = float(hostBox.result['cpu'])
if len(hostBox.result['cores']) > 0: if len(hostBox.result['cores']) > 0:
@@ -2288,6 +2487,8 @@ class MiniEdit( Frame ):
newHostOpts['externalInterfaces'] = hostBox.result['externalInterfaces'] newHostOpts['externalInterfaces'] = hostBox.result['externalInterfaces']
if len(hostBox.result['vlanInterfaces']) > 0: if len(hostBox.result['vlanInterfaces']) > 0:
newHostOpts['vlanInterfaces'] = hostBox.result['vlanInterfaces'] newHostOpts['vlanInterfaces'] = hostBox.result['vlanInterfaces']
if len(hostBox.result['privateDirectory']) > 0:
newHostOpts['privateDirectory'] = hostBox.result['privateDirectory']
self.hostOpts[name] = newHostOpts self.hostOpts[name] = newHostOpts
print 'New host details for ' + name + ' = ' + str(newHostOpts) print 'New host details for ' + name + ' = ' + str(newHostOpts)
@@ -2309,6 +2510,10 @@ class MiniEdit( Frame ):
newSwitchOpts = {'nodeNum':self.switchOpts[name]['nodeNum']} newSwitchOpts = {'nodeNum':self.switchOpts[name]['nodeNum']}
newSwitchOpts['switchType'] = switchBox.result['switchType'] newSwitchOpts['switchType'] = switchBox.result['switchType']
newSwitchOpts['controllers'] = self.switchOpts[name]['controllers'] newSwitchOpts['controllers'] = self.switchOpts[name]['controllers']
if len(switchBox.result['startCommand']) > 0:
newSwitchOpts['startCommand'] = switchBox.result['startCommand']
if len(switchBox.result['stopCommand']) > 0:
newSwitchOpts['stopCommand'] = switchBox.result['stopCommand']
if len(switchBox.result['dpctl']) > 0: if len(switchBox.result['dpctl']) > 0:
newSwitchOpts['dpctl'] = switchBox.result['dpctl'] newSwitchOpts['dpctl'] = switchBox.result['dpctl']
if len(switchBox.result['dpid']) > 0: if len(switchBox.result['dpid']) > 0:
@@ -2498,6 +2703,7 @@ class MiniEdit( Frame ):
if 'Switch' in tags: if 'Switch' in tags:
opts = self.switchOpts[name] opts = self.switchOpts[name]
#print str(opts)
# Create the correct switch class # Create the correct switch class
switchClass = customOvs switchClass = customOvs
@@ -2525,13 +2731,28 @@ class MiniEdit( Frame ):
switchClass = IVSSwitch switchClass = IVSSwitch
else: else:
switchClass = customOvs switchClass = customOvs
if switchClass == customOvs:
# Set OpenFlow versions
self.openFlowVersions = []
if self.appPrefs['openFlowVersions']['ovsOf10'] == '1':
self.openFlowVersions.append('OpenFlow10')
if self.appPrefs['openFlowVersions']['ovsOf11'] == '1':
self.openFlowVersions.append('OpenFlow11')
if self.appPrefs['openFlowVersions']['ovsOf12'] == '1':
self.openFlowVersions.append('OpenFlow12')
if self.appPrefs['openFlowVersions']['ovsOf13'] == '1':
self.openFlowVersions.append('OpenFlow13')
protoList = ",".join(self.openFlowVersions)
switchParms['protocols'] = protoList
newSwitch = net.addSwitch( name , cls=switchClass, **switchParms) newSwitch = net.addSwitch( name , cls=switchClass, **switchParms)
# Some post startup config
if switchClass == CustomUserSwitch: if switchClass == CustomUserSwitch:
if ('switchIP' in opts): if ('switchIP' in opts):
if (len(opts['switchIP']) > 0): if (len(opts['switchIP']) > 0):
newSwitch.setSwitchIP(opts['switchIP']) newSwitch.setSwitchIP(opts['switchIP'])
if switchClass == customOvs: if switchClass == customOvs:
newSwitch.setOpenFlowVersion(self.appPrefs['openFlowVersions'])
if ('switchIP' in opts): if ('switchIP' in opts):
if (len(opts['switchIP']) > 0): if (len(opts['switchIP']) > 0):
newSwitch.setSwitchIP(opts['switchIP']) newSwitch.setSwitchIP(opts['switchIP'])
@@ -2548,6 +2769,7 @@ class MiniEdit( Frame ):
newSwitch = net.addHost( name , cls=LegacyRouter) newSwitch = net.addHost( name , cls=LegacyRouter)
elif 'Host' in tags: elif 'Host' in tags:
opts = self.hostOpts[name] opts = self.hostOpts[name]
#print str(opts)
ip = None ip = None
defaultRoute = None defaultRoute = None
if 'defaultRoute' in opts and len(opts['defaultRoute']) > 0: if 'defaultRoute' in opts and len(opts['defaultRoute']) > 0:
@@ -2560,9 +2782,18 @@ class MiniEdit( Frame ):
ip = ipAdd(i=nodeNum, prefixLen=prefixLen, ipBaseNum=ipBaseNum) ip = ipAdd(i=nodeNum, prefixLen=prefixLen, ipBaseNum=ipBaseNum)
# Create the correct host class # Create the correct host class
hostCls = Host
if 'cores' in opts or 'cpu' in opts: if 'cores' in opts or 'cpu' in opts:
hostCls=CPULimitedHost if ('privateDirectory' in opts):
hostCls = partial( CPULimitedHostWithPrivateDirs,
privateDirs=opts['privateDirectory'] )
else:
hostCls=CPULimitedHost
else:
if ('privateDirectory' in opts):
hostCls = partial( HostWithPrivateDirs,
privateDirs=opts['privateDirectory'] )
else:
hostCls=Host
newHost = net.addHost( name, newHost = net.addHost( name,
cls=hostCls, cls=hostCls,
ip=ip, ip=ip,
@@ -2590,28 +2821,37 @@ class MiniEdit( Frame ):
# Get controller info from panel # Get controller info from panel
controllerType = opts['controllerType'] controllerType = opts['controllerType']
if 'controllerProtocol' in opts:
controllerProtocol = opts['controllerProtocol']
else:
controllerProtocol = 'tcp'
opts['controllerProtocol'] = 'tcp'
controllerIP = opts['remoteIP']
controllerPort = opts['remotePort']
# Make controller # Make controller
print 'Getting controller selection:'+controllerType print 'Getting controller selection:'+controllerType
controllerIP = opts['remoteIP']
controllerPort = opts['remotePort']
if controllerType == 'remote': if controllerType == 'remote':
net.addController(name=name, net.addController(name=name,
controller=RemoteController, controller=RemoteController,
ip=controllerIP, ip=controllerIP,
protocol=controllerProtocol,
port=controllerPort) port=controllerPort)
elif controllerType == 'inband': elif controllerType == 'inband':
net.addController(name=name, net.addController(name=name,
controller=InbandController, controller=InbandController,
ip=controllerIP, ip=controllerIP,
protocol=controllerProtocol,
port=controllerPort) port=controllerPort)
elif controllerType == 'ovsc': elif controllerType == 'ovsc':
net.addController(name=name, net.addController(name=name,
controller=OVSController, controller=OVSController,
protocol=controllerProtocol,
port=controllerPort) port=controllerPort)
else: else:
net.addController(name=name, net.addController(name=name,
controller=Controller, controller=Controller,
protocol=controllerProtocol,
port=controllerPort) port=controllerPort)
else: else:
@@ -2637,11 +2877,13 @@ class MiniEdit( Frame ):
dst=link['dest'] dst=link['dest']
linkopts=link['linkOpts'] linkopts=link['linkOpts']
srcName, dstName = src[ 'text' ], dst[ 'text' ] srcName, dstName = src[ 'text' ], dst[ 'text' ]
src, dst = net.nameToNode[ srcName ], net.nameToNode[ dstName ] srcNode, dstNode = net.nameToNode[ srcName ], net.nameToNode[ dstName ]
if linkopts: if linkopts:
net.addLink(src, dst, cls=TCLink, **linkopts) net.addLink(srcNode, dstNode, cls=TCLink, **linkopts)
else: else:
net.addLink(src, dst) #print str(srcNode)
#print str(dstNode)
net.addLink(srcNode, dstNode)
self.canvas.itemconfig(key, dash=()) self.canvas.itemconfig(key, dash=())
@@ -2667,19 +2909,28 @@ class MiniEdit( Frame ):
def postStartSetup( self ): def postStartSetup( self ):
# Setup host VLAN subinterfaces # Setup host details
for widget in self.widgetToItem: for widget in self.widgetToItem:
name = widget[ 'text' ] name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] ) tags = self.canvas.gettags( self.widgetToItem[ widget ] )
if 'Host' in tags: if 'Host' in tags:
newHost = self.net.get(name)
opts = self.hostOpts[name] opts = self.hostOpts[name]
# Attach vlan interfaces # Attach vlan interfaces
if ('vlanInterfaces' in opts): if ('vlanInterfaces' in opts):
for vlanInterface in opts['vlanInterfaces']: for vlanInterface in opts['vlanInterfaces']:
print 'adding vlan interface '+vlanInterface[1] print 'adding vlan interface '+vlanInterface[1]
newHost = self.net.get(name)
newHost.cmdPrint('vconfig add '+name+'-eth0 '+vlanInterface[1])
newHost.cmdPrint('ifconfig '+name+'-eth0.'+vlanInterface[1]+' '+vlanInterface[0]) newHost.cmdPrint('ifconfig '+name+'-eth0.'+vlanInterface[1]+' '+vlanInterface[0])
# Run User Defined Start Command
if ('startCommand' in opts):
newHost.cmdPrint(opts['startCommand'])
if 'Switch' in tags:
newNode = self.net.get(name)
opts = self.switchOpts[name]
# Run User Defined Start Command
if ('startCommand' in opts):
newNode.cmdPrint(opts['startCommand'])
# Configure NetFlow # Configure NetFlow
nflowValues = self.appPrefs['netflow'] nflowValues = self.appPrefs['netflow']
@@ -2782,6 +3033,23 @@ class MiniEdit( Frame ):
def stop( self ): def stop( self ):
"Stop network." "Stop network."
if self.net is not None: if self.net is not None:
# Stop host details
for widget in self.widgetToItem:
name = widget[ 'text' ]
tags = self.canvas.gettags( self.widgetToItem[ widget ] )
if 'Host' in tags:
newHost = self.net.get(name)
opts = self.hostOpts[name]
# Run User Defined Stop Command
if ('stopCommand' in opts):
newHost.cmdPrint(opts['stopCommand'])
if 'Switch' in tags:
newNode = self.net.get(name)
opts = self.switchOpts[name]
# Run User Defined Stop Command
if ('stopCommand' in opts):
newNode.cmdPrint(opts['stopCommand'])
self.net.stop() self.net.stop()
cleanUpScreens() cleanUpScreens()
self.net = None self.net = None
@@ -2908,6 +3176,8 @@ class MiniEdit( Frame ):
opts = OptionParser( description=desc, usage=usage ) opts = OptionParser( description=desc, usage=usage )
addDictOption( opts, TOPOS, TOPODEF, 'topo' ) addDictOption( opts, TOPOS, TOPODEF, 'topo' )
addDictOption( opts, LINKS, LINKDEF, 'link' )
opts.add_option( '--custom', type='string', default=None, opts.add_option( '--custom', type='string', default=None,
help='read custom topo and node params from .py' + help='read custom topo and node params from .py' +
'file' ) 'file' )
@@ -2947,7 +3217,8 @@ class MiniEdit( Frame ):
return return
self.newTopology() self.newTopology()
topo = buildTopo( TOPOS, self.options.topo ) topo = buildTopo( TOPOS, self.options.topo )
importNet = Mininet(topo=topo, build=False) link = customConstructor( LINKS, self.options.link )
importNet = Mininet(topo=topo, build=False, link=link)
importNet.build() importNet.build()
c = self.canvas c = self.canvas
@@ -2965,6 +3236,7 @@ class MiniEdit( Frame ):
icon.bind('<Button-3>', self.do_controllerPopup ) icon.bind('<Button-3>', self.do_controllerPopup )
ctrlr = { 'controllerType': 'ref', ctrlr = { 'controllerType': 'ref',
'hostname': name, 'hostname': name,
'controllerProtocol': controller.protocol,
'remoteIP': controller.ip, 'remoteIP': controller.ip,
'remotePort': controller.port} 'remotePort': controller.port}
self.controllers[name] = ctrlr self.controllers[name] = ctrlr
@@ -3038,6 +3310,7 @@ class MiniEdit( Frame ):
print 'links:'+str(len(topo.links())) print 'links:'+str(len(topo.links()))
#[('h1', 's3'), ('h2', 's4'), ('s3', 's4')] #[('h1', 's3'), ('h2', 's4'), ('s3', 's4')]
for link in topo.links(): for link in topo.links():
print str(link)
srcNode = link[0] srcNode = link[0]
src = self.findWidgetByName(srcNode) src = self.findWidgetByName(srcNode)
sx, sy = self.canvas.coords( self.widgetToItem[ src ] ) sx, sy = self.canvas.coords( self.widgetToItem[ src ] )
@@ -3046,10 +3319,13 @@ class MiniEdit( Frame ):
dest = self.findWidgetByName(destNode) dest = self.findWidgetByName(destNode)
dx, dy = self.canvas.coords( self.widgetToItem[ dest] ) dx, dy = self.canvas.coords( self.widgetToItem[ dest] )
params = topo.linkInfo( srcNode, destNode )
print 'Link Parameters='+str(params)
self.link = self.canvas.create_line( sx, sy, dx, dy, width=4, self.link = self.canvas.create_line( sx, sy, dx, dy, width=4,
fill='blue', tag='link' ) fill='blue', tag='link' )
c.itemconfig(self.link, tags=c.gettags(self.link)+('data',)) c.itemconfig(self.link, tags=c.gettags(self.link)+('data',))
self.addLink( src, dest ) self.addLink( src, dest, linkopts=params )
self.createDataLinkBindings() self.createDataLinkBindings()
self.link = self.linkWidget = None self.link = self.linkWidget = None