Compare commits

..

18 Commits

Author SHA1 Message Date
Bob Lantz 1969669f51 pass code check 2018-08-23 13:06:16 -07:00
Bob Lantz c639f342e5 2.3.0d4 2018-08-23 11:43:45 -07:00
Bob Lantz 6e887d0788 Close pty to avoid leak 2018-08-23 11:43:43 -07:00
Bob Lantz 092863f113 2.3.0d3 2018-08-15 23:13:20 -07:00
Bob Lantz 5100a38fcd pmonitor() fixes
pmonitor() is hard to get right, but this seems like
a reasonable improvement:

1. non-blocking I/O so we can drain buffer with impunity
2. drain buffer after poll
3. unregister fd on POLLHUP

Note we may have a unicode splitting problem since we're
decoding chunks of bytes, but that is a problem for another
day I think.
2018-08-02 12:45:35 -07:00
Bob Lantz 3bcecd8e08 Fix popen() to work properly with shell=True 2018-08-02 06:56:18 -07:00
Bob Lantz 486676d617 2.3.0d2 2018-07-26 14:04:08 -07:00
lantz 9e5280b4d1 Python 3 Compatibility (Merge pull request #817 from lantz/py3-compat)
Changes for compatibility with Python 3.

The approach is to make as few changes as possible to maintain compatibility with both Python 2 and Python 3.

We use whatever python is installed, and also support a PYTHON environment variable for installing another version.

For simplicity, we provide mininet.util.pexpect which works out of the box with Python 3 utf-8 strings.

Thanks to @cuihantao for looking at this as well and also for changes to MiniEdit.

Closes #794
2018-07-26 14:03:34 -07:00
Bob Lantz b70eed69d3 Fix typo (50s -> 50ms) 2018-07-26 13:52:15 -07:00
Bob Lantz d96b35694a Use appropriate python version 2018-07-26 13:40:12 -07:00
Bob Lantz c7deeae11c Add sanity check for python mn version 2018-07-26 13:40:12 -07:00
Bob Lantz 323989953b Try to fix pylint errors ;-p 2018-07-26 13:40:12 -07:00
Bob Lantz 17f9756e5c sudo interferes with travis python 3 environment 2018-07-26 13:40:12 -07:00
Bob Lantz 71f3931f2f Remove redundancies in miniedit; pass code check 2018-07-26 13:40:12 -07:00
Bob Lantz 1e9ca5f7fc Fix missing quote in .travis.yml 2018-07-26 13:40:12 -07:00
Bob Lantz 8933c996cb Add python-tk/python3-tk 2018-07-26 13:40:06 -07:00
Bob Lantz afa83cd5ae Restore python 2 compatibility 2018-07-26 13:40:03 -07:00
Hantao Cui 3e81ea7455 miniedit.py changes for Python 3 2018-07-26 13:39:49 -07:00
9 changed files with 55 additions and 54 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
- sudo util/install.sh -n
- PYTHON=`which python` util/install.sh -n
install:
- bash -c "if [ `lsb_release -rs` == '14.04' ]; then make codecheck; fi"
- sudo util/install.sh -fnvw
- pip install pexpect || pip3 install pexpect
- util/install.sh -nfvw
script:
- sudo mn --test pingall
- sudo python mininet/test/runner.py -v -quick
- sudo python examples/test/runner.py -v -quick
- 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
notifications:
email:
on_success: never
# More details: https://docs.travis-ci.com/user/notifications#Configuring-email-notifications
# More details: https://docs.travis-ci.com/user/notifications
+1 -1
View File
@@ -2,7 +2,7 @@
Mininet Installation/Configuration Notes
----------------------------------------
Mininet 2.3.0d1
Mininet 2.3.0d4
---
The supported installation methods for Mininet are 1) using a
+1 -1
View File
@@ -1,4 +1,4 @@
Mininet 2.3.0d1 License
Mininet 2.3.0d4 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.0d1
Mininet 2.3.0d4
[![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
+2 -2
View File
@@ -24,6 +24,7 @@ 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,
@@ -32,11 +33,9 @@ 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,
@@ -48,6 +47,7 @@ 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
+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.0d1"
VERSION = "2.3.0d4"
class Mininet( object ):
"Network emulation with hosts spawned in network namespaces."
+17 -12
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 == True )
self.waitExited = params.get( 'waitExited', Python3 )
# Stash configuration parameters for future reference
self.params = params
@@ -107,6 +107,7 @@ class Node( object ):
self.readbuf = ''
# Start command interpreter shell
self.master, self.slave = None, None # pylint
self.startShell()
self.mountPrivateDirs()
@@ -145,12 +146,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
master, slave = pty.openpty()
self.shell = self._popen( cmd, stdin=slave, stdout=slave, stderr=slave,
close_fds=False )
self.master, self.slave = pty.openpty()
self.shell = self._popen( cmd, stdin=self.slave, stdout=self.slave,
stderr=self.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( master, 'r' )
self.stdin = os.fdopen( self.master, 'r' )
self.stdout = self.stdin
self.pid = self.shell.pid
self.pollOut = select.poll()
@@ -217,9 +218,13 @@ class Node( object ):
# for intfName in self.intfNames():
# if self.name in intfName:
# quietRun( 'ip link del ' + intfName )
if self.waitExited and self.shell:
debug( 'waiting for', self.pid, 'to terminate\n' )
self.shell.wait()
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()
self.shell = None
# Subshell I/O, commands and control
@@ -383,23 +388,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 ].split()
cmd = [ args[ 0 ] ] if shell else 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
+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 > 50s' )
self.assertTrue( delay <= 50, 'Delay > 50ms' )
p.expect( self.prompt )
p.sendline( 'exit' )
p.wait()
+15 -19
View File
@@ -25,7 +25,10 @@ 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"
@@ -413,34 +416,27 @@ def pmonitor(popens, timeoutms=500, readline=True,
for host, popen in popens.items():
fd = popen.stdout.fileno()
fdToHost[ fd ] = host
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 )
poller.register( fd, POLLIN | POLLHUP )
flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
while popens:
fds = poller.poll( timeoutms )
if fds:
for fd, event in fds:
host = fdToHost[ fd ]
popen = popens[ host ]
if event & POLLIN:
line = readit( popen.stdout )
yield host, line
if event & POLLHUP:
if event & POLLIN or event & POLLHUP:
while True:
# Drain buffer
line = readit( popen.stdout )
yield host, line
try:
f = popen.stdout
line = decode( f.readline() if readline
else f.read( readmax ) )
except IOError:
line = ''
if line == '':
break
yield host, line
if event & POLLHUP:
poller.unregister( fd )
del popens[ host ]
else: