[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/dev/Dockerfile-dev b/tools/dev/Dockerfile-dev
index d589ba0..87316c3 100644
--- a/tools/dev/Dockerfile-dev
+++ b/tools/dev/Dockerfile-dev
@@ -20,7 +20,7 @@
 WORKDIR /src/onos
 RUN apt-get update && \
         DEBIAN_FRONTEND=noninteractive \
-        apt-get install -y zip python git bzip2 build-essential && \
+        apt-get install -y zip python3 git bzip2 build-essential && \
         export ONOS_ROOT=/src/onos && \
         mkdir -p /src/tar && \
         cd /src/tar && \
diff --git a/tools/dev/bash_profile b/tools/dev/bash_profile
index eaff4b3..f6a9543 100644
--- a/tools/dev/bash_profile
+++ b/tools/dev/bash_profile
@@ -77,7 +77,7 @@
 alias ole='olo "ERROR|WARN|Exception|Error"'
 
 # Pretty-print JSON output
-alias pp='python -m json.tool'
+alias pp='python3 -m json.tool'
 
 # Short-hand to launch Java API docs, REST API docs and ONOS GUI
 alias docs='open $ONOS_ROOT/docs/target/site/apidocs/index.html'
diff --git a/tools/dev/bin/branch-clean b/tools/dev/bin/branch-clean
index 17960b0..87f303b 100755
--- a/tools/dev/bin/branch-clean
+++ b/tools/dev/bin/branch-clean
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 from subprocess import check_output
 import sys
@@ -31,21 +31,21 @@
     one_by_one = '--one-by-one' in sys.argv
     to_delete = get_merged_branches_by_change_id()
     if len(to_delete) == 0:
-        print "Nothing to clean"
+        print("Nothing to clean")
         sys.exit(0)
     for branch in to_delete:
         if dry_run:
-            print branch
+            print(branch)
         else:
             if one_by_one:
-                print 'Do you want to delete branch %s [y/N]' % branch
-                ans = raw_input()
+                print('Do you want to delete branch %s [y/N]' % branch)
+                ans = input()
                 if ans == 'y' or ans == 'Y':
-                    print delete_branch(branch)
+                    print(delete_branch(branch))
             else:
-                    print delete_branch(branch)
+                    print(delete_branch(branch))
     
     if dry_run:
-        print '*****************************************************************'
-        print 'Did not actually delete anything yet, pass in --confirm to delete'
-        print 
+        print('*****************************************************************')
+        print('Did not actually delete anything yet, pass in --confirm to delete')
+        print() 
diff --git a/tools/dev/bin/branch-compare b/tools/dev/bin/branch-compare
index 2ea535d..24a82f1 100755
--- a/tools/dev/bin/branch-compare
+++ b/tools/dev/bin/branch-compare
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import os
 import re
@@ -42,7 +42,7 @@
   try:
     sourceRef, targetRef = sys.argv[1:3]
   except ValueError:
-    print 'branch-compare <source ref> <target ref>'
+    print('branch-compare <source ref> <target ref>')
 
   targetCommits = getCommits(sourceRef, targetRef)
   sourceCommits = getCommits(targetRef, sourceRef)
@@ -51,5 +51,5 @@
   
   for id in missingCommitsFromTarget:
     hash = sourceCommits[id]
-    print 'git cherry-pick', hash
-    print commitMsgs[hash] 
+    print('git cherry-pick', hash)
+    print(commitMsgs[hash]) 
diff --git a/tools/dev/bin/onos-gen-bazel-project b/tools/dev/bin/onos-gen-bazel-project
index 355193a..bb3c4a1 100755
--- a/tools/dev/bin/onos-gen-bazel-project
+++ b/tools/dev/bin/onos-gen-bazel-project
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 import os
 
 import subprocess
@@ -43,12 +43,12 @@
         "script_name": os.path.basename(__file__),
         "language_level": JAVA_LANGUAGE_LEVEL,
         "exclude_dirs": "\n".join(
-            map(lambda x: "  -" + x, EXCLUDE_DIRECTORIES)),
-        "targets": "\n".join(map(lambda x: "  " + x, all_targets)),
-        "test_sources": "\n".join(map(lambda x: "  " + x, TEST_SOURCES)),
+            ["  -" + x for x in EXCLUDE_DIRECTORIES]),
+        "targets": "\n".join(["  " + x for x in all_targets]),
+        "test_sources": "\n".join(["  " + x for x in TEST_SOURCES]),
     }
     return TEMPLATE.format(**data)
 
 
 if __name__ == "__main__":
