[WIP] ONOS-8091 Port python script and utilities to python3

Steps performed so far:
- Updated bash scripts and similar to explicitly invoke python3 (instead of python)
- Updated all python scripts using 2to3

Testing these changes will be a major headache because:
- different scripts are executed in different environments
  (e.g., Jenkins, cell servers, tutorial VMs, etc.)
- we don’t have control on all environments
- some environments we used to control have been dismissed
  (e.g., cell servers)

The approach for now is to focus on the essentials:
- Jenkins jobs for pre-merge and release

Test and fix everything else as the need arises.

Change-Id: I943e214760c9dea9a7ded0d47ef08adbc0ed0bec
diff --git a/tools/test/topos/attcli.py b/tools/test/topos/attcli.py
index 1945320..80bac6f 100644
--- a/tools/test/topos/attcli.py
+++ b/tools/test/topos/attcli.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 """
 CLI for test with AttMplsTopo
diff --git a/tools/test/topos/attmpls.py b/tools/test/topos/attmpls.py
index fedcb6c..b72e711 100644
--- a/tools/test/topos/attmpls.py
+++ b/tools/test/topos/attmpls.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/bmv2-demo.py b/tools/test/topos/bmv2-demo.py
index 949fe0c..ab0e811 100755
--- a/tools/test/topos/bmv2-demo.py
+++ b/tools/test/topos/bmv2-demo.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import os
 import sys
@@ -18,13 +18,13 @@
 JUMBO_MTU=9000
 
 if 'ONOS_ROOT' not in os.environ:
-    print "Environment var $ONOS_ROOT not set"
+    print("Environment var $ONOS_ROOT not set")
     exit()
 else:
     ONOS_ROOT = os.environ["ONOS_ROOT"]
     sys.path.append(ONOS_ROOT + "/tools/dev/mininet")
 if 'RUN_PACK_PATH' not in os.environ:
-    print "Environment var $RUN_PACK_PATH not set"
+    print("Environment var $RUN_PACK_PATH not set")
     exit()
 else:
     RUN_PACK_PATH = os.environ["RUN_PACK_PATH"]
@@ -130,14 +130,14 @@
         self.cmd("killall arping")
 
     def describe(self):
-        print "**********"
-        print self.name
-        print "default interface: %s\t%s\t%s" % (
+        print("**********")
+        print(self.name)
+        print("default interface: %s\t%s\t%s" % (
             self.defaultIntf().name,
             self.defaultIntf().IP(),
             self.defaultIntf().MAC()
-        )
-        print "**********"
+        ))
+        print("**********")
 
     def getInfiniteCmdBg(self, cmd, logfile="/dev/null", delay=1):
         return "(while [ -e {} ]; " \
@@ -227,7 +227,7 @@
             }
         }
 
-    print "Writing network config to %s" % TEMP_NETCFG_FILE
+    print("Writing network config to %s" % TEMP_NETCFG_FILE)
     with open(TEMP_NETCFG_FILE, 'w') as tempFile:
         json.dump(netcfg, tempFile, indent=4)
 
@@ -267,7 +267,7 @@
     net.build()
     net.start()
 
-    print "Network started"
+    print("Network started")
 
     # Always generate background pings.
     sleep(3)
@@ -275,7 +275,7 @@
         h1.startPingBg(h2)
         h2.startPingBg(h1)
 
-    print "Background ping started"
+    print("Background ping started")
 
     # Increase the MTU size for INT operation
     if args.pipeconf_id.endswith("int") or args.pipeconf_id.endswith("full"):
@@ -284,22 +284,22 @@
     for h in net.hosts:
         h.startIperfServer()
 
-    print "Iperf servers started"
+    print("Iperf servers started")
 
     if args.bg_traffic:
         sleep(4)
-        print "Starting iperf clients..."
+        print("Starting iperf clients...")
         net.hosts[0].startIperfClient(net.hosts[-1], flowBw="400k",
                                       numFlows=50, duration=10)
 
     generateNetcfg(onosIp, net, args)
 
     if args.netcfg_sleep > 0:
-        print "Waiting %d seconds before pushing config to ONOS..." \
-              % args.netcfg_sleep
+        print("Waiting %d seconds before pushing config to ONOS..." \
+              % args.netcfg_sleep)
         sleep(args.netcfg_sleep)
 
-    print "Pushing config to ONOS..."
+    print("Pushing config to ONOS...")
     call(("%s/onos-netcfg" % RUN_PACK_PATH, onosIp, TEMP_NETCFG_FILE))
 
     if not args.onos_ip:
diff --git a/tools/test/topos/default.py b/tools/test/topos/default.py
index b58b780..5525c92 100644
--- a/tools/test/topos/default.py
+++ b/tools/test/topos/default.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/dual-onos.py b/tools/test/topos/dual-onos.py
index b0b92ed..a6e424a 100644
--- a/tools/test/topos/dual-onos.py
+++ b/tools/test/topos/dual-onos.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 from onosnet import run
 from dual import DualTopo
diff --git a/tools/test/topos/dual.py b/tools/test/topos/dual.py
index d795a37..3240173 100644
--- a/tools/test/topos/dual.py
+++ b/tools/test/topos/dual.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/ectest.py b/tools/test/topos/ectest.py
index 37acfc5..7115bee 100755
--- a/tools/test/topos/ectest.py
+++ b/tools/test/topos/ectest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import json
 
@@ -54,34 +54,34 @@
         return self.__dId
 
     def getControllers(self, name=None):
-        return self.__cmap.values() if not name else self.__cmap.get(name)
+        return list(self.__cmap.values()) if not name else self.__cmap.get(name)
 
     def getSwitches(self, name=None):
-        return self.__smap.values() if not name else self.__smap.get(name)
+        return list(self.__smap.values()) if not name else self.__smap.get(name)
 
     def getHosts(self, name=None):
-        return self.__hmap.values() if not name else self.__hmap.get(name)
+        return list(self.__hmap.values()) if not name else self.__hmap.get(name)
 
     def injectInto(self, net):
         """ Adds available topology info to a supplied Mininet object. """
         # add switches, hosts, then links to mininet object
-        for sw, args in self.__switches.iteritems():
+        for sw, args in self.__switches.items():
             self.__smap[sw] = net.addSwitch(sw, **args)
-        for h, args in self.__hosts.iteritems():
+        for h, args in self.__hosts.items():
             self.__hmap[h] = net.addHost(h, **args)
-        for l, args in self.__links.iteritems():
+        for l, args in self.__links.items():
             src = self.__smap.get(l[0])
             dst = self.__smap.get(l[1])
             net.addLink(src if src else self.__hmap.get(l[0]),
                          dst if dst else self.__hmap.get(l[1]), **args)
         # then controllers
-        for c, args in self.__ctrls.iteritems():
+        for c, args in self.__ctrls.items():
             self.__cmap[c] = net.addController(c, **args)
 
     def start(self):
         """ starts the switches with the correct controller. """
-        map(lambda c: c.start(), self.__cmap.values())
-        map(lambda s: s.start(self.__cmap.values()), self.__smap.values())
+        list(map(lambda c: c.start(), list(self.__cmap.values())))
+        list(map(lambda s: s.start(list(self.__cmap.values())), list(self.__smap.values())))
 
     def build(self, *args):
         """ override for custom topology, similar to Topo """
@@ -193,7 +193,7 @@
 
     # fire everything up
     net.build()
-    map(lambda x: x.start(), domains)
+    list(map(lambda x: x.start(), domains))
 
     # create a minimal copy of the network for configuring LINC.
     cfgnet = Mininet()
@@ -226,7 +226,7 @@
     setLogLevel('info')
     import sys
     if len(sys.argv) < 4:
-        print ("Usage: sudo -E ./ectest.py ctl-set1 ... ctl-set4\n\n",
-                "Where ctl-set are comma-separated controller IP's")
+        print(("Usage: sudo -E ./ectest.py ctl-set1 ... ctl-set4\n\n",
+                "Where ctl-set are comma-separated controller IP's"))
     else:
         setup(sys.argv)
diff --git a/tools/test/topos/fractal.py b/tools/test/topos/fractal.py
index bc5c689..7590144 100755
--- a/tools/test/topos/fractal.py
+++ b/tools/test/topos/fractal.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from mininet.topo import Topo
 
diff --git a/tools/test/topos/geant.py b/tools/test/topos/geant.py
index 6eedd29..25da34e 100644
--- a/tools/test/topos/geant.py
+++ b/tools/test/topos/geant.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/gratuitousArp.py b/tools/test/topos/gratuitousArp.py
index 27af1e9..0fce183 100755
--- a/tools/test/topos/gratuitousArp.py
+++ b/tools/test/topos/gratuitousArp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 import sys
 import os
 import fcntl
@@ -22,14 +22,14 @@
     try:
         sock.bind((intf, socket.SOCK_RAW))
     except:
-        print 'Device does not exist: %s' % intf
+        print('Device does not exist: %s' % intf)
         return
 
     if not ip:
         try:
             ip = getIPAddress(intf)
         except IOError:
-            print 'No IP for %s' % intf
+            print('No IP for %s' % intf)
             return
     packed_ip = pack('!4B', *[int(x) for x in ip.split('.')])
 
diff --git a/tools/test/topos/metro.py b/tools/test/topos/metro.py
index 76f4ed2..0ba7303 100755
--- a/tools/test/topos/metro.py
+++ b/tools/test/topos/metro.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import json
 
@@ -53,34 +53,34 @@
         return self.__dId
 
     def getControllers(self, name=None):
-        return self.__cmap.values() if not name else self.__cmap.get(name)
+        return list(self.__cmap.values()) if not name else self.__cmap.get(name)
 
     def getSwitches(self, name=None):
-        return self.__smap.values() if not name else self.__smap.get(name)
+        return list(self.__smap.values()) if not name else self.__smap.get(name)
 
     def getHosts(self, name=None):
-        return self.__hmap.values() if not name else self.__hmap.get(name)
+        return list(self.__hmap.values()) if not name else self.__hmap.get(name)
 
     def injectInto(self, net):
         """ Adds available topology info to a supplied Mininet object. """
         # add switches, hosts, then links to mininet object
-        for sw, args in self.__switches.iteritems():
+        for sw, args in self.__switches.items():
             self.__smap[sw] = net.addSwitch(sw, **args)
-        for h, args in self.__hosts.iteritems():
+        for h, args in self.__hosts.items():
             self.__hmap[h] = net.addHost(h, **args)
-        for l, args in self.__links.iteritems():
+        for l, args in self.__links.items():
             src = self.__smap.get(l[0])
             dst = self.__smap.get(l[1])
             net.addLink(src if src else self.__hmap.get(l[0]),
                          dst if dst else self.__hmap.get(l[1]), **args)
         # then controllers
-        for c, args in self.__ctrls.iteritems():
+        for c, args in self.__ctrls.items():
             self.__cmap[c] = net.addController(c, **args)
 
     def start(self):
         """ starts the switches with the correct controller. """
-        map(lambda c: c.start(), self.__cmap.values())
-        map(lambda s: s.start(self.__cmap.values()), self.__smap.values())
+        list(map(lambda c: c.start(), list(self.__cmap.values())))
+        list(map(lambda s: s.start(list(self.__cmap.values())), list(self.__smap.values())))
 
     def build(self, *args):
         """ override for custom topology, similar to Topo """
@@ -216,7 +216,7 @@
 
     # fire everything up
     net.build()
-    map(lambda x: x.start(), domains)
+    list(map(lambda x: x.start(), domains))
 
     # create a minimal copy of the network for configuring LINC.
     cfgnet = Mininet()
@@ -249,7 +249,7 @@
     setLogLevel('info')
     import sys
     if len(sys.argv) < 5:
-        print ("Usage: sudo -E ./metro.py ctl-set1 ... ctl-set4\n\n",
-                "Where ctl-set are comma-separated controller IP's")
+        print(("Usage: sudo -E ./metro.py ctl-set1 ... ctl-set4\n\n",
+                "Where ctl-set are comma-separated controller IP's"))
     else:
         setup(sys.argv)
diff --git a/tools/test/topos/newFuncTopo.py b/tools/test/topos/newFuncTopo.py
index 5edf7f7..c3c6cbcf 100644
--- a/tools/test/topos/newFuncTopo.py
+++ b/tools/test/topos/newFuncTopo.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 """
 Custom topology for Mininet
