Sync bmv2.py mininet files with onos branch.

Change-Id: I481ce415f88cbdfaaf7b6b060bc3f466e35ac86e
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index 313d9b6..687f915 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -64,7 +64,7 @@
             else:
                 main.useBmv2 = False
             main.configPath = main.path + ( "/.." if main.useCommonConf else "" ) + "/dependencies/"
-            main.bmv2Path = main.path + "/../dependencies/"
+            main.bmv2Path = "/tools/dev/mininet/"
             main.forJson = "json/"
             main.forChart = "chart/"
             main.forConfig = "conf/"
@@ -207,7 +207,7 @@
                                                                 "~/",
                                                                 direction="to" )
         copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
-                                                        main.bmv2Path + main.bmv2,
+                                                        main.ONOSbench.home + main.bmv2Path + main.bmv2,
                                                         main.Mininet1.home + "custom",
                                                         direction="to" )
         stepResult = copyResult
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/bmv2.py b/TestON/tests/USECASE/SegmentRouting/dependencies/bmv2.py
deleted file mode 100644
index eafb482..0000000
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/bmv2.py
+++ /dev/null
@@ -1,353 +0,0 @@
-import json
-import multiprocessing
-import os
-import random
-import re
-import socket
-import threading
-import urllib2
-from contextlib import closing
-
-import time
-from mininet.log import info, warn
-from mininet.node import Switch, Host
-
-SIMPLE_SWITCH_GRPC = 'simple_switch_grpc'
-PKT_BYTES_TO_DUMP = 80
-VALGRIND_PREFIX = 'valgrind --leak-check=yes'
-SWITCH_START_TIMEOUT = 5  # seconds
-BMV2_LOG_LINES = 5
-BMV2_DEFAULT_DEVICE_ID = 1
-
-
-def parseBoolean(value):
-    if value in ['1', 1, 'true', 'True']:
-        return True
-    else:
-        return False
-
-
-def pickUnusedPort():
-    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    s.bind(('localhost', 0))
-    addr, port = s.getsockname()
-    s.close()
-    return port
-
-
-def writeToFile(path, value):
-    with open(path, "w") as f:
-        f.write(str(value))
-
-
-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:
-            if s.connect_ex(('127.0.0.1', sw.grpcPort)) == 0:
-                time.sleep(1)
-            else:
-                warn("\n*** WARN: BMv2 instance %s died!\n" % sw.name)
-                sw.printBmv2Log()
-                print ("-" * 80) + "\n"
-                return
-
-
-class ONOSHost(Host):
-    def __init__(self, name, inNamespace=True, **params):
-        Host.__init__(self, name, inNamespace=inNamespace, **params)
-
-    def config(self, **params):
-        r = super(Host, self).config(**params)
-        for off in ["rx", "tx", "sg"]:
-            cmd = "/sbin/ethtool --offload %s %s off" \
-                  % (self.defaultIntf(), off)
-            self.cmd(cmd)
-        # disable IPv6
-        self.cmd("sysctl -w net.ipv6.conf.all.disable_ipv6=1")
-        self.cmd("sysctl -w net.ipv6.conf.default.disable_ipv6=1")
-        self.cmd("sysctl -w net.ipv6.conf.lo.disable_ipv6=1")
-        return r
-
-
-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, notifications=False,
-                 thriftport=None, netcfg=True, dryrun=False, pipeconf="",
-                 pktdump=False, valgrind=False, gnmi=False,
-                 portcfg=True, onosdevid=None, **kwargs):
-        Switch.__init__(self, name, **kwargs)
-        self.grpcPort = grpcport
-        self.thriftPort = thriftport
-        self.cpuPort = cpuport
-        self.json = json
-        self.debugger = parseBoolean(debugger)
-        self.notifications = parseBoolean(notifications)
-        self.loglevel = loglevel
-        # Important: Mininet removes all /tmp/*.log files in case of exceptions.
-        # We want to be able to see the bmv2 log if anything goes wrong, hence
-        # avoid the .log extension.
-        self.logfile = '/tmp/bmv2-%s-log' % self.name
-        self.elogger = parseBoolean(elogger)
-        self.pktdump = parseBoolean(pktdump)
-        self.netcfg = parseBoolean(netcfg)
-        self.dryrun = parseBoolean(dryrun)
-        self.valgrind = parseBoolean(valgrind)
-        self.netcfgfile = '/tmp/bmv2-%s-netcfg.json' % self.name
-        self.pipeconfId = pipeconf
-        self.injectPorts = parseBoolean(portcfg)
-        self.withGnmi = parseBoolean(gnmi)
-        self.longitude = kwargs['longitude'] if 'longitude' in kwargs else None
-        self.latitude = kwargs['latitude'] if 'latitude' in kwargs else None
-        if onosdevid is not None and len(onosdevid) > 0:
-            self.onosDeviceId = onosdevid
-        else:
-            self.onosDeviceId = "device:bmv2:%s" % self.name
-        self.logfd = None
-        self.bmv2popen = None
-        self.stopped = False
-
-        # Remove files from previous executions
-        self.cleanupTmpFiles()
-
-    def getSourceIp(self, dstIP):
-        """
-        Queries the Linux routing table to get the source IP that can talk with
-        dstIP, and vice versa.
-        """
-        ipRouteOut = self.cmd('ip route get %s' % dstIP)
-        r = re.search(r"src (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", ipRouteOut)
-        return r.group(1) if r else None
-
-    def getDeviceConfig(self, srcIP):
-
-        basicCfg = {
-            "driver": "bmv2"
-        }
-
-        if self.longitude and self.latitude:
-            basicCfg["longitude"] = self.longitude
-            basicCfg["latitude"] = self.latitude
-
-        cfgData = {
-            "generalprovider": {
-                "p4runtime": {
-                    "ip": srcIP,
-                    "port": self.grpcPort,
-                    "deviceId": BMV2_DEFAULT_DEVICE_ID,
-                    "deviceKeyId": "p4runtime:%s" % self.onosDeviceId
-                },
-                "bmv2-thrift": {
-                    "ip": srcIP,
-                    "port": self.thriftPort
-                }
-            },
-            "piPipeconf": {
-                "piPipeconfId": self.pipeconfId
-            },
-            "basic": basicCfg
-        }
-
-        if self.withGnmi:
-            cfgData["generalprovider"]["gnmi"] = {
-                "ip": srcIP,
-                "port": self.grpcPort
-            }
-
-        if self.injectPorts:
-            portData = {}
-            portId = 1
-            for intfName in self.intfNames():
-                if intfName == 'lo':
-                    continue
-                portData[str(portId)] = {
-                    "number": portId,
-                    "name": intfName,
-                    "enabled": True,
-                    "removed": False,
-                    "type": "copper",
-                    "speed": 10000
-                }
-                portId += 1
-
-            cfgData['ports'] = portData
-
-        return cfgData
-
-    def doOnosNetcfg(self, controllerIP):
-        """
-        Notifies ONOS about the new device via Netcfg.
-        """
-        srcIP = self.getSourceIp(controllerIP)
-        if not srcIP:
-            warn("*** WARN: unable to get switch IP address, won't do netcfg\n")
-            return
-
-        cfgData = {
-            "devices": {
-                self.onosDeviceId: self.getDeviceConfig(srcIP)
-            }
-        }
-        with open(self.netcfgfile, 'w') as fp:
-            json.dump(cfgData, fp, indent=4)
-
-        if not self.netcfg:
-            # Do not push config to ONOS.
-            return
-
-        # Build netcfg URL
-        url = 'http://%s:8181/onos/v1/network/configuration/' % controllerIP
-        # Instantiate password manager for HTTP auth
-        pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
-        pm.add_password(None, url,
-                        os.environ['ONOS_WEB_USER'],
-                        os.environ['ONOS_WEB_PASS'])
-        urllib2.install_opener(urllib2.build_opener(
-            urllib2.HTTPBasicAuthHandler(pm)))
-        # Push config data to controller
-        req = urllib2.Request(url, json.dumps(cfgData),
-                              {'Content-Type': 'application/json'})
-        try:
-            f = urllib2.urlopen(req)
-            print f.read()
-            f.close()
-        except urllib2.URLError as e:
-            warn("*** WARN: unable to push config to ONOS (%s)\n" % e.reason)
-
-    def start(self, controllers):
-        bmv2Args = [SIMPLE_SWITCH_GRPC] + self.grpcTargetArgs()
-        if self.valgrind:
-            bmv2Args = VALGRIND_PREFIX.split() + bmv2Args
-
-        cmdString = " ".join(bmv2Args)
-
-        if self.dryrun:
-            info("\n*** DRY RUN (not executing bmv2)")
-
-        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
-                self.logfd = open(self.logfile, "w")
-                self.bmv2popen = self.popen(cmdString,
-                                            stdout=self.logfd,
-                                            stderr=self.logfd)
-                self.waitBmv2Start()
-                # We want to be notified if BMv2 dies...
-                threading.Thread(target=watchDog, args=[self]).start()
-
-            self.doOnosNetcfg(self.controllerIp(controllers))
-        except Exception:
-            ONOSBmv2Switch.mininet_exception = 1
-            self.killBmv2()
-            self.printBmv2Log()
-            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():
-                args.append('-i %d@%s' % (port, intf.name))
-        args.append('--thrift-port %s' % self.thriftPort)
-        if self.notifications:
-            ntfaddr = 'ipc:///tmp/bmv2-%s-notifications.ipc' % self.name
-            args.append('--notifications-addr %s' % ntfaddr)
-        if self.elogger:
-            nanologaddr = 'ipc:///tmp/bmv2-%s-nanolog.ipc' % self.name
-            args.append('--nanolog %s' % nanologaddr)
-        if self.debugger:
-            dbgaddr = 'ipc:///tmp/bmv2-%s-debug.ipc' % self.name
-            args.append('--debugger-addr %s' % dbgaddr)
-        args.append('--log-console')
-        if self.pktdump:
-            args.append('--pcap --dump-packet-data %s' % PKT_BYTES_TO_DUMP)
-        args.append('-L%s' % self.loglevel)
-        if not self.json:
-            args.append('--no-p4')
-        else:
-            args.append(self.json)
-        # gRPC target-specific options
-        args.append('--')
-        args.append('--cpu-port %s' % self.cpuPort)
-        args.append('--grpc-server-addr 0.0.0.0:%s' % self.grpcPort)
-        return args
-
-    def waitBmv2Start(self):
-        # Wait for switch to open gRPC port, before sending ONOS the netcfg.
-        # Include time-out just in case something hangs.
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        endtime = time.time() + SWITCH_START_TIMEOUT
-        while True:
-            result = sock.connect_ex(('127.0.0.1', self.grpcPort))
-            if result == 0:
-                # The port is open. Let's go! (Close socket first)
-                sock.close()
-                break
-            # Port is not open yet. If there is time, we wait a bit.
-            if endtime > time.time():
-                time.sleep(0.1)
-            else:
-                # Time's up.
-                raise Exception("Switch did not start before timeout")
-
-    def printBmv2Log(self):
-        if os.path.isfile(self.logfile):
-            print "-" * 80
-            print "%s log (from %s):" % (self.name, self.logfile)
-            with open(self.logfile, 'r') as f:
-                lines = f.readlines()
-                if len(lines) > BMV2_LOG_LINES:
-                    print "..."
-                for line in lines[-BMV2_LOG_LINES:]:
-                    print line.rstrip()
-
-    @staticmethod
-    def controllerIp(controllers):
-        try:
-            # onos.py
-            clist = controllers[0].nodes()
-        except AttributeError:
-            clist = controllers
-        assert len(clist) > 0
-        return random.choice(clist).IP()
-
-    def killBmv2(self, log=False):
-        if self.bmv2popen is not None:
-            self.bmv2popen.kill()
-        if self.logfd is not None:
-            if log:
-                self.logfd.write("*** PROCESS TERMINATED BY MININET ***\n")
-            self.logfd.close()
-
-    def cleanupTmpFiles(self):
-        self.cmd("rm -f /tmp/bmv2-%s-*" % self.name)
-
-    def stop(self, deleteIntfs=True):
-        """Terminate switch."""
-        self.stopped = True
-        self.killBmv2(log=True)
-        Switch.stop(self, deleteIntfs)
-
-
-# Exports for bin/mn
-switches = {'onosbmv2': ONOSBmv2Switch}
-hosts = {'onoshost': ONOSHost}