From 1a5314150224a503435e16ce5df99306dfd189cb Mon Sep 17 00:00:00 2001
From: Gregory Gee <gee.developer@gmail.com>
Date: Thu, 14 Aug 2014 21:41:45 -0400
Subject: [PATCH] Update to MiniEdit 2.2.0.0

- Updated for new Mininet 2.2.0
- Support TCP or SSL for remote controller
- Support HostWithPrivateDirs Hosts
---
 examples/miniedit.py | 246 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 183 insertions(+), 63 deletions(-)

diff --git a/examples/miniedit.py b/examples/miniedit.py
index 62336a00..4d1fa817 100755
--- a/examples/miniedit.py
+++ b/examples/miniedit.py
@@ -13,10 +13,11 @@
 OpenFlow icon from https://www.opennetworking.org/
 """
 
-MINIEDIT_VERSION = '2.1.0.9'
+MINIEDIT_VERSION = '2.2.0.0'
 
 from optparse import OptionParser
 from Tkinter import *
+from ttk import Notebook
 from tkMessageBox import showinfo, showerror, showwarning
 from subprocess import call
 import tkFont
@@ -28,6 +29,7 @@
 from distutils.version import StrictVersion
 import os
 import sys
+from functools import partial
 
 if 'PYTHONPATH' in os.environ:
     sys.path = os.environ[ 'PYTHONPATH' ].split( ':' ) + sys.path
@@ -41,7 +43,7 @@
 from mininet.util import custom, customConstructor
 from mininet.term import makeTerm, cleanUpScreens
 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.link import TCLink, Intf, Link
 from mininet.cli import CLI
@@ -76,6 +78,32 @@
           '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 ):
 
     def checkListening( self ):
@@ -440,36 +468,43 @@ def __init__(self, master, title, prefDefaults):
 
         def body(self, master):
             self.rootFrame = master
-            self.leftfieldFrame = Frame(self.rootFrame)
-            self.leftfieldFrame.grid(row=0, column=0, sticky='nswe', columnspan=2)
-            self.rightfieldFrame = Frame(self.rootFrame)
-            self.rightfieldFrame.grid(row=0, column=2, sticky='nswe', columnspan=2)
-
+            n = Notebook(self.rootFrame)
+            self.propFrame = Frame(n)
+            self.vlanFrame = Frame(n)
+            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
-            Label(self.leftfieldFrame, text="Hostname:").grid(row=0, sticky=E)
-            self.hostnameEntry = Entry(self.leftfieldFrame)
+            Label(self.propFrame, text="Hostname:").grid(row=0, sticky=E)
+            self.hostnameEntry = Entry(self.propFrame)
             self.hostnameEntry.grid(row=0, column=1)
             if 'hostname' in self.prefValues:
                 self.hostnameEntry.insert(0, self.prefValues['hostname'])
 
             # Field for Switch IP
-            Label(self.leftfieldFrame, text="IP Address:").grid(row=1, sticky=E)
-            self.ipEntry = Entry(self.leftfieldFrame)
+            Label(self.propFrame, text="IP Address:").grid(row=1, sticky=E)
+            self.ipEntry = Entry(self.propFrame)
             self.ipEntry.grid(row=1, column=1)
             if 'ip' in self.prefValues:
                 self.ipEntry.insert(0, self.prefValues['ip'])
 
             # Field for default route
-            Label(self.leftfieldFrame, text="Default Route:").grid(row=2, sticky=E)
-            self.routeEntry = Entry(self.leftfieldFrame)
+            Label(self.propFrame, text="Default Route:").grid(row=2, sticky=E)
+            self.routeEntry = Entry(self.propFrame)
             self.routeEntry.grid(row=2, column=1)
             if 'defaultRoute' in self.prefValues:
                 self.routeEntry.insert(0, self.prefValues['defaultRoute'])
 
             # Field for CPU
-            Label(self.rightfieldFrame, text="Amount CPU:").grid(row=0, sticky=E)
-            self.cpuEntry = Entry(self.rightfieldFrame)
-            self.cpuEntry.grid(row=0, column=1)
+            Label(self.propFrame, text="Amount CPU:").grid(row=3, sticky=E)
+            self.cpuEntry = Entry(self.propFrame)
+            self.cpuEntry.grid(row=3, column=1)
             if 'cpu' in self.prefValues:
                 self.cpuEntry.insert(0, str(self.prefValues['cpu']))
             # Selection of Scheduler
@@ -477,26 +512,40 @@ def body(self, master):
                 sched =  self.prefValues['sched']
             else:
                 sched = 'host'
-            self.schedVar = StringVar(self.rightfieldFrame)
-            self.schedOption = OptionMenu(self.rightfieldFrame, self.schedVar, "host", "cfs", "rt")
-            self.schedOption.grid(row=0, column=2, sticky=W)
+            self.schedVar = StringVar(self.propFrame)
+            self.schedOption = OptionMenu(self.propFrame, self.schedVar, "host", "cfs", "rt")
+            self.schedOption.grid(row=3, column=2, sticky=W)
             self.schedVar.set(sched)
 
             # Selection of Cores
-            Label(self.rightfieldFrame, text="Cores:").grid(row=1, sticky=E)
-            self.coreEntry = Entry(self.rightfieldFrame)
-            self.coreEntry.grid(row=1, column=1)
+            Label(self.propFrame, text="Cores:").grid(row=4, sticky=E)
+            self.coreEntry = Entry(self.propFrame)
+            self.coreEntry.grid(row=4, column=1)
             if 'cores' in self.prefValues:
                 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
             self.externalInterfaces = 0
-            Label(self.rootFrame, text="External Interface:").grid(row=1, column=0, sticky=E)
-            self.b = Button( self.rootFrame, text='Add', command=self.addInterface)
-            self.b.grid(row=1, column=1)
+            Label(self.interfaceFrame, text="External Interface:").grid(row=0, column=0, sticky=E)
+            self.b = Button( self.interfaceFrame, text='Add', command=self.addInterface)
+            self.b.grid(row=0, column=1)
 
-            self.interfaceFrame = VerticalScrolledTable(self.rootFrame, rows=0, columns=1, title='External Interfaces')
-            self.interfaceFrame.grid(row=2, column=0, sticky='nswe', columnspan=2)
+            self.interfaceFrame = VerticalScrolledTable(self.interfaceFrame, rows=0, columns=1, title='External Interfaces')
+            self.interfaceFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
             self.tableFrame = self.interfaceFrame.interior
             self.tableFrame.addRow(value=['Interface Name'], readonly=True)
 
@@ -508,14 +557,15 @@ def body(self, master):
             for externalInterface in externalInterfaces:
                 self.tableFrame.addRow(value=[externalInterface])
 
+            ### TAB 3
             # VLAN Interfaces
             self.vlanInterfaces = 0
-            Label(self.rootFrame, text="VLAN Interface:").grid(row=1, column=2, sticky=E)
-            self.vlanButton = Button( self.rootFrame, text='Add', command=self.addVlanInterface)
-            self.vlanButton.grid(row=1, column=3)
+            Label(self.vlanFrame, text="VLAN Interface:").grid(row=0, column=0, sticky=E)
+            self.vlanButton = Button( self.vlanFrame, text='Add', command=self.addVlanInterface)
+            self.vlanButton.grid(row=0, column=1)
 
-            self.vlanFrame = VerticalScrolledTable(self.rootFrame, rows=0, columns=2, title='VLAN Interfaces')
-            self.vlanFrame.grid(row=2, column=2, sticky='nswe', columnspan=2)
+            self.vlanFrame = VerticalScrolledTable(self.vlanFrame, rows=0, columns=2, title='VLAN Interfaces')
+            self.vlanFrame.grid(row=1, column=0, sticky='nswe', columnspan=2)
             self.vlanTableFrame = self.vlanFrame.interior
             self.vlanTableFrame.addRow(value=['IP Address','VLAN ID'], readonly=True)
 
@@ -525,22 +575,30 @@ def body(self, master):
             for vlanInterface in vlanInterfaces:
                 self.vlanTableFrame.addRow(value=vlanInterface)
 
-            self.commandFrame = Frame(self.rootFrame)
-            self.commandFrame.grid(row=3, column=0, sticky='nswe', columnspan=4)
-            self.commandFrame.columnconfigure(1, weight=1)
+            ### 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,''])
 
-            # Start command
-            Label(self.commandFrame, text="Start Command:").grid(row=0, sticky=E)
-            self.startEntry = Entry(self.commandFrame)
-            self.startEntry.grid(row=0, column=1, sticky='nswe')
-            if 'startCommand' in self.prefValues:
-                self.startEntry.insert(0, str(self.prefValues['startCommand']))
-            # Stop command
-            Label(self.commandFrame, text="Stop Command:").grid(row=1, sticky=E)
-            self.stopEntry = Entry(self.commandFrame)
-            self.stopEntry.grid(row=1, column=1, sticky='nswe')
-            if 'stopCommand' in self.prefValues:
-                self.stopEntry.insert(0, str(self.prefValues['stopCommand']))
+
+        def addDirectory( self ):
+            self.mountTableFrame.addRow()
 
         def addVlanInterface( self ):
             self.vlanTableFrame.addRow()
@@ -560,6 +618,13 @@ def apply(self):
                     len(self.vlanTableFrame.get(row, 1)) > 0 and
                     row > 0):
                     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(),
                        'cores':self.coreEntry.get(),
@@ -569,6 +634,7 @@ def apply(self):
                        'defaultRoute':self.routeEntry.get(),
                        'startCommand':self.startEntry.get(),
                        'stopCommand':self.stopEntry.get(),
+                       'privateDirectory':privateDirectories,
                        'externalInterfaces':externalInterfaces,
                        'vlanInterfaces':vlanInterfaces}
             self.result = results
@@ -923,6 +989,7 @@ def __init__(self, parent, title, ctrlrDefaults=None):
         def body(self, master):
 
             self.var = StringVar(master)
+            self.protcolvar = StringVar(master)
 
             rowCount=0
             # Field for Hostname
@@ -954,6 +1021,20 @@ def body(self, master):
                 self.var.set("OVS Controller")
             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
             remoteFrame= LabelFrame(master, text='Remote/In-Band Controller', padx=5, pady=5)
             remoteFrame.grid(row=rowCount, column=0, columnspan=2, sticky=W)
@@ -967,14 +1048,11 @@ def body(self, master):
             return self.hostnameEntry # initial focus
 
         def apply(self):
-            hostname = self.hostnameEntry.get()
-            controllerType = self.var.get()
-            remoteIP = self.e1.get()
-            controllerPort = int(self.e2.get())
-            self.result = { 'hostname': hostname,
-                            'remoteIP': remoteIP,
-                            'remotePort': controllerPort}
+            self.result = { 'hostname': self.hostnameEntry.get(),
+                            'remoteIP': self.e1.get(),
+                            'remotePort': int(self.e2.get())}
 
+            controllerType = self.var.get()
             if controllerType == 'Remote Controller':
                 self.result['controllerType'] = 'remote'
             elif controllerType == 'In-Band Controller':
@@ -983,6 +1061,11 @@ def apply(self):
                 self.result['controllerType'] = 'ref'
             else:
                 self.result['controllerType'] = 'ovsc'
+            controllerProtocol = self.protcolvar.get()
+            if controllerProtocol == 'SSL':
+                self.result['controllerProtocol'] = 'ssl'
+            else:
+                self.result['controllerProtocol'] = 'tcp'
 
 class ToolTip(object):
 
@@ -1429,6 +1512,16 @@ def loadTopology( self ):
             x = host['x']
             y = host['y']
             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']
             icon = self.findWidgetByName(hostname)
             icon.bind('<Button-3>', self.do_hostPopup )
@@ -1670,6 +1763,10 @@ def exportScript( self ):
                 if 'Controller' in tags:
                     opts = self.controllers[name]
                     controllerType = opts['controllerType']
+                    if 'controllerProtocol' in opts:
+                        controllerProtocol = opts['controllerProtocol']
+                    else:
+                        controllerProtocol = 'tcp'
                     controllerIP = opts['remoteIP']
                     controllerPort = opts['remotePort']
 
@@ -1687,6 +1784,7 @@ def exportScript( self ):
                     else:
                         f.write("                      controller=Controller,\n")
         
+                    f.write("                      protocol='"+controllerProtocol+"',\n")
                     f.write("                      port="+str(controllerPort)+")\n")
                     f.write("\n")
 
@@ -2070,6 +2168,7 @@ def newNode( self, node, event ):
             name = self.nodePrefixes[ node ] + str( self.controllerCount )
             ctrlr = { 'controllerType': 'ref',
                       'hostname': name,
+                      'controllerProtocol': 'tcp',
                       'remoteIP': '127.0.0.1',
                       'remotePort': 6633}
             self.controllers[name] = ctrlr
@@ -2414,6 +2513,8 @@ def hostDetails( self, _ignore=None ):
                 newHostOpts['externalInterfaces'] = hostBox.result['externalInterfaces']
             if len(hostBox.result['vlanInterfaces']) > 0:
                 newHostOpts['vlanInterfaces'] = hostBox.result['vlanInterfaces']
+            if len(hostBox.result['privateDirectory']) > 0:
+                newHostOpts['privateDirectory'] = hostBox.result['privateDirectory']
             self.hostOpts[name] = newHostOpts
             print 'New host details for ' + name + ' = ' + str(newHostOpts)
 
@@ -2624,11 +2725,11 @@ def buildNodes( self, net):
         for widget in self.widgetToItem:
             name = widget[ 'text' ]
             tags = self.canvas.gettags( self.widgetToItem[ widget ] )
-            print name+' has '+str(tags)
+            #print name+' has '+str(tags)
 
             if 'Switch' in tags:
                 opts = self.switchOpts[name]
-                print str(opts)
+                #print str(opts)
 
                 # Create the correct switch class
                 switchClass = customOvs
@@ -2679,7 +2780,7 @@ def buildNodes( self, net):
                 newSwitch = net.addHost( name , cls=LegacyRouter)
             elif 'Host' in tags:
                 opts = self.hostOpts[name]
-                print str(opts)
+                #print str(opts)
                 ip = None
                 defaultRoute = None
                 if 'defaultRoute' in opts and len(opts['defaultRoute']) > 0:
@@ -2692,9 +2793,18 @@ def buildNodes( self, net):
                     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
+                    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,
                                        cls=hostCls,
                                        ip=ip,
@@ -2722,28 +2832,37 @@ def buildNodes( self, net):
 
                 # Get controller info from panel
                 controllerType = opts['controllerType']
+                if 'controllerProtocol' in opts:
+                    controllerProtocol = opts['controllerProtocol']
+                else:
+                    controllerProtocol = 'tcp'
+                    opts['controllerProtocol'] = 'tcp'
+                controllerIP = opts['remoteIP']
+                controllerPort = opts['remotePort']
 
                 # Make controller
                 print 'Getting controller selection:'+controllerType
-                controllerIP = opts['remoteIP']
-                controllerPort = opts['remotePort']
                 if controllerType == 'remote':
                     net.addController(name=name,
                                       controller=RemoteController,
                                       ip=controllerIP,
+                                      protocol=controllerProtocol,
                                       port=controllerPort)
                 elif controllerType == 'inband':
                     net.addController(name=name,
                                       controller=InbandController,
                                       ip=controllerIP,
+                                      protocol=controllerProtocol,
                                       port=controllerPort)
                 elif controllerType == 'ovsc':
                     net.addController(name=name,
                                       controller=OVSController,
+                                      protocol=controllerProtocol,
                                       port=controllerPort)
                 else:
                     net.addController(name=name,
                                       controller=Controller,
+                                      protocol=controllerProtocol,
                                       port=controllerPort)
 
             else:
@@ -2773,8 +2892,8 @@ def buildLinks( self, net):
                 if linkopts:
                     net.addLink(srcNode, dstNode, cls=TCLink, **linkopts)
                 else:
-                    print str(srcNode)
-                    print str(dstNode)
+                    #print str(srcNode)
+                    #print str(dstNode)
                     net.addLink(srcNode, dstNode)
                 self.canvas.itemconfig(key, dash=())
 
@@ -3128,6 +3247,7 @@ def importTopo( self ):
             icon.bind('<Button-3>', self.do_controllerPopup )
             ctrlr = { 'controllerType': 'ref',
                       'hostname': name,
+                      'controllerProtocol': controller.protocol,
                       'remoteIP': controller.ip,
                       'remotePort': controller.port}
             self.controllers[name] = ctrlr
-- 
GitLab