Compare commits

..

3 Commits

Author SHA1 Message Date
Bob Lantz 547b91cb11 Add python-tk/python3-tkk 2018-07-25 21:39:48 -07:00
Bob Lantz 55f4eb7e94 Restore python 2 compatibility 2018-07-25 21:32:09 -07:00
Hantao Cui 4e507fb01f mininedit.py changes for Python 3 compatibility 2018-07-25 21:30:06 -07:00
20 changed files with 84 additions and 137 deletions
+15 -15
View File
@@ -1,35 +1,35 @@
language: python
sudo: required
python:
- "2.7
- "3.6"
matrix:
include:
- dist: trusty
python: 2.7
env: dist="14.04 LTS trusty"
- dist: trusty
python: 3.6
env: dist="14.04 LTS trusty"
# - dist: xenial
# env: dist="16.04 LTS xenial"
# Travis-CI only proposes 14.04 LTS Trusty and there is no plan to update to 16.04 xenial
# (c.f. https://github.com/travis-ci/travis-ci/issues/5821)
# It is useless to add a second job because it will run in the same Ubuntu version (14.04)
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq vlan
- PYTHON=`which python` util/install.sh -n
- sudo util/install.sh -n
install:
- bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi"
- pip install pexpect || pip3 install pexpect
- util/install.sh -nfvw
- sudo util/install.sh -fnvw
script:
- alias sudo="sudo env PATH=$PATH"
- export PYTHON=`which python`
- echo 'px import sys; print(sys.version_info)' | sudo $PYTHON bin/mn -v output
- sudo $PYTHON bin/mn --test pingall
- sudo $PYTHON mininet/test/runner.py -v -quick
- sudo $PYTHON examples/test/runner.py -v -quick
- sudo mn --test pingall
- sudo python mininet/test/runner.py -v -quick
- sudo python examples/test/runner.py -v -quick
notifications:
email:
on_success: never
# More details: https://docs.travis-ci.com/user/notifications
# More details: https://docs.travis-ci.com/user/notifications#Configuring-email-notifications
+1 -1
View File
@@ -2,7 +2,7 @@
Mininet Installation/Configuration Notes
----------------------------------------
Mininet 2.3.0d4
Mininet 2.3.0d1
---
The supported installation methods for Mininet are 1) using a
+1 -1
View File
@@ -1,4 +1,4 @@
Mininet 2.3.0d4 License
Mininet 2.3.0d1 License
Copyright (c) 2013-2018 Open Networking Laboratory
Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
+2 -2
View File
@@ -2,7 +2,7 @@ Mininet: Rapid Prototyping for Software Defined Networks
========================================================
*The best way to emulate almost any network on your laptop!*
Mininet 2.3.0d4
Mininet 2.3.0d1
[![Build Status][1]](https://travis-ci.org/mininet/mininet)
@@ -126,7 +126,7 @@ hard work that Mininet continues to grow and improve.
Best wishes, and we look forward to seeing what you can do with
Mininet to change the networking world!
Bob Lantz
Bob Lantz
Mininet Core Team
[1]: https://travis-ci.org/mininet/mininet.svg?branch=master
+4 -1
View File
@@ -13,9 +13,12 @@ from mininet.topo import Topo
class MyTopo( Topo ):
"Simple topology example."
def build( self ):
def __init__( self ):
"Create custom topo."
# Initialize topology
Topo.__init__( self )
# Add hosts and switches
leftHost = self.addHost( 'h1' )
rightHost = self.addHost( 'h2' )
+5 -20
View File
@@ -843,26 +843,11 @@ class MininetCluster( Mininet ):
def addController( self, *args, **kwargs ):
"Patch to update IP address to global IP address"
controller = Mininet.addController( self, *args, **kwargs )
loopback = '127.0.0.1'
if ( not isinstance( controller, Controller ) or
controller.IP() != loopback ):
return
# Find route to a different server IP address
serverIPs = [ ip for ip in self.serverIP.values()
if ip is not controller.IP() ]
if not serverIPs:
return # no remote servers - loopback is fine
remoteIP = serverIPs[ 0 ]
# Route should contain 'dev <intfname>'
route = controller.cmd( 'ip route get', remoteIP,
r'| egrep -o "dev\s[^[:space:]]+"' )
if not route:
raise Exception('addController: no route from', controller,
'to', remoteIP )
intf = route.split()[ 1 ].strip()
debug( 'adding', intf, 'to', controller )
Intf( intf, node=controller ).updateIP()
debug( controller, 'IP address updated to', controller.IP() )
# Update IP address for controller that may not be local
if ( isinstance( controller, Controller)
and controller.IP() == '127.0.0.1'
and ' eth0:' in controller.cmd( 'ip link show' ) ):
Intf( 'eth0', node=controller ).updateIP()
return controller
def buildFromTopo( self, *args, **kwargs ):
+2 -2
View File
@@ -30,7 +30,7 @@ class ClusterCLI( CLI ):
global nx, plt, graphviz_layout
if not nx:
try:
# pylint: disable=import-error,no-member
# pylint: disable=import-error
import networkx
nx = networkx # satisfy pylint
from matplotlib import pyplot
@@ -42,7 +42,7 @@ class ClusterCLI( CLI ):
graphviz_layout = nx.graphviz_layout
else:
graphviz_layout = nx.drawing.nx_agraph.graphviz_layout
# pylint: enable=import-error,no-member
# pylint: enable=import-error
except ImportError:
error( 'plot requires networkx, matplotlib and pygraphviz - '
'please install them and try again\n' )
+2 -1
View File
@@ -100,9 +100,10 @@ class MininetFacade( object ):
class ControlNetwork( Topo ):
"Control Network Topology"
def build( self, n, dataController=DataController, **_kwargs ):
def __init__( self, n, dataController=DataController, **kwargs ):
"""n: number of data network controller nodes
dataController: class for data network controllers"""
Topo.__init__( self, **kwargs )
# Connect everything to a single switch
cs0 = self.addSwitch( 'cs0' )
# Add hosts which will serve as data network controllers
+5 -1
View File
@@ -38,7 +38,11 @@ flush = sys.stdout.flush
class LinearTestTopo( Topo ):
"Topology for a string of N hosts and N-1 switches."
def build( self, N, **params ):
def __init__( self, N, **params ):
# Initialize topology
Topo.__init__( self, **params )
# Create switches and hosts
hosts = [ self.addHost( 'h%s' % h )
for h in irange( 1, N ) ]
+2 -2
View File
@@ -24,7 +24,6 @@ import sys
from optparse import OptionParser
from subprocess import call
# pylint: disable=import-error
if sys.version_info[0] == 2:
from Tkinter import ( Frame, Label, LabelFrame, Entry, OptionMenu,
Checkbutton, Menu, Toplevel, Button, BitmapImage,
@@ -33,9 +32,11 @@ if sys.version_info[0] == 2:
CENTER, RIGHT, LEFT, BOTH, TRUE, FALSE )
from ttk import Notebook
from tkMessageBox import showerror
from subprocess import call
import tkFont
import tkFileDialog
import tkSimpleDialog
import tkFileDialog
else:
from tkinter import ( Frame, Label, LabelFrame, Entry, OptionMenu,
Checkbutton, Menu, Toplevel, Button, BitmapImage,
@@ -47,7 +48,6 @@ else:
from tkinter import font as tkFont
from tkinter import simpledialog as tkSimpleDialog
from tkinter import filedialog as tkFileDialog
# pylint: enable=import-error
import re
import json
+3 -1
View File
@@ -21,7 +21,9 @@ def runMultiLink():
class simpleMultiLinkTopo( Topo ):
"Simple topology with multiple links"
def build( self, n, **_kwargs ):
def __init__( self, n, **kwargs ):
Topo.__init__( self, **kwargs )
h1, h2 = self.addHost( 'h1' ), self.addHost( 'h2' )
s1 = self.addSwitch( 's1' )
+3 -1
View File
@@ -27,7 +27,9 @@ from mininet.util import irange
class InternetTopo(Topo):
"Single switch connected to n hosts."
def build(self, n=2, **_kwargs ):
def __init__(self, n=2, **opts):
Topo.__init__(self, **opts)
# set up inet switch
inetSwitch = self.addSwitch('s0')
# add inet host
-9
View File
@@ -29,8 +29,6 @@ from subprocess import call
from cmd import Cmd
from os import isatty
from select import poll, POLLIN
import select
import errno
import sys
import time
import os
@@ -461,13 +459,6 @@ class CLI( Cmd ):
# it's possible to interrupt ourselves after we've
# read data but before it has been printed.
node.sendInt()
except select.error as e:
# pylint: disable=unpacking-non-sequence
errno_, errmsg = e.args
# pylint: enable=unpacking-non-sequence
if errno_ != errno.EINTR:
error( "select.error: %d, %s" % (errno_, errmsg) )
node.sendInt()
def precmd( self, line ):
"allow for comments in the cli"
-3
View File
@@ -146,9 +146,6 @@ class Intf( object ):
def rename( self, newname ):
"Rename interface"
if self.node and self.name in self.node.nameToIntf:
# rename intf in node's nameToIntf
self.node.nameToIntf[newname] = self.node.nameToIntf.pop(self.name)
self.ifconfig( 'down' )
result = self.cmd( 'ip link set', self.name, 'name', newname )
self.name = newname
+1 -1
View File
@@ -108,7 +108,7 @@ from mininet.util import ( quietRun, fixLimits, numCores, ensureRoot,
from mininet.term import cleanUpScreens, makeTerms
# Mininet version: should be consistent with README and LICENSE
VERSION = "2.3.0d4"
VERSION = "2.3.0d1"
class Mininet( object ):
"Network emulation with hosts spawned in network namespaces."
+12 -17
View File
@@ -89,7 +89,7 @@ class Node( object ):
self.inNamespace = params.get( 'inNamespace', inNamespace )
# Python 3 complains if we don't wait for shell exit
self.waitExited = params.get( 'waitExited', Python3 )
self.waitExited = params.get( 'waitExited', Python3 == True )
# Stash configuration parameters for future reference
self.params = params
@@ -107,7 +107,6 @@ class Node( object ):
self.readbuf = ''
# Start command interpreter shell
self.master, self.slave = None, None # pylint
self.startShell()
self.mountPrivateDirs()
@@ -146,12 +145,12 @@ class Node( object ):
# Spawn a shell subprocess in a pseudo-tty, to disable buffering
# in the subprocess and insulate it from signals (e.g. SIGINT)
# received by the parent
self.master, self.slave = pty.openpty()
self.shell = self._popen( cmd, stdin=self.slave, stdout=self.slave,
stderr=self.slave, close_fds=False )
master, slave = pty.openpty()
self.shell = self._popen( cmd, stdin=slave, stdout=slave, stderr=slave,
close_fds=False )
# XXX BL: This doesn't seem right, and we should also probably
# close our files when we exit...
self.stdin = os.fdopen( self.master, 'r' )
self.stdin = os.fdopen( master, 'r' )
self.stdout = self.stdin
self.pid = self.shell.pid
self.pollOut = select.poll()
@@ -218,13 +217,9 @@ class Node( object ):
# for intfName in self.intfNames():
# if self.name in intfName:
# quietRun( 'ip link del ' + intfName )
if self.shell:
# Close ptys
self.stdin.close()
os.close(self.slave)
if self.waitExited:
debug( 'waiting for', self.pid, 'to terminate\n' )
self.shell.wait()
if self.waitExited and self.shell:
debug( 'waiting for', self.pid, 'to terminate\n' )
self.shell.wait()
self.shell = None
# Subshell I/O, commands and control
@@ -388,23 +383,23 @@ class Node( object ):
'mncmd':
[ 'mnexec', '-da', str( self.pid ) ] }
defaults.update( kwargs )
shell = defaults.pop( 'shell', False )
if len( args ) == 1:
if isinstance( args[ 0 ], list ):
# popen([cmd, arg1, arg2...])
cmd = args[ 0 ]
elif isinstance( args[ 0 ], BaseString ):
# popen("cmd arg1 arg2...")
cmd = [ args[ 0 ] ] if shell else args[ 0 ].split()
cmd = args[ 0 ].split()
else:
raise Exception( 'popen() requires a string or list' )
elif len( args ) > 0:
# popen( cmd, arg1, arg2... )
cmd = list( args )
if shell:
cmd = [ os.environ[ 'SHELL' ], '-c' ] + [ ' '.join( cmd ) ]
# Attach to our namespace using mnexec -a
cmd = defaults.pop( 'mncmd' ) + cmd
# Shell requires a string, not a list!
if defaults.get( 'shell', False ):
cmd = ' '.join( cmd )
popen = self._popen( cmd, **defaults )
return popen
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env python
"""
Regression test for pty leak in Node()
"""
import unittest
from mininet.net import Mininet
from mininet.clean import cleanup
from mininet.topo import SingleSwitchTopo
class TestPtyLeak( unittest.TestCase ):
"Verify that there is no pty leakage"
@staticmethod
def testPtyLeak():
"Test for pty leakage"
net = Mininet( SingleSwitchTopo() )
net.start()
host = net[ 'h1' ]
for _ in range( 0, 10 ):
oldptys = host.slave, host.master
net.delHost( host )
host = net.addHost( 'h1' )
assert ( host.slave, host.master ) == oldptys
net.stop()
if __name__ == '__main__':
unittest.main()
cleanup()
+1 -1
View File
@@ -228,7 +228,7 @@ class testWalkthrough( unittest.TestCase ):
r'([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+) ms' )
delay = float( p.match.group( 2 ) )
self.assertTrue( delay >= 40, 'Delay < 40ms' )
self.assertTrue( delay <= 50, 'Delay > 50ms' )
self.assertTrue( delay <= 50, 'Delay > 50s' )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
+21 -17
View File
@@ -25,10 +25,7 @@ def encode( s ):
"Encode a byte string if needed for Python 3"
return s.encode( Encoding ) if Python3 else s
try:
# pylint: disable=import-error
oldpexpect = None
import pexpect as oldpexpect
# pylint: enable=import-error
class Pexpect( object ):
"Custom pexpect that is compatible with str"
@@ -66,7 +63,7 @@ def oldQuietRun( *cmd ):
cmd: list of command params"""
if len( cmd ) == 1:
cmd = cmd[ 0 ]
if isinstance( cmd, BaseString ):
if isinstance( cmd, str ):
cmd = cmd.split( ' ' )
popen = Popen( cmd, stdout=PIPE, stderr=STDOUT )
# We can't use Popen.communicate() because it uses
@@ -107,7 +104,7 @@ def errRun( *cmd, **kwargs ):
if len( cmd ) == 1:
cmd = cmd[ 0 ]
# Allow passing in a list or a string
if isinstance( cmd, BaseString ) and not shell:
if isinstance( cmd, str ) and not shell:
cmd = cmd.split( ' ' )
cmd = [ str( arg ) for arg in cmd ]
elif isinstance( cmd, list ) and shell:
@@ -416,27 +413,34 @@ def pmonitor(popens, timeoutms=500, readline=True,
for host, popen in popens.items():
fd = popen.stdout.fileno()
fdToHost[ fd ] = host
poller.register( fd, POLLIN | POLLHUP )
flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
poller.register( fd, POLLIN )
if not readline:
# Use non-blocking reads
flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
def readit( f ):
"Helper function - read line or data"
# Note this will block if readline is True
line = f.readline() if readline else f.read( readmax )
return decode( line )
while popens:
fds = poller.poll( timeoutms )
if fds:
for fd, event in fds:
host = fdToHost[ fd ]
popen = popens[ host ]
if event & POLLIN or event & POLLHUP:
if event & POLLIN:
line = readit( popen.stdout )
yield host, line
if event & POLLHUP:
while True:
try:
f = popen.stdout
line = decode( f.readline() if readline
else f.read( readmax ) )
except IOError:
line = ''
# Drain buffer
line = readit( popen.stdout )
yield host, line
if line == '':
break
yield host, line
if event & POLLHUP:
poller.unregister( fd )
del popens[ host ]
else:
+4 -10
View File
@@ -159,10 +159,9 @@ function mn_deps {
ethtool help2man python-pyflakes python3-pylint \
python-pep8 ${PYPKG}-pexpect ${PYPKG}-tk
else # Debian/Ubuntu
$install gcc make socat psmisc xterm ssh iperf telnet \
$install gcc make socat psmisc xterm ssh iperf iproute2 telnet \
cgroup-bin ethtool help2man pyflakes pylint pep8 \
${PYPKG}-setuptools ${PYPKG}-pexpect ${PYPKG}-tk
$install iproute2 || $install iproute
fi
echo "Installing Mininet core"
@@ -347,20 +346,15 @@ function ubuntuOvs {
cd $BUILD_DIR/openvswitch/openvswitch-$OVS_RELEASE
DEB_BUILD_OPTIONS='parallel=$parallel nocheck' fakeroot debian/rules binary
cd ..
# Install packages
if [ -e libopenvswitch_$OVS_RELEASE*.deb ]; then
$pkginst libopenvswitch_$OVS_RELEASE*.deb 2>/dev/null
fi
for pkg in common datapath-dkms pki switch; do
pkg=openvswitch-${pkg}_$OVS_RELEASE*.deb
echo "Installing $pkg"
$pkginst $pkg
done
if [ -e openvswitch-controller_$OVS_RELEASE*.deb ]; then
$pkginst openvswitch-controller_$OVS_RELEASE*.deb 2>/dev/null
if $pkginst openvswitch-controller_$OVS_RELEASE*.deb 2>/dev/null; then
echo "Ignoring error installing openvswitch-controller"
fi
# Ubuntu/Debian will mask a service if you uninstall it
sudo systemctl unmask openvswitch-switch || true
/sbin/modinfo openvswitch
sudo ovs-vsctl show
# Switch can run on its own, but