-    print gen_project()
+    print(gen_project())
diff --git a/tools/dev/bin/onos-gen-p4-constants b/tools/dev/bin/onos-gen-p4-constants
index 07530d6..5a5aa06 100755
--- a/tools/dev/bin/onos-gen-p4-constants
+++ b/tools/dev/bin/onos-gen-p4-constants
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2.7
+#!/usr/bin/env python3
 # -*- utf-8 -*-
 import argparse
 import google.protobuf.text_format as tf
@@ -240,7 +240,7 @@
 
     if output == '-':
         # std output
-        print java_code
+        print(java_code)
     else:
         with open(output, 'w') as output_file:
             output_file.write(java_code)
diff --git a/tools/dev/bin/onos-split-logs b/tools/dev/bin/onos-split-logs
index 687019d..065d804 100755
--- a/tools/dev/bin/onos-split-logs
+++ b/tools/dev/bin/onos-split-logs
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Splits ONOS DEBUG logs by partition/session for debugging consistent primitives.
 # When logs are split, this script will create a separate log file for each partition
 # and each Atomix session, e.g. karaf.log.partition-1, karaf.log.session-10, etc.
diff --git a/tools/dev/mininet/examples/ha.py b/tools/dev/mininet/examples/ha.py
index 18f1222..1ec6932 100755
--- a/tools/dev/mininet/examples/ha.py
+++ b/tools/dev/mininet/examples/ha.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 """
 NOTES
@@ -196,13 +196,13 @@
     def start( self ):
         output( "(starting HTTP Server)" )
         # start python web server as a bg process
-        self.cmd( 'python -m SimpleHTTPServer &> web.log &' )
+        self.cmd( 'python3 -m SimpleHTTPServer &> web.log &' )
 
     def stop( self ):
         # XXX is this ever called?
-        print "Stopping HTTP Server..."
-        print self.cmd( 'fg' )
-        print self.cmd( '\x03' )  # ctrl-c
+        print("Stopping HTTP Server...")
+        print(self.cmd( 'fg' ))
+        print(self.cmd( '\x03' ))  # ctrl-c
 
 
 class DynamicONOSNode( onos.ONOSNode ):
@@ -278,7 +278,7 @@
                 l.rotate( -1 )
             return perms
 
-        print "Generating %s with %s" % ( location, str(nodes) )
+        print("Generating %s with %s" % ( location, str(nodes) ))
         port = 9876
         ips = [ node.IP() for node in nodes ]
         node = lambda k: { 'id': k, 'ip': k, 'port': port }
@@ -411,7 +411,7 @@
         for node in cluster.activeNodes:
             node.shouldStart = True
     else:
-        print "Incorrect test"
+        print("Incorrect test")
         return
     net.start()
     if args.interactive:
diff --git a/tools/dev/mininet/examples/multicluster.py b/tools/dev/mininet/examples/multicluster.py
index 29e2b56..1ad7c5b 100755
--- a/tools/dev/mininet/examples/multicluster.py
+++ b/tools/dev/mininet/examples/multicluster.py
@@ -1,5 +1,4 @@
-#!/usr/bin/python
-
+#!/usr/bin/python3
 """
 multicluster.py: multiple ONOS clusters example
 
@@ -85,7 +84,7 @@
         cmap.setdefault( c, [] ).append( s.name )
     for c in sorted( cmap.keys() ):
         switches = ' '.join( cmap[ c ] )
