From 53e9c1215480f22295306943523150a6aedd5aaf Mon Sep 17 00:00:00 2001 From: Arthur Valadares Date: Tue, 21 Feb 2017 23:55:30 -0800 Subject: [PATCH 1/3] makes miniNExT compatible to mininet 2.3.0 --- examples/quagga-ixp/topo.py | 6 ++---- mininext/node.py | 30 ++++++++++++++++++++---------- mininext/topo.py | 5 +++-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/examples/quagga-ixp/topo.py b/examples/quagga-ixp/topo.py index 77b20e3..4aab81c 100644 --- a/examples/quagga-ixp/topo.py +++ b/examples/quagga-ixp/topo.py @@ -17,12 +17,10 @@ class QuaggaTopo(Topo): "Creates a topology of Quagga routers" - def __init__(self): + def build(self): """Initialize a Quagga topology with 5 routers, configure their IP addresses, loop back interfaces, and paths to their private configuration directories.""" - Topo.__init__(self) - # Directory where this file / script is located" selfPath = os.path.dirname(os.path.abspath( inspect.getfile(inspect.currentframe()))) # script directory @@ -74,4 +72,4 @@ def __init__(self): nodeConfig=quaggaSvcConfig) # Attach the quaggaContainer to the IXP Fabric Switch - self.addLink(quaggaContainer, ixpfabric) + self.addLink(quaggaContainer, ixpfabric, fast=False) diff --git a/mininext/node.py b/mininext/node.py index 10b5ef9..bd358b8 100644 --- a/mininext/node.py +++ b/mininext/node.py @@ -6,6 +6,8 @@ import select import shutil import tempfile +import pty +import os from subprocess import Popen, PIPE, STDOUT from mininet.node import Node as BaseNode @@ -50,7 +52,7 @@ def __init__(self, name, inMountNamespace=False, inPIDNamespace=False, self.loIntfs = {} # Request initialization of the BaseNode - BaseNode.__init__(self, name, **params) + BaseNode.__init__(self, name, inUTSNamespace, **params) # Overrides to support additional extensions # @@ -75,11 +77,13 @@ def startShell(self): opts += 'u' # bash -m: enable job control # -s: pass $* to shell, and make process easy to find in ps - cmd = ['mxexec', opts, 'bash', '-ms', 'mininet:' + self.name] - self.shell = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT, + cmd = [ 'mxexec', opts, 'env', 'PS1=' + chr( 127 ), + 'bash', '--norc', '-is', 'mininet:' + self.name ] + master, slave = pty.openpty() + self.shell = Popen(cmd, stdin=slave, stdout=slave, stderr=slave, close_fds=True) - self.stdin = self.shell.stdin - self.stdout = self.shell.stdout + self.stdin = os.fdopen( master, 'rw') + self.stdout = self.stdin self.pid = self.shell.pid self.pollOut = select.poll() self.pollOut.register(self.stdout) @@ -92,17 +96,25 @@ def startShell(self): self.lastCmd = None self.lastPid = None self.readbuf = '' - self.waiting = False - # If this node has a private PID space, grab the PID to attach to # Otherwise, we use the same PID as the shell's PID if self.inPIDNamespace: # monitor() will grab shell's true PID and put in self.lastPid - self.monitor() + self.monitor(1000) if self.lastPid is None: raise Exception('Unable to determine shell\'s PID') self.pid = self.lastPid self.lastPid = None + # Wait for prompt + while True: + data = self.read( 1024 ) + if data[ -1 ] == chr( 127 ): + break + self.pollOut.poll() + self.waiting = False + self.cmd( 'stty -echo' ) + self.cmd( 'set +m' ) + # Override on popen() to support mount and PID namespaces def popen(self, *args, **kwargs): @@ -440,5 +452,3 @@ def hasPrivateMount(self, target): class Host(Node): - "MiniNExT enabled host" - pass diff --git a/mininext/topo.py b/mininext/topo.py index 177e215..53635bf 100644 --- a/mininext/topo.py +++ b/mininext/topo.py @@ -17,7 +17,7 @@ def __init__(self, nopts=None, **opts): BaseTopo.__init__(self, **opts) # Override addHost so that constructor defaults to MiniNExT host - def addHost(self, name, cls=Host, **opts): + def addHost(self, name, **opts): """Adds a host using the MiniNExT host constructor. name: host name cls: host constructor @@ -25,7 +25,8 @@ def addHost(self, name, cls=Host, **opts): returns: host name""" if not opts and self.hopts: opts = self.hopts - return BaseTopo.addNode(self, name, cls=cls, **opts) + opts['cls'] = Host + return BaseTopo.addNode(self, name, **opts) # Configure a loopback interface def addNodeLoopbackIntf(self, node, ip, loNum=None, **opts): From 9c031b5c3febb5c744e26ed4c4266c238960b0de Mon Sep 17 00:00:00 2001 From: Arthur Valadares Date: Fri, 24 Feb 2017 15:28:03 -0800 Subject: [PATCH 2/3] accidentally deleted Host lines --- mininext/node.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mininext/node.py b/mininext/node.py index bd358b8..91d0dd0 100644 --- a/mininext/node.py +++ b/mininext/node.py @@ -451,4 +451,5 @@ def hasPrivateMount(self, target): class Host(Node): - + "MiniNExT enabled host" + pass From 73d27048e168178865bc444bf881c8e94bcbc437 Mon Sep 17 00:00:00 2001 From: Arthur Valadares Date: Tue, 28 Feb 2017 10:32:43 -0800 Subject: [PATCH 3/3] addresses pull request comments --- examples/quagga-ixp/topo.py | 4 ++++ mininext/node.py | 7 +++---- mininext/topo.py | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/quagga-ixp/topo.py b/examples/quagga-ixp/topo.py index 4aab81c..1b0f58c 100644 --- a/examples/quagga-ixp/topo.py +++ b/examples/quagga-ixp/topo.py @@ -72,4 +72,8 @@ def build(self): nodeConfig=quaggaSvcConfig) # Attach the quaggaContainer to the IXP Fabric Switch + # NOTE: needs the fast=False parameter to work on mininet > 2.2 + # The fast path in mininet passes namens to ip instead of + # bringing up the interfaces and moving them to namespaces. + # That approach fails when processes are in separate PID ns self.addLink(quaggaContainer, ixpfabric, fast=False) diff --git a/mininext/node.py b/mininext/node.py index bd358b8..53a5fc2 100644 --- a/mininext/node.py +++ b/mininext/node.py @@ -81,7 +81,7 @@ def startShell(self): 'bash', '--norc', '-is', 'mininet:' + self.name ] master, slave = pty.openpty() self.shell = Popen(cmd, stdin=slave, stdout=slave, stderr=slave, - close_fds=True) + close_fds=False) self.stdin = os.fdopen( master, 'rw') self.stdout = self.stdin self.pid = self.shell.pid @@ -112,9 +112,8 @@ def startShell(self): break self.pollOut.poll() self.waiting = False - self.cmd( 'stty -echo' ) - self.cmd( 'set +m' ) - + # +m: disable job control notification + self.cmd( 'unset HISTFILE; stty -echo; set +m' ) # Override on popen() to support mount and PID namespaces def popen(self, *args, **kwargs): diff --git a/mininext/topo.py b/mininext/topo.py index 53635bf..fea4175 100644 --- a/mininext/topo.py +++ b/mininext/topo.py @@ -25,7 +25,8 @@ def addHost(self, name, **opts): returns: host name""" if not opts and self.hopts: opts = self.hopts - opts['cls'] = Host + if 'cls' not in opts: + opts['cls'] = Host return BaseTopo.addNode(self, name, **opts) # Configure a loopback interface