diff --git a/tools/test/topos/obelisk.py b/tools/test/topos/obelisk.py
index fb6ccdb..3e96ee3 100755
--- a/tools/test/topos/obelisk.py
+++ b/tools/test/topos/obelisk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from mininet.topo import Topo
 
diff --git a/tools/test/topos/obeliskHostCheck.py b/tools/test/topos/obeliskHostCheck.py
index 988e2e5..92bc166 100755
--- a/tools/test/topos/obeliskHostCheck.py
+++ b/tools/test/topos/obeliskHostCheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import sys
 import os
@@ -7,10 +7,10 @@
 # TODO: if none given, use OCI
 try:
     onosIp = sys.argv[1]
-    print "Reading hosts view from ONOS node " + onosIp + ":"
+    print("Reading hosts view from ONOS node " + onosIp + ":")
 except Exception as e:
-    print "Error reading ONOS IP arguement"
-    print e
+    print("Error reading ONOS IP arguement")
+    print(e)
 # Grab the json objects from ONOS
 output = os.popen("onos " + onosIp + " \"hosts -j\"" )
 hosts = json.loads( output.read() )
@@ -49,7 +49,7 @@
 
 if hosts or "Error" not in hosts:
     if hosts == []:
-        print "WARNING: There are no hosts discovered"
+        print("WARNING: There are no hosts discovered")
     else:
         for host in hosts:
             mac = None