-        print '%s: %s' % ( c, switches )
+        print('%s: %s' % ( c, switches ))
 
 ONOSCLI.do_controllers = do_controllers
 
diff --git a/tools/dev/mininet/onos.py b/tools/dev/mininet/onos.py
index f8e3703..8e22e5b 100755
--- a/tools/dev/mininet/onos.py
+++ b/tools/dev/mininet/onos.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
 
 """
 onos.py: ONOS cluster and control network in Mininet
@@ -113,7 +113,7 @@
     # Get rid of stale junk
     for var in 'ONOS_CELL', 'ONOS_INSTANCES':
         env[ var ] = ''
-    for var in environ.keys():
+    for var in list(environ.keys()):
         if var.startswith( 'OC' ):
             env[ var ] = ''
     for index, node in enumerate( nodes, 1 ):
@@ -285,7 +285,7 @@
 
     def intfsDown( self ):
         """Bring all interfaces down"""
-        for intf in self.intfs.values():
+        for intf in list(self.intfs.values()):
             cmdOutput = intf.ifconfig( 'down' )
             # no output indicates success
             if cmdOutput:
@@ -293,7 +293,7 @@
 
     def intfsUp( self ):
         """Bring all interfaces up"""
-        for intf in self.intfs.values():
+        for intf in list(self.intfs.values()):
             cmdOutput = intf.ifconfig( 'up' )
             if cmdOutput:
                 error( "Error setting %s up: %s " % ( intf.name, cmdOutput ) )
@@ -338,7 +338,7 @@
     def memAvailable( self ):
         "Return available memory in KB (or -1 if we can't tell)"
         lines = open( '/proc/meminfo' ).read().strip().split( '\n' )
-        entries = map( str.split, lines )
+        entries = list(map( str.split, lines ))
         index = { entry[ 0 ]: entry for entry in entries }
         # Check MemAvailable if present
         default = ( None, '-1', 'kB' )
@@ -411,7 +411,7 @@
         "Update environment variables"
         cmd = ';'.join( ( 'export %s="%s"' % ( var, val )
                           if val else 'unset %s' % var )
-                        for var, val in envDict.iteritems() )
+                        for var, val in envDict.items() )
         self.cmd( cmd )
 
     def ucmd( self, *args, **_kwargs ):
diff --git a/tools/dev/p4vm/install-p4-tools.sh b/tools/dev/p4vm/install-p4-tools.sh
index 4bc4e04..e3ca954 100755
--- a/tools/dev/p4vm/install-p4-tools.sh
+++ b/tools/dev/p4vm/install-p4-tools.sh
@@ -88,13 +88,13 @@
         libtool \
         make \
         pkg-config \
-        python2.7 \
-        python2.7-dev \
+        python3 \
+        python3-dev \
         tcpdump \
         wget \
         unzip
 
-    sudo -H pip2.7 install setuptools cffi ipaddr ipaddress pypcap \
+    sudo -H pip3 install setuptools cffi ipaddr ipaddress pypcap \
         git+https://github.com/p4lang/scapy-vxlan \
         git+https://github.com/p4lang/ptf.git
 }
@@ -150,8 +150,8 @@
     # Hack to get the -std=c++11 flag when building 3.6.1
     # https://github.com/protocolbuffers/protobuf/blob/v3.6.1/python/setup.py#L208
     export KOKORO_BUILD_NUMBER="hack"
-    sudo -E python2.7 setup.py build --cpp_implementation
-    sudo -E pip2.7 install .
+    sudo -E python3 setup.py build --cpp_implementation
+    sudo -E pip3 install .
     unset KOKORO_BUILD_NUMBER
 }
 
@@ -180,8 +180,8 @@
     sudo ldconfig
     unset LDFLAGS
 
-    sudo pip2.7 install -r requirements.txt
-    sudo pip2.7 install .
+    sudo pip3 install -r requirements.txt
+    sudo pip3 install .
 }
 
 function checkout_bmv2 {
diff --git a/tools/dev/p4vm/root-bootstrap.sh b/tools/dev/p4vm/root-bootstrap.sh
index e1b9449..6b3bab1 100755
--- a/tools/dev/p4vm/root-bootstrap.sh
+++ b/tools/dev/p4vm/root-bootstrap.sh
@@ -42,8 +42,8 @@
     git \
     git-review \
     htop \
-    python2.7 \
-    python2.7-dev \
+    python3 \
+    python3-dev \
     valgrind \
     zip unzip \
     tcpdump \
@@ -65,14 +65,11 @@
 
 rm -f corretto.deb
 
-rm -f /usr/bin/python
-ln -s `which python2.7` /usr/bin/python
-
 # Install pip and some python deps (others are defined in install-p4-tools.sh)
 curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
-python2.7 get-pip.py --force-reinstall
+python3 get-pip.py --force-reinstall
 rm -f get-pip.py
-pip2.7 install ipaddress
+pip3 install ipaddress
 
 if [[ ${VM_TYPE} = "dev" ]]
 then
diff --git a/tools/dev/p4vm/upload-ova.sh b/tools/dev/p4vm/upload-ova.sh
index 0b2cfd3..2dbd4b4 100755
--- a/tools/dev/p4vm/upload-ova.sh
+++ b/tools/dev/p4vm/upload-ova.sh
@@ -2,5 +2,5 @@
 
 VM_TYPE=${P4_VM_TYPE:-dev}
 
-python $ONOS_ROOT/tools/build/uploadToS3.py -f onos-p4-${VM_TYPE}.ova ./onos-p4-${VM_TYPE}.ova
+python3 $ONOS_ROOT/tools/build/uploadToS3.py -f onos-p4-${VM_TYPE}.ova ./onos-p4-${VM_TYPE}.ova
 
diff --git a/tools/dev/vagrant/ansible/roles/common/tasks/main.yml b/tools/dev/vagrant/ansible/roles/common/tasks/main.yml
index c9d4dc5..c8e406f 100644
--- a/tools/dev/vagrant/ansible/roles/common/tasks/main.yml
+++ b/tools/dev/vagrant/ansible/roles/common/tasks/main.yml
@@ -21,6 +21,6 @@
 
 - name: Installing python3-lxc
   pip:
-    name: lxc-python2
+    name: python3-lxc
     state: present
   tags: [common]
\ No newline at end of file
diff --git a/tools/dev/vagrant/ansible/vars/global_vars.yml b/tools/dev/vagrant/ansible/vars/global_vars.yml
index cba95ef..cef41d9 100644
--- a/tools/dev/vagrant/ansible/vars/global_vars.yml
+++ b/tools/dev/vagrant/ansible/vars/global_vars.yml
@@ -38,8 +38,8 @@
   - "git-review"
   - "lxc"
   - "lxc-dev"
-  - "python-dev"
-  - "python-pip"
+  - "python3-dev"
+  - "python3-pip"
   - "unzip"
   - "zip"
 
@@ -106,7 +106,7 @@
     user: "optical"
     pass: $6$rounds=656000$Fdw89xOiuYlJAKpi$dK6wqIVaJpn96XBxZbcwZbg2mAuPdGbNEUfJaLV1dqC/SFtdrNIWXjxCobIefy3AVMdgobZl9D3OACtt8LkTz/
     cell: "1node"
-    mininet_exec: sudo -E python /home/ubuntu/onos/tools/test/topos/opticalTest.py {{ lxc.lxc_one.ip }}
+    mininet_exec: sudo -E python3 /home/ubuntu/onos/tools/test/topos/opticalTest.py {{ lxc.lxc_one.ip }}
     lincoe_exec: sudo /home/ubuntu/linc-oe/rel/linc/bin/linc attach
     reset_exec: /home/ubuntu/reset-to-1.sh proxyarp,optical
     url: "https://wiki.onosproject.org/display/ONOS/Packet+Optical+Tutorial"