Fixed bmv2.py assigning gRPC/Thrift port already in use
Also handle Mininet exceptions by shutting down all BMv2 instances
Change-Id: I5a8d1a06441daa57c5dd3b0861f1b7484828174a
diff --git a/tools/dev/mininet/bmv2.py b/tools/dev/mininet/bmv2.py
index 08effd0..b6ac2f6 100644
--- a/tools/dev/mininet/bmv2.py
+++ b/tools/dev/mininet/bmv2.py
@@ -1,3 +1,4 @@
+import multiprocessing
import os
import socket
import re
@@ -41,6 +42,9 @@
def watchDog(sw):
while True:
+ if ONOSBmv2Switch.mininet_exception == 1:
+ sw.killBmv2(log=False)
+ return
if sw.stopped:
return
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
@@ -72,6 +76,11 @@
class ONOSBmv2Switch(Switch):
"""BMv2 software switch with gRPC server"""
+ # Shared value used to notify to all instances of this class that a Mininet
+ # exception occurred. Mininet exception handling doesn't call the stop()
+ # method, so the mn process would hang after clean-up since Bmv2 would still
+ # be running.
+ mininet_exception = multiprocessing.Value('i', 0)
def __init__(self, name, json=None, debugger=False, loglevel="warn",
elogger=False, grpcport=None, cpuport=255,
@@ -79,8 +88,8 @@
pktdump=False, valgrind=False, gnmi=False,
portcfg=True, onosdevid=None, **kwargs):
Switch.__init__(self, name, **kwargs)
- self.grpcPort = pickUnusedPort() if not grpcport else grpcport
- self.thriftPort = pickUnusedPort() if not thriftport else thriftport
+ self.grpcPort = grpcport
+ self.thriftPort = thriftport
self.cpuPort = cpuport
self.json = json
self.debugger = parseBoolean(debugger)
@@ -111,9 +120,6 @@
# Remove files from previous executions
self.cleanupTmpFiles()
- writeToFile("/tmp/bmv2-%s-grpc-port" % self.name, self.grpcPort)
- writeToFile("/tmp/bmv2-%s-thrift-port" % self.name, self.thriftPort)
-
def getSourceIp(self, dstIP):
"""
Queries the Linux routing table to get the source IP that can talk with
@@ -226,6 +232,9 @@
info("\nStarting BMv2 target: %s\n" % cmdString)
+ writeToFile("/tmp/bmv2-%s-grpc-port" % self.name, self.grpcPort)
+ writeToFile("/tmp/bmv2-%s-thrift-port" % self.name, self.thriftPort)
+
try:
if not self.dryrun:
# Start the switch
@@ -238,12 +247,17 @@
threading.Thread(target=watchDog, args=[self]).start()
self.doOnosNetcfg(self.controllerIp(controllers))
- except Exception as ex:
+ except Exception:
+ ONOSBmv2Switch.mininet_exception = 1
self.killBmv2()
self.printBmv2Log()
- raise ex
+ raise
def grpcTargetArgs(self):
+ if self.grpcPort is None:
+ self.grpcPort = pickUnusedPort()
+ if self.thriftPort is None:
+ self.thriftPort = pickUnusedPort()
args = ['--device-id %s' % str(BMV2_DEFAULT_DEVICE_ID)]
for port, intf in self.intfs.items():
if not intf.IP():
@@ -284,7 +298,7 @@
break
# Port is not open yet. If there is time, we wait a bit.
if endtime > time.time():
- time.sleep(0.2)
+ time.sleep(0.1)
else:
# Time's up.
raise Exception("Switch did not start before timeout")