@@ -73,19 +73,19 @@
                 # Now check if this matches where they should be
                 if mac and device and port:
                     if device != mappings[ str( mac ) ]:
-                        print "The attachment device is incorrect for host " + str( mac ) +\
-                              ". Expected: " + mappings[ str( mac ) ] + "; Actual: " + device
+                        print("The attachment device is incorrect for host " + str( mac ) +\
+                              ". Expected: " + mappings[ str( mac ) ] + "; Actual: " + device)
                         hostAttachment = False
                     if str( port ) != "1":
-                        print "The attachment port is incorrect for host " + str( mac ) +\
-                              ". Expected: 1; Actual: " + str( port)
+                        print("The attachment port is incorrect for host " + str( mac ) +\
+                              ". Expected: 1; Actual: " + str( port))
                         hostAttachment = False
                 else:
                     hostAttachment = False
             except AssertionError as e:
-                print "ERROR: Json object not as expected:"
-                print e
-                print "host object: " + repr( host )
+                print("ERROR: Json object not as expected:")
+                print(e)
+                print("host object: " + repr( host ))
                 hostAttachment = False
 else:
-    print "No hosts json output or \"Error\" in output. hosts = " + repr( hosts )
+    print("No hosts json output or \"Error\" in output. hosts = " + repr( hosts ))
diff --git a/tools/test/topos/onosnet.py b/tools/test/topos/onosnet.py
index adb4a10..223a585 100644
--- a/tools/test/topos/onosnet.py
+++ b/tools/test/topos/onosnet.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 import itertools
 import os
 import signal
@@ -137,7 +137,7 @@
         t -= 1
         sys.stdout.flush()
         sleep(1)
-    print
+    print()
 
 def formatBw( bw ):
     bw = float(bw)
@@ -221,7 +221,7 @@
 
 def run( topo, controllers=None, link=TCLink, autoSetMacs=True):
     if not topo:
-        print 'Need to provide a topology'
+        print('Need to provide a topology')
         exit(1)
 
     args = parse_args()
@@ -230,14 +230,14 @@
         controllers = args.ipAddrs
 
     if not controllers and args.clusterSize < 1:
-        print 'Need to provide a list of controller IPs, or define a cluster size.'
+        print('Need to provide a list of controller IPs, or define a cluster size.')
         exit( 1 )
 
     setLogLevel( 'info' )
 
     if args.clusterSize > 0:
         if 'ONOS_ROOT' not in os.environ:
-            print "Environment var $ONOS_ROOT not set (needed to import onos.py)"
+            print("Environment var $ONOS_ROOT not set (needed to import onos.py)")
             exit( 1 )
         sys.path.append(os.environ["ONOS_ROOT"] + "/tools/dev/mininet")
         from onos import ONOSCluster, ONOSOVSSwitch, ONOSCLI
diff --git a/tools/test/topos/opticalTest.py b/tools/test/topos/opticalTest.py
index 8e316fa..2f94747 100755
--- a/tools/test/topos/opticalTest.py
+++ b/tools/test/topos/opticalTest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 from opticalUtils import MininetOE, LINCSwitch, LINCLink
 from mininet.topo import Topo
@@ -86,8 +86,8 @@
     if len( sys.argv ) >= 2:
         controllers = sys.argv[1:]
     else:
-        print 'Usage:sudo -E python opticalTest.py (<Controller IP>)+'
-        print 'Using localhost...\n'
+        print('Usage:sudo -E python3 opticalTest.py (<Controller IP>)+')
+        print('Using localhost...\n')
         controllers = [ '127.0.0.1' ]
 
     setLogLevel( 'info' )
diff --git a/tools/test/topos/opticalTestBig.py b/tools/test/topos/opticalTestBig.py
index b730c73..888a52d 100755
--- a/tools/test/topos/opticalTestBig.py
+++ b/tools/test/topos/opticalTestBig.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 from opticalUtils import MininetOE, LINCSwitch, LINCLink
 from mininet.topo import Topo
@@ -379,8 +379,8 @@
     if len( sys.argv ) >= 2:
         controllers = sys.argv[1:]
     else:
-        print 'Usage: sudo -E python opticalTestBig.py (<Controller IP>)+'
-        print 'Using localhost...\n'
+        print('Usage: sudo -E python3 opticalTestBig.py (<Controller IP>)+')
+        print('Using localhost...\n')
         controllers = [ '127.0.0.1' ]
 
     setLogLevel( 'info' )
diff --git a/tools/test/topos/opticalUtils.py b/tools/test/topos/opticalUtils.py
index ca01395..6eaf99d 100644
--- a/tools/test/topos/opticalUtils.py
+++ b/tools/test/topos/opticalUtils.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#!/usr/bin/python3
 '''
 Notes:
 
@@ -56,7 +55,7 @@
 import json
 import os
 from time import sleep
-import urllib2
+import urllib.request, urllib.error, urllib.parse
 
 from mininet.node import Switch, OVSSwitch, RemoteController
 from mininet.topo import Topo
@@ -87,7 +86,7 @@
                     switch_id += 1
         return dpids_to_ids
     except:
-        print "Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info())
+        print("Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info()))
         fd.close()
         return None
 
@@ -114,7 +113,7 @@
     annotations.setdefault('name', switch.name)
     configDict[ 'annotations' ] = annotations
     ports = []
-    for port, intf in switch.intfs.items():
+    for port, intf in list(switch.intfs.items()):
         if intf.name == 'lo':
             continue
         portDict = {}
@@ -330,7 +329,7 @@
         self.configDict[ 'annotations' ].setdefault('name', self.name)
         self.configDict[ 'type' ] = self.switchType
         self.configDict[ 'ports' ] = []
-        for port, intf in self.intfs.items():
+        for port, intf in list(self.intfs.items()):
             if intf.name == 'lo':
                 continue
             else:
@@ -358,7 +357,7 @@
             fd.write(command)
             fd.close()
         except:
-            print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info())
+            print("Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info()))
             if fd:
                 fd.close()
 
@@ -553,26 +552,26 @@
         url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip
         time = 0
         # Set up password authentication
-        pw_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
+        pw_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
         pw_mgr.add_password(None, url, LINCSwitch.restUser, LINCSwitch.restPass)
-        handler = urllib2.HTTPBasicAuthHandler(pw_mgr)
-        opener = urllib2.build_opener(handler)
+        handler = urllib.request.HTTPBasicAuthHandler(pw_mgr)
+        opener = urllib.request.build_opener(handler)
         opener.open(url)
-        urllib2.install_opener(opener)
+        urllib.request.install_opener(opener)
         # focus on just checking the state of devices we're interested in
         # expected devices availability map
-        devMap =  dict.fromkeys(map( lambda x: x['uri'], devices ), False)
+        devMap =  dict.fromkeys([x['uri'] for x in devices], False)
         while True:
-            response = json.load(urllib2.urlopen(url))
+            response = json.load(urllib.request.urlopen(url))
             devs = response.get('devices')
 
             # update availability map
             for d in devs:
-                if devMap.has_key(d['id']):
+                if d['id'] in devMap:
                     devMap[d['id']] = d['available']
 
             # Check if all devices we're interested became available
-            if all(devMap.viewvalues()):
+            if all(devMap.values()):
                 break;
 
             if (time >= TIMEOUT):
@@ -612,7 +611,7 @@
             # Annotations hold switch name and latitude/longitude
             devDict = {}
             devDict[ 'type' ] = switch[ 'type' ]
-            devDict.update({k: v for k, v in switch[ 'annotations' ].iteritems() if k in BasicDevConfigKeys})
+            devDict.update({k: v for k, v in switch[ 'annotations' ].items() if k in BasicDevConfigKeys})
             devSubj = switch[ 'uri' ]
             devices[ devSubj ] = { 'basic': devDict }
 
diff --git a/tools/test/topos/regionabc-onos.py b/tools/test/topos/regionabc-onos.py
index f2c8218..9696b57 100644
--- a/tools/test/topos/regionabc-onos.py
+++ b/tools/test/topos/regionabc-onos.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 from onosnet import run
 from regionabc import RegionABC
diff --git a/tools/test/topos/regionabc.py b/tools/test/topos/regionabc.py
index 14aa9e7..be537f5 100644
--- a/tools/test/topos/regionabc.py
+++ b/tools/test/topos/regionabc.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
       [1] ----- [3] ----- [5]
diff --git a/tools/test/topos/rftest.py b/tools/test/topos/rftest.py
index 7aba54f..80807c7 100644
--- a/tools/test/topos/rftest.py
+++ b/tools/test/topos/rftest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import sys
 
@@ -35,6 +35,6 @@
     if len( sys.argv ) > 1:
         controllers = sys.argv[ 1: ]
     else:
-        print 'Usage: rf-test.py <c0 IP> <c1 IP> ...'
+        print('Usage: rf-test.py <c0 IP> <c1 IP> ...')
         exit( 1 )
     run( controllers )
diff --git a/tools/test/topos/rftesttopo.py b/tools/test/topos/rftesttopo.py
index 9b97578..205811a 100644
--- a/tools/test/topos/rftesttopo.py
+++ b/tools/test/topos/rftesttopo.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/routinglib.py b/tools/test/topos/routinglib.py
index 6ac0932..c92e52f 100644
--- a/tools/test/topos/routinglib.py
+++ b/tools/test/topos/routinglib.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 """
 Libraries for creating L3 topologies with routing protocols.
@@ -45,7 +45,7 @@
         self.cmd('sysctl net.ipv4.ip_forward=1')
         self.cmd('sysctl net.ipv4.conf.all.rp_filter=0')
 
-        for intf, configs in self.interfaces.items():
+        for intf, configs in list(self.interfaces.items()):
             self.cmd('ip addr flush dev %s' % intf)
             self.cmd( 'sysctl net.ipv4.conf.%s.rp_filter=0' % intf )
             
@@ -99,9 +99,9 @@
         try:
             original_umask = os.umask(0)
             if (not os.path.isdir(QuaggaRouter.logDir)):
-                os.makedirs(QuaggaRouter.logDir, 0777)
+                os.makedirs(QuaggaRouter.logDir, 0o777)
             if (not os.path.isdir(self.runDir)):
-                os.makedirs(self.runDir, 0777)
+                os.makedirs(self.runDir, 0o777)
         finally:
             os.umask(original_umask)
 
@@ -182,8 +182,8 @@
         conf = ConfigurationWriter(self.configFile)
                     
         def getRouterId(interfaces):
-            intfAttributes = interfaces.itervalues().next()
-            print intfAttributes
+            intfAttributes = next(iter(interfaces.values()))
+            print(intfAttributes)
             if isinstance(intfAttributes, list):
                 # Try use the first set of attributes, but if using vlans they might not have addresses
                 intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
@@ -236,8 +236,8 @@
         conf = ConfigurationWriter(self.configFile)
             
         def getRouterId(interfaces):
-            intfAttributes = interfaces.itervalues().next()
-            print intfAttributes
+            intfAttributes = next(iter(interfaces.values()))
+            print(intfAttributes)
             if isinstance(intfAttributes, list):
                 # Try use the first set of attributes, but if using vlans they might not have addresses
                 intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
@@ -253,7 +253,7 @@
         conf.writeLine('ospf router-id %s' % getRouterId(self.qr.interfaces))
         conf.writeLine('!')
         
-        for name, intf in self.qr.interfaces.items():
+        for name, intf in list(self.qr.interfaces.items()):
             for ip in intf['ipAddrs']:
                 conf.writeLine('network %s area 0' % ip)
             #if intf['ipAddrs'][0].startswith('192.168'):
@@ -409,7 +409,7 @@
 
     @staticmethod
     def generatePeeringAddresses():
-        network = ip_network(u'10.0.%s.0/24' % AutonomousSystem.psIdx)
+        network = ip_network('10.0.%s.0/24' % AutonomousSystem.psIdx)
         AutonomousSystem.psIdx += 1
         
         return ip_interface('%s/%s' % (network[1], network.prefixlen)), \
@@ -456,7 +456,7 @@
         intfs = {}
         
         router = self.routers[1]
-        for i, router in self.routers.items():
+        for i, router in list(self.routers.items()):
         
             #routerName = 'r%i%i' % (self.num, i)
             routerName = 'r%i' % self.num
@@ -465,12 +465,12 @@
                 
             hostName = 'h%i' % self.num
         
-            for j, interface in router.interfaces.items():
+            for j, interface in list(router.interfaces.items()):
                 nativeAddresses = interface.addressesByVlan.pop(None, [])
                 peeringIntf = [{'mac' : '00:00:%02x:00:%02x:%02x' % (self.num, i, j),
                                'ipAddrs' : nativeAddresses}]
                 
-                for vlan, addresses in interface.addressesByVlan.items():
+                for vlan, addresses in list(interface.addressesByVlan.items()):
                     peeringIntf.append({'vlan':vlan,
                                         'mac':'00:00:%02x:%02x:%02x:%02x' % (self.num, vlan, i, j),
                                         'ipAddrs':addresses})
@@ -486,7 +486,7 @@
                 internalIntf = {'ipAddrs' : internalAddresses}
         
                 # This is the configuration of the next interface after all the peering interfaces
-                intfs.update({'%s-eth%s' % (routerName, len(router.interfaces.keys())) : internalIntf})
+                intfs.update({'%s-eth%s' % (routerName, len(list(router.interfaces.keys()))) : internalIntf})
     
             routerNode = topology.addHost(routerName,  
                                   asNum=self.asNum, neighbors=router.neighbors,
@@ -550,15 +550,15 @@
         self.peerIntfConfig = peerIntfConfig
         self.withFpm = withFpm
         self.externalOnos= externalOnos
-        self.internalPeeringSubnet = ip_network(u'1.1.1.0/24')
+        self.internalPeeringSubnet = ip_network('1.1.1.0/24')
         
-        for router in self.routers.values():
+        for router in list(self.routers.values()):
             # Add iBGP sessions to ONOS nodes
             for onosIp in onosIps:
                 router.neighbors.append({'address':onosIp, 'as':asNum, 'port':2000})
                 
             # Add iBGP sessions to other BGP speakers
-            for i, router2 in self.routers.items():
+            for i, router2 in list(self.routers.items()):
                 if router == router2:
                     continue
                 ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, 10+i)
@@ -568,7 +568,7 @@
         
         natIp = AutonomousSystem.getLastAddress(self.internalPeeringSubnet)
         
-        for i, router in self.routers.items():
+        for i, router in list(self.routers.items()):
             name = 'bgp%s' % i
             
             ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, 10+i)
@@ -580,7 +580,7 @@
                 eth1 = [{ 'mac':'00:00:00:00:00:%02x' % i, 
                          'ipAddrs' : nativeAddresses }]
                 
-                for vlan, addresses in router.interfaces[1].addressesByVlan.items():
+                for vlan, addresses in list(router.interfaces[1].addressesByVlan.items()):
                     eth1.append({'vlan':vlan,
                                 'mac':'00:00:00:%02x:%02x:00' % (i, vlan),
                                 'ipAddrs':addresses})
diff --git a/tools/test/topos/sdnip.py b/tools/test/topos/sdnip.py
index 7739d58..b561111 100755
--- a/tools/test/topos/sdnip.py
+++ b/tools/test/topos/sdnip.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from mininet.cli import CLI
 from mininet.log import setLogLevel
@@ -65,26 +65,26 @@
         numRoutesPerAs = 32
 
         # Add external ASes
-        as1 = BasicAutonomousSystem(1, generateRoutes(u'192.168.1.0/24', numRoutesPerAs))
+        as1 = BasicAutonomousSystem(1, generateRoutes('192.168.1.0/24', numRoutesPerAs))
         AutonomousSystem.addPeering(as1, sdnAs)
         AutonomousSystem.addPeering(as1, sdnAs, router2=3, intf1=2)
         as1.addLink(s5)
         as1.addLink(s6)
         as1.build(self)
         
-        as2 = BasicAutonomousSystem(2, generateRoutes(u'192.168.2.0/24', numRoutesPerAs))
+        as2 = BasicAutonomousSystem(2, generateRoutes('192.168.2.0/24', numRoutesPerAs))
         AutonomousSystem.addPeering(as2, sdnAs)
         AutonomousSystem.addPeering(as2, sdnAs, router2=2)
         as2.addLink(s7)
         as2.build(self)
         
-        as3 = BasicAutonomousSystem(3, generateRoutes(u'192.168.3.0/24', numRoutesPerAs))
+        as3 = BasicAutonomousSystem(3, generateRoutes('192.168.3.0/24', numRoutesPerAs))
         AutonomousSystem.addPeering(as3, sdnAs, router2=2)
         AutonomousSystem.addPeering(as3, sdnAs, router2=3)
         as3.addLink(s8)
         as3.build(self)
         
-        as4 = BasicAutonomousSystem(4, generateRoutes(u'192.168.4.0/24', numRoutesPerAs), numRouters=2)
+        as4 = BasicAutonomousSystem(4, generateRoutes('192.168.4.0/24', numRoutesPerAs), numRouters=2)
         AutonomousSystem.addPeering(as4, sdnAs)
         AutonomousSystem.addPeering(as4, sdnAs, router1=2, router2=3)
         as4.addLink(s9)
diff --git a/tools/test/topos/sol.py b/tools/test/topos/sol.py
index 68f2d40..823fbe6 100755
--- a/tools/test/topos/sol.py
+++ b/tools/test/topos/sol.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 import sys, solar
 topo = solar.Solar(cips=sys.argv[1:])
 topo.run()
diff --git a/tools/test/topos/solar.py b/tools/test/topos/solar.py
index f316162..be3123a 100644
--- a/tools/test/topos/solar.py
+++ b/tools/test/topos/solar.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 from mininet.cli import CLI
 from mininet.net import Mininet
 from mininet.node import RemoteController, OVSKernelSwitch
diff --git a/tools/test/topos/topo b/tools/test/topos/topo
index 854de50..4ba951f 100755
--- a/tools/test/topos/topo
+++ b/tools/test/topos/topo
@@ -7,4 +7,4 @@
 topo=${1:-att-onos.py}
 
 [ -n "$1" ] && shift
-sudo python $topo "$@"
+sudo python3 $topo "$@"
diff --git a/tools/test/topos/tower.py b/tools/test/topos/tower.py
index 22d515b..02d2721 100755
--- a/tools/test/topos/tower.py
+++ b/tools/test/topos/tower.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/uk-onos.py b/tools/test/topos/uk-onos.py
index 2426b4f..5202ee2 100644
--- a/tools/test/topos/uk-onos.py
+++ b/tools/test/topos/uk-onos.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#!/usr/bin/python3
 from onosnet import run
 from uk import UkTopo
 
diff --git a/tools/test/topos/uk-region-onos.py b/tools/test/topos/uk-region-onos.py
index 744844d..214d2e8 100644
--- a/tools/test/topos/uk-region-onos.py
+++ b/tools/test/topos/uk-region-onos.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#!/usr/bin/python3
 from onosnet import run
 from ukRegion import UkRegionTopo
 
diff --git a/tools/test/topos/uk.py b/tools/test/topos/uk.py
index aabd0b7..9bb5ec7 100644
--- a/tools/test/topos/uk.py
+++ b/tools/test/topos/uk.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 """
diff --git a/tools/test/topos/ukRegion.py b/tools/test/topos/ukRegion.py
index ecbdf6a..af6c76b 100644
--- a/tools/test/topos/ukRegion.py
+++ b/tools/test/topos/ukRegion.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
   Sample network for demonstrating regions (see uk-region.json)
diff --git a/tools/test/topos/vpls.py b/tools/test/topos/vpls.py
index 0be2e68..8b3adf6 100755
--- a/tools/test/topos/vpls.py
+++ b/tools/test/topos/vpls.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from mininet.cli import CLI
 from mininet.node import Link, Host