[ovs-dev] [PATCH v3] Require Python 3 and remove support for Python 2.

Ben Pfaff blp at ovn.org
Wed Sep 25 16:40:19 UTC 2019


Numan, please (re-)review this when you have time.

On Fri, Sep 20, 2019 at 08:44:48AM -0700, Ben Pfaff wrote:
> Python 2 reaches end-of-life on January 1, 2020, which is only
> a few months away.  This means that OVS needs to stop depending
> on in the next release that should occur roughly that same time.
> Therefore, this commit removes all support for Python 2.  It
> also makes Python 3 a mandatory build dependency.
> 
> Some of the interesting consequences:
> 
> - HAVE_PYTHON, HAVE_PYTHON2, and HAVE_PYTHON3 conditionals have
>   been removed, since we now know that Python3 is available.
> 
> - $PYTHON and $PYTHON2 are removed, and $PYTHON3 is always
>   available.
> 
> - Many tests for Python 2 support have been removed, and the ones
>   that depended on Python 3 now run unconditionally.  This allowed
>   several macros in the testsuite to be removed, making the code
>   clearer.  This does make some of the changes to the testsuite
>   files large due to indentation level changes.
> 
> - #! lines for Python now use /usr/bin/python3 instead of
>   /usr/bin/python.
> 
> - Packaging depends on Python 3 packages.
> ---
> v1->v2: Bug fixes.
> v2->v3: Update RPM spec file for Fedora packaging to delete the
>   Python 2 packaging and to move ovstest into the Python 3
>   packaging.  This is going to break compatibility with older
>   Fedora and RHEL releases that don't have Python 3.  I do not
>   know whether this is important, and I don't know how to really
>   avoid it if it is.  Comments requested.
> 
>  .cirrus.yml                                   |   3 +-
>  .travis/osx-prepare.sh                        |   4 +-
>  Documentation/intro/install/fedora.rst        |   4 +-
>  Documentation/intro/install/general.rst       |   8 +-
>  Documentation/intro/install/netbsd.rst        |  10 +-
>  Documentation/intro/install/rhel.rst          |   2 +-
>  Documentation/intro/install/windows.rst       |   4 +-
>  Documentation/intro/install/xenserver.rst     |   4 +-
>  Makefile.am                                   |  12 +-
>  Vagrantfile                                   |  24 +-
>  Vagrantfile-FreeBSD                           |   2 +-
>  appveyor.yml                                  |   2 +-
>  build-aux/check-structs                       |   2 +-
>  build-aux/extract-ofp-actions                 |   2 +-
>  build-aux/extract-ofp-errors                  |   2 +-
>  build-aux/extract-ofp-fields                  |   2 +-
>  build-aux/extract-ofp-msgs                    |   2 +-
>  build-aux/sodepends.py                        |   2 +-
>  build-aux/soexpand.py                         |   2 +-
>  build-aux/text2c                              |   2 +-
>  build-aux/xml2nroff                           |   2 +-
>  configure.ac                                  |   3 +-
>  debian/.gitignore                             |   1 +
>  debian/automake.mk                            |   4 +-
>  debian/control                                |  35 +-
>  debian/openvswitch-test.install               |   2 +-
>  debian/python-openvswitch.install             |   1 -
>  ...nvswitch.dirs => python3-openvswitch.dirs} |   0
>  debian/python3-openvswitch.install            |   1 +
>  debian/rules                                  |   2 +-
>  include/openflow/automake.mk                  |   2 -
>  ipsec/ovs-monitor-ipsec.in                    |   2 +-
>  m4/openvswitch.m4                             | 101 +---
>  manpages.mk                                   |   6 -
>  ovn/automake.mk                               |   8 +-
>  ovsdb/ovsdb-dot.in                            |   2 +-
>  ovsdb/ovsdb-idlc.in                           |   2 +-
>  python/automake.mk                            |   9 +-
>  rhel/openvswitch-fedora.spec.in               |  45 +-
>  tests/atlocal.in                              |  42 +-
>  tests/automake.mk                             |   2 +-
>  tests/check-structs.at                        |   3 +-
>  tests/checkpatch.at                           |  17 +-
>  tests/daemon-py.at                            | 453 ++++++++----------
>  tests/flowgen.py                              |   2 +-
>  tests/interface-reconfigure.at                |   2 +-
>  tests/json.at                                 |  57 +--
>  tests/jsonrpc-py.at                           |  67 +--
>  tests/library.at                              |  42 +-
>  tests/ofproto-dpif.at                         |  10 +-
>  tests/ofproto.at                              |   4 +-
>  tests/ovs-macros.at                           |   2 +-
>  tests/ovs-xapi-sync.at                        |   3 +-
>  tests/ovsdb-data.at                           |   9 +-
>  tests/ovsdb-idl.at                            | 188 ++------
>  tests/ovsdb-macros.at                         |  52 +-
>  tests/ovsdb-monitor.at                        |  20 +-
>  tests/reconnect.at                            |  13 +-
>  tests/system-common-macros.at                 |   2 +-
>  tests/system-kmod-macros.at                   |   3 +-
>  tests/system-traffic.at                       |  16 +-
>  tests/system-userspace-macros.at              |   4 +-
>  tests/unixctl-py.at                           | 208 ++++----
>  tests/vlog.at                                 | 219 ++++-----
>  utilities/automake.mk                         |   5 +-
>  utilities/bugtool/automake.mk                 |   2 -
>  utilities/bugtool/ovs-bugtool.in              |   2 +-
>  utilities/checkpatch.py                       |   2 +-
>  utilities/ovs-check-dead-ifs.in               |   2 +-
>  utilities/ovs-dpctl-top.in                    |   2 +-
>  utilities/ovs-l3ping.in                       |   2 +-
>  utilities/ovs-parse-backtrace.in              |   2 +-
>  utilities/ovs-pcap.in                         |   2 +-
>  utilities/ovs-tcpdump.in                      |   2 +-
>  utilities/ovs-tcpundump.in                    |   2 +-
>  utilities/ovs-test.in                         |   2 +-
>  utilities/ovs-vlan-test.in                    |   2 +-
>  vswitchd/automake.mk                          |   4 +-
>  vtep/automake.mk                              |   4 +-
>  vtep/ovs-vtep.in                              |   2 +-
>  80 files changed, 651 insertions(+), 1151 deletions(-)
>  delete mode 100644 debian/python-openvswitch.install
>  rename debian/{python-openvswitch.dirs => python3-openvswitch.dirs} (100%)
>  create mode 100644 debian/python3-openvswitch.install
> 
> diff --git a/.cirrus.yml b/.cirrus.yml
> index eb6af0a719c8..bae5a089b248 100644
> --- a/.cirrus.yml
> +++ b/.cirrus.yml
> @@ -9,8 +9,7 @@ freebsd_build_task:
>  
>    env:
>      DEPENDENCIES: automake libtool gmake gcc wget openssl
> -                  python py27-six py27-sphinx py27-openssl
> -                  python3 py36-six py36-openssl
> +                  python3 py36-six py36-openssl p36-sphinx
>      matrix:
>        COMPILER: gcc
>        COMPILER: clang
> diff --git a/.travis/osx-prepare.sh b/.travis/osx-prepare.sh
> index 58ccb67cddbd..78d5bb579217 100755
> --- a/.travis/osx-prepare.sh
> +++ b/.travis/osx-prepare.sh
> @@ -1,4 +1,4 @@
>  #!/bin/bash
>  set -ev
> -pip2 install --user six
> -pip2 install --user --upgrade docutils
> +pip3 install --user six
> +pip3 install --user --upgrade docutils
> diff --git a/Documentation/intro/install/fedora.rst b/Documentation/intro/install/fedora.rst
> index f11d05a01041..6fe1fb5b2468 100644
> --- a/Documentation/intro/install/fedora.rst
> +++ b/Documentation/intro/install/fedora.rst
> @@ -102,7 +102,7 @@ in which `./configure` was executed:
>  
>      $ make rpm-fedora
>  
> -This will create the RPMs `openvswitch`, `python-openvswitch`,
> +This will create the RPMs `openvswitch`, `python3-openvswitch`,
>  `openvswitch-test`, `openvswitch-devel` and `openvswitch-debuginfo`.
>  
>  To enable DPDK support in the openvswitch package, the ``--with dpdk`` option
> @@ -151,7 +151,7 @@ Refer to the :doc:`/faq/index` for more information about the various Open
>  vSwitch datapath options.
>  
>  In most cases only the `openvswitch` RPM will need to be installed. The
> -`python-openvswitch`, `openvswitch-test`, `openvswitch-devel`, and
> +`python3-openvswitch`, `openvswitch-test`, `openvswitch-devel`, and
>  `openvswitch-debuginfo` RPMs are optional unless required for a specific
>  purpose.
>  
> diff --git a/Documentation/intro/install/general.rst b/Documentation/intro/install/general.rst
> index b03d70f6fa6e..e62501be7fc1 100644
> --- a/Documentation/intro/install/general.rst
> +++ b/Documentation/intro/install/general.rst
> @@ -90,8 +90,8 @@ need the following software:
>    If libcap-ng is installed, then Open vSwitch will automatically build with
>    support for it.
>  
> -- Python 2.7. You must also have the Python ``six`` library version 1.4.0
> -  or later.
> +- Python 3.4 or later. You must also have the Python ``six`` library
> +  version 1.4.0 or later.
>  
>  - Unbound library, from http://www.unbound.net, is optional but recommended if
>    you want to enable ovs-vswitchd and other utilities to use DNS names when
> @@ -203,8 +203,8 @@ simply install and run Open vSwitch you require the following software:
>    from iproute2 (part of all major distributions and available at
>    https://wiki.linuxfoundation.org/networking/iproute2).
>  
> -- Python 2.7. You must also have the Python six library version 1.4.0
> -  or later.
> +- Python 3.4 or later. You must also have the Python six library
> +  version 1.4.0 or later.
>  
>  On Linux you should ensure that ``/dev/urandom`` exists. To support TAP
>  devices, you must also ensure that ``/dev/net/tun`` exists.
> diff --git a/Documentation/intro/install/netbsd.rst b/Documentation/intro/install/netbsd.rst
> index 7eb7f0cebbaf..4f60dad869b6 100644
> --- a/Documentation/intro/install/netbsd.rst
> +++ b/Documentation/intro/install/netbsd.rst
> @@ -31,20 +31,18 @@ you need at least the following packages.
>  - automake
>  - libtool-base
>  - gmake
> -- python27
> -- py27-six
> -- py27-xml
> +- python37
> +- py37-six
>  
>  Some components have additional requirements. Refer to :doc:`general` for more
>  information.
>  
> -Assuming you are running NetBSD/amd64 6.1.2, you can download and install
> +Assuming you are running NetBSD/amd64 7.0.2, you can download and install
>  pre-built binary packages as the following::
>  
>      $ PKG_PATH=http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/7.0.2/All/
>      $ export PKG_PATH
> -    $ pkg_add automake libtool-base gmake python27 py27-six py27-xml \
> -        pkg_alternatives
> +    $ pkg_add automake libtool-base gmake python37 py37-six pkg_alternatives
>  
>  .. note::
>    You might get some warnings about minor version mismatch. These can be safely
> diff --git a/Documentation/intro/install/rhel.rst b/Documentation/intro/install/rhel.rst
> index 0e5ca2743ef5..17b3bc26f11d 100644
> --- a/Documentation/intro/install/rhel.rst
> +++ b/Documentation/intro/install/rhel.rst
> @@ -92,7 +92,7 @@ Once that is completed, remove the file ``/tmp/ovs.spec``.
>  If python3-sphinx package is not available in your version of RHEL, you can
>  install it via pip with 'pip install sphinx'.
>  
> -Open vSwitch requires python 2.7 or newer which is not available in older
> +Open vSwitch requires python 3.4 or newer which is not available in older
>  distributions. In the case of RHEL 6.x and its derivatives, one option is
>  to install python34 and python34-six from `EPEL`_.
>  
> diff --git a/Documentation/intro/install/windows.rst b/Documentation/intro/install/windows.rst
> index f696d2c9b621..019e83e64425 100644
> --- a/Documentation/intro/install/windows.rst
> +++ b/Documentation/intro/install/windows.rst
> @@ -56,9 +56,9 @@ The following explains the steps in some detail.
>  
>        'C:/MinGW /mingw'.
>  
> -- Python
> +- Python 3.4 or later.
>  
> -  Install the latest Python 2.x from python.org and verify that its path is
> +  Install the latest Python 3.x from python.org and verify that its path is
>    part of Windows' PATH environment variable.
>    We require that you have Python six and pypiwin32 libraries installed.
>    The libraries can be installed via pip command:
> diff --git a/Documentation/intro/install/xenserver.rst b/Documentation/intro/install/xenserver.rst
> index c0f5e3156697..366e11ac27ad 100644
> --- a/Documentation/intro/install/xenserver.rst
> +++ b/Documentation/intro/install/xenserver.rst
> @@ -30,8 +30,8 @@ XenServer host.  If you want to install Open vSwitch on a generic Linux or BSD
>  host, refer to :doc:`general` instead.
>  
>  Open vSwitch should work with XenServer 5.6.100 and later.  However, Open
> -vSwitch requires Python 2.7 or later, so using Open vSwitch with XenServer 6.5
> -or earlier requires installing Python 2.7.
> +vSwitch requires Python 3.4 or later, so using Open vSwitch with XenServer 6.5
> +or earlier requires installing Python 3.x.
>  
>  Building
>  --------
> diff --git a/Makefile.am b/Makefile.am
> index ff1f94b4841f..6030cdb495d6 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -60,7 +60,7 @@ endif
>  # foo/__init__.pyc will cause Python to ignore foo.py.
>  run_python = \
>  	PYTHONPATH=$(top_srcdir)/python$(psep)$$PYTHONPATH \
> -	PYTHONDONTWRITEBYTECODE=yes $(PYTHON)
> +	PYTHONDONTWRITEBYTECODE=yes $(PYTHON3)
>  
>  ALL_LOCAL =
>  BUILT_SOURCES =
> @@ -147,13 +147,13 @@ ro_shell = printf '\043 Generated automatically -- do not modify!    -*- buffer-
>  
>  SUFFIXES += .in
>  .in:
> -	$(AM_V_GEN)PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON) $(srcdir)/build-aux/soexpand.py -I$(srcdir) < $< | \
> -	  $(PYTHON) $(srcdir)/build-aux/dpdkstrip.py $(DPDKSTRIP_FLAGS) | \
> +	$(AM_V_GEN)PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON3) $(srcdir)/build-aux/soexpand.py -I$(srcdir) < $< | \
> +	  $(PYTHON3) $(srcdir)/build-aux/dpdkstrip.py $(DPDKSTRIP_FLAGS) | \
>  	  sed \
>  	    -e 's,[@]PKIDIR[@],$(PKIDIR),g' \
>  	    -e 's,[@]LOGDIR[@],$(LOGDIR),g' \
>  	    -e 's,[@]DBDIR[@],$(DBDIR),g' \
> -	    -e 's,[@]PYTHON[@],$(PYTHON),g' \
> +	    -e 's,[@]PYTHON3[@],$(PYTHON3),g' \
>  	    -e 's,[@]RUNDIR[@],$(RUNDIR),g' \
>  	    -e 's,[@]VERSION[@],$(VERSION),g' \
>  	    -e 's,[@]localstatedir[@],$(localstatedir),g' \
> @@ -177,7 +177,7 @@ SUFFIXES += .xml
>  	  PKIDIR='$(PKIDIR)' \
>  	  LOGDIR='$(LOGDIR)' \
>  	  DBDIR='$(DBDIR)' \
> -	  PYTHON='$(PYTHON)' \
> +	  PYTHON3='$(PYTHON3)' \
>  	  RUNDIR='$(RUNDIR)' \
>  	  VERSION='$(VERSION)' \
>  	  localstatedir='$(localstatedir)' \
> @@ -414,7 +414,7 @@ CLEANFILES += flake8-check
>  
>  include $(srcdir)/manpages.mk
>  $(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py python/build/soutil.py
> -	@PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON) $(srcdir)/build-aux/sodepends.py -I. -I$(srcdir) $(MAN_ROOTS) >$(@F).tmp
> +	@PYTHONPATH=$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON3) $(srcdir)/build-aux/sodepends.py -I. -I$(srcdir) $(MAN_ROOTS) >$(@F).tmp
>  	@if cmp -s $(@F).tmp $@; then \
>  	  touch $@; \
>  	  rm -f $(@F).tmp; \
> diff --git a/Vagrantfile b/Vagrantfile
> index fbd772a1bec5..236e3a7bdcb7 100644
> --- a/Vagrantfile
> +++ b/Vagrantfile
> @@ -8,12 +8,14 @@ Vagrant.require_version ">=1.7.0"
>  $bootstrap_fedora = <<SCRIPT
>  dnf -y update
>  dnf -y install autoconf automake openssl-devel libtool \
> -               python-devel python3-devel \
> -               python-twisted python-zope-interface \
> +               python3-devel \
> +               python3-twisted python3-zope-interface \
>                 desktop-file-utils groff graphviz rpmdevtools nc curl \
> -               wget python-six pyftpdlib checkpolicy selinux-policy-devel \
> -               libcap-ng-devel kernel-devel-`uname -r` ethtool python-tftpy \
> +               wget python3-six python3-pyftpdlib checkpolicy \
> +               selinux-policy-devel \
> +               libcap-ng-devel kernel-devel-`uname -r` ethtool python3-pip \
>                 lftp
> +pip-3 install tftpy             # Not yet available for Python3 via dnf.
>  echo "search extra update built-in" >/etc/depmod.d/search_path.conf
>  SCRIPT
>  
> @@ -24,21 +26,23 @@ aptitude -y install -R \
>                  build-essential dpkg-dev lintian devscripts fakeroot \
>                  debhelper dh-autoreconf uuid-runtime \
>                  autoconf automake libtool \
> -                python-all python-twisted-core python-twisted-conch \
> +                python3-all python3-twisted-core python3-twisted-conch \
>                  xdg-utils groff graphviz netcat curl \
> -                wget python-six ethtool \
> -                libcap-ng-dev libssl-dev python-dev openssl \
> -                python-pyftpdlib python-flake8 python-tftpy \
> +                wget python3-six ethtool \
> +                libcap-ng-dev libssl-dev python3-dev openssl \
> +                python3-pyftpdlib python3-flake8 \
>                  linux-headers-`uname -r` \
>                  lftp
> +pip-3 install tftpy             # Not yet available for Python3 via apt.
>  SCRIPT
>  
>  $bootstrap_centos = <<SCRIPT
>  yum -y update
>  yum -y install autoconf automake openssl-devel libtool \
> -               python-twisted-core python-zope-interface \
> +               python3-twisted-core python3-zope-interface \
>                 desktop-file-utils groff graphviz rpmdevtools nc curl \
> -               wget python-six pyftpdlib checkpolicy selinux-policy-devel \
> +               wget python3-six python3-pyftpdlib checkpolicy \
> +               selinux-policy-devel \
>                 libcap-ng-devel kernel-devel-`uname -r` ethtool net-tools \
>                 lftp
>  SCRIPT
> diff --git a/Vagrantfile-FreeBSD b/Vagrantfile-FreeBSD
> index 52599eefaebe..d978faa1c2fe 100644
> --- a/Vagrantfile-FreeBSD
> +++ b/Vagrantfile-FreeBSD
> @@ -12,7 +12,7 @@ Vagrant.require_version ">=1.7.0"
>  $bootstrap_freebsd = <<SCRIPT
>  sed  -e 's/\#DEFAULT_ALWAYS_YES = false/DEFAULT_ALWAYS_YES = true/g' -e 's/\#ASSUME_ALWAYS_YES = false/ASSUME_ALWAYS_YES = true/g' /usr/local/etc/pkg.conf > /tmp/pkg.conf
>  mv -f /tmp/pkg.conf /usr/local/etc/pkg.conf
> -pkg install automake libtool wget python py27-six gmake lftp
> +pkg install automake libtool wget py37 py37-six gmake lftp
>  SCRIPT
>  
>  $configure_ovs = <<SCRIPT
> diff --git a/appveyor.yml b/appveyor.yml
> index 2e5c37a37adc..b301227445d0 100644
> --- a/appveyor.yml
> +++ b/appveyor.yml
> @@ -33,7 +33,7 @@ init:
>  
>      cd C:\openvswitch
>  
> -    python -m pip install six pypiwin32 --disable-pip-version-check
> +    python3 -m pip install six pypiwin32 --disable-pip-version-check
>  
>  build_script:
>  - '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd"'
> diff --git a/build-aux/check-structs b/build-aux/check-structs
> index 37ffa06b3ab3..2c088b446943 100755
> --- a/build-aux/check-structs
> +++ b/build-aux/check-structs
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import os.path
>  import sys
> diff --git a/build-aux/extract-ofp-actions b/build-aux/extract-ofp-actions
> index 64de0f31f4a0..2d1dbe70973f 100755
> --- a/build-aux/extract-ofp-actions
> +++ b/build-aux/extract-ofp-actions
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import getopt
>  import sys
> diff --git a/build-aux/extract-ofp-errors b/build-aux/extract-ofp-errors
> index 03f40ea3e4c2..2c3fbfc881b1 100755
> --- a/build-aux/extract-ofp-errors
> +++ b/build-aux/extract-ofp-errors
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import sys
>  import os.path
> diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
> index 7a4e8e170171..8766995d9ab1 100755
> --- a/build-aux/extract-ofp-fields
> +++ b/build-aux/extract-ofp-fields
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import getopt
>  import sys
> diff --git a/build-aux/extract-ofp-msgs b/build-aux/extract-ofp-msgs
> index 3d50724aebd3..6b3295cf64c2 100755
> --- a/build-aux/extract-ofp-msgs
> +++ b/build-aux/extract-ofp-msgs
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import sys
>  import os.path
> diff --git a/build-aux/sodepends.py b/build-aux/sodepends.py
> index 90cfaa0f7fb4..45812bcbd700 100755
> --- a/build-aux/sodepends.py
> +++ b/build-aux/sodepends.py
> @@ -1,4 +1,4 @@
> -#! /usr/bin/env python
> +#! /usr/bin/env python3
>  
>  # Copyright (c) 2008, 2011, 2017 Nicira, Inc.
>  #
> diff --git a/build-aux/soexpand.py b/build-aux/soexpand.py
> index 53ca640739fe..00adcf47a356 100755
> --- a/build-aux/soexpand.py
> +++ b/build-aux/soexpand.py
> @@ -1,4 +1,4 @@
> -#! /usr/bin/env python
> +#! /usr/bin/env python3
>  
>  # Copyright (c) 2008, 2017 Nicira, Inc.
>  #
> diff --git a/build-aux/text2c b/build-aux/text2c
> index cb1f256f1775..dca58648b90c 100755
> --- a/build-aux/text2c
> +++ b/build-aux/text2c
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  import re
>  import sys
> diff --git a/build-aux/xml2nroff b/build-aux/xml2nroff
> index bd4e87928e4f..ee5553f4564e 100755
> --- a/build-aux/xml2nroff
> +++ b/build-aux/xml2nroff
> @@ -1,4 +1,4 @@
> -#! /usr/bin/python
> +#! /usr/bin/python3
>  
>  # Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
>  #
> diff --git a/configure.ac b/configure.ac
> index 1d45c4fdd153..afd1e83450eb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -92,9 +92,8 @@ OVS_CHECK_NETLINK
>  OVS_CHECK_OPENSSL
>  OVS_CHECK_LIBCAPNG
>  OVS_CHECK_LOGDIR
> -OVS_CHECK_PYTHON2
>  OVS_CHECK_PYTHON3
> -OVS_CHECK_PYTHON
> +OVS_CHECK_SIX
>  OVS_CHECK_FLAKE8
>  OVS_CHECK_SPHINX
>  OVS_CHECK_DOT
> diff --git a/debian/.gitignore b/debian/.gitignore
> index 441a8ffb702d..d02526b21fa7 100644
> --- a/debian/.gitignore
> +++ b/debian/.gitignore
> @@ -23,4 +23,5 @@
>  /openvswitch-testcontroller
>  /openvswitch-vtep
>  /python-openvswitch
> +/python3-openvswitch
>  /tmp
> diff --git a/debian/automake.mk b/debian/automake.mk
> index 03a1d68c2635..37b1a243390c 100644
> --- a/debian/automake.mk
> +++ b/debian/automake.mk
> @@ -52,8 +52,8 @@ EXTRA_DIST += \
>  	debian/openvswitch-vtep.init \
>  	debian/openvswitch-vtep.install \
>  	debian/openvswitch-vtep.manpages \
> -	debian/python-openvswitch.dirs \
> -	debian/python-openvswitch.install \
> +	debian/python3-openvswitch.dirs \
> +	debian/python3-openvswitch.install \
>  	debian/rules \
>  	debian/rules.modules \
>  	debian/ifupdown.sh \
> diff --git a/debian/control b/debian/control
> index 2ad35f2cea6f..ad4b187860f3 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -13,10 +13,10 @@ Build-Depends: graphviz,
>                 libtool,
>                 openssl,
>                 procps,
> -               python-all (>= 2.7),
> -               python-twisted-conch,
> -               python-zopeinterface,
> -               python-six,
> +               python3-all,
> +               python3-twisted-conch,
> +               python3-zopeinterface,
> +               python3-six,
>                 libunbound-dev
>  Standards-Version: 3.9.3
>  Homepage: http://openvswitch.org/
> @@ -41,7 +41,7 @@ Description: Open vSwitch datapath module source - module-assistant version
>  
>  Package: openvswitch-datapath-dkms
>  Architecture: all
> -Depends: dkms (>= 1.95), libc6-dev, libelf-dev, make, ${misc:Depends}, ${python:Depends}
> +Depends: dkms (>= 1.95), libc6-dev, libelf-dev, make, ${misc:Depends}, ${python3:Depends}
>  Description: Open vSwitch datapath module source - DKMS version
>   Open vSwitch is a production quality, multilayer, software-based,
>   Ethernet virtual switch. It is designed to enable massive network
> @@ -58,8 +58,8 @@ Description: Open vSwitch datapath module source - DKMS version
>  Package: openvswitch-common
>  Architecture: linux-any
>  Multi-Arch: foreign
> -Depends: python (>= 2.7),
> -         python-six,
> +Depends: python3,
> +         python3-six,
>           libopenvswitch (= ${binary:Version}),
>           ${misc:Depends},
>           ${shlibs:Depends}
> @@ -102,10 +102,9 @@ Depends: kmod | module-init-tools,
>           netbase,
>           openvswitch-common (= ${binary:Version}),
>           procps,
> -         python-argparse,
>           uuid-runtime,
>           ${misc:Depends},
> -         ${python:Depends},
> +         ${python3:Depends},
>           ${shlibs:Depends}
>  Description: Open vSwitch switch implementations
>   Open vSwitch is a production quality, multilayer, software-based,
> @@ -171,10 +170,10 @@ Description: Debug symbols for Open vSwitch packages
>   packages.  Install it to debug one of them or to examine a core dump
>   produced by one of them.
>  
> -Package: python-openvswitch
> +Package: python3-openvswitch
>  Architecture: all
>  Section: python
> -Depends: ${misc:Depends}, ${python:Depends}, python-six
> +Depends: ${misc:Depends}, ${python3:Depends}, python3-six
>  Description: Python bindings for Open vSwitch
>   Open vSwitch is a production quality, multilayer, software-based,
>   Ethernet virtual switch. It is designed to enable massive network
> @@ -188,10 +187,10 @@ Description: Python bindings for Open vSwitch
>  
>  Package: openvswitch-test
>  Architecture: all
> -Depends: python (>= 2.7) | python-argparse,
> -         python-twisted-web,
> +Depends: python3,
> +         python3-twisted-web,
>           ${misc:Depends},
> -         ${python:Depends}
> +         ${python3:Depends}
>  Description: Open vSwitch test package
>   Open vSwitch is a production quality, multilayer, software-based,
>   Ethernet virtual switch. It is designed to enable massive network
> @@ -208,8 +207,8 @@ Package: openvswitch-vtep
>  Architecture: linux-any
>  Depends: openvswitch-common (>= ${binary:Version}),
>           openvswitch-switch (>= ${binary:Version}),
> -         python,
> -         python-openvswitch (>= ${source:Version}),
> +         python3,
> +         python3-openvswitch (>= ${source:Version}),
>           ${misc:Depends},
>           ${shlibs:Depends}
>  Description: Open vSwitch VTEP utilities
> @@ -250,8 +249,8 @@ Architecture: linux-any
>  Depends: iproute2,
>           openvswitch-common (= ${binary:Version}),
>           openvswitch-switch (= ${binary:Version}),
> -         python,
> -         python-openvswitch (= ${source:Version}),
> +         python3,
> +         python3-openvswitch (= ${source:Version}),
>           strongswan,
>           ${misc:Depends},
>           ${shlibs:Depends}
> diff --git a/debian/openvswitch-test.install b/debian/openvswitch-test.install
> index 8a01a51259b7..cb371c906d94 100644
> --- a/debian/openvswitch-test.install
> +++ b/debian/openvswitch-test.install
> @@ -1,3 +1,3 @@
>  usr/bin/ovs-l3ping
>  usr/bin/ovs-test
> -usr/share/openvswitch/python/ovstest usr/lib/python2.7/dist-packages/
> +usr/share/openvswitch/python/ovstest usr/lib/python3.7/dist-packages/
> diff --git a/debian/python-openvswitch.install b/debian/python-openvswitch.install
> deleted file mode 100644
> index 0472d413f627..000000000000
> --- a/debian/python-openvswitch.install
> +++ /dev/null
> @@ -1 +0,0 @@
> -usr/share/openvswitch/python/ovs usr/lib/python2.7/dist-packages/
> diff --git a/debian/python-openvswitch.dirs b/debian/python3-openvswitch.dirs
> similarity index 100%
> rename from debian/python-openvswitch.dirs
> rename to debian/python3-openvswitch.dirs
> diff --git a/debian/python3-openvswitch.install b/debian/python3-openvswitch.install
> new file mode 100644
> index 000000000000..7ba956e3be63
> --- /dev/null
> +++ b/debian/python3-openvswitch.install
> @@ -0,0 +1 @@
> +usr/share/openvswitch/python/ovs usr/lib/python3.7/dist-packages/
> diff --git a/debian/rules b/debian/rules
> index 77f3a19841e5..4dc05c39ba6c 100755
> --- a/debian/rules
> +++ b/debian/rules
> @@ -22,7 +22,7 @@ PARALLEL =
>  endif
>  
>  %:
> -	dh $@ --with autoreconf,python2 --parallel
> +	dh $@ --with autoreconf,python3 --parallel
>  
>  # use --as-needed only if supported by dh-autoreconf (to simplify backporting)
>  DH_AS_NEEDED=$(shell dpkg --compare-versions $$(dpkg --status dh-autoreconf | grep Version | cut -d' ' -f2) ge 6 && echo --as-needed)
> diff --git a/include/openflow/automake.mk b/include/openflow/automake.mk
> index 18cc649899f8..a1d75756c9d7 100644
> --- a/include/openflow/automake.mk
> +++ b/include/openflow/automake.mk
> @@ -12,7 +12,6 @@ openflowinclude_HEADERS = \
>  	include/openflow/openflow-common.h \
>  	include/openflow/openflow.h
>  
> -if HAVE_PYTHON
>  SUFFIXES += .h .hstamp
>  
>  .h.hstamp:
> @@ -23,7 +22,6 @@ HSTAMP_FILES = $(openflowinclude_HEADERS:.h=.hstamp)
>  CLEANFILES += $(HSTAMP_FILES)
>  ALL_LOCAL += $(HSTAMP_FILES)
>  $(HSTAMP_FILES): build-aux/check-structs $(openflowinclude_HEADERS)
> -endif
>  
>  EXTRA_DIST += build-aux/check-structs
>  
> diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in
> index 4710be039ac7..37e370324562 100755
> --- a/ipsec/ovs-monitor-ipsec.in
> +++ b/ipsec/ovs-monitor-ipsec.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  # Copyright (c) 2017 Nicira, Inc.
>  #
>  # Licensed under the Apache License, Version 2.0 (the "License");
> diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
> index 4379d16b4203..78d70fb4e17e 100644
> --- a/m4/openvswitch.m4
> +++ b/m4/openvswitch.m4
> @@ -354,57 +354,16 @@ dnl Checks for valgrind/valgrind.h.
>  AC_DEFUN([OVS_CHECK_VALGRIND],
>    [AC_CHECK_HEADERS([valgrind/valgrind.h])])
>  
> -dnl Checks for Python 2.x, x >= 7.
> -AC_DEFUN([OVS_CHECK_PYTHON2],
> -  [AC_CACHE_CHECK(
> -     [for Python 2.x for x >= 7],
> -     [ovs_cv_python2],
> -     [if test -n "$PYTHON2"; then
> -        ovs_cv_python2=$PYTHON2
> -      else
> -        ovs_cv_python2=no
> -        for binary in python2 python2.7 python; do
> -          ovs_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> -          for dir in $PATH; do
> -            IFS=$ovs_save_IFS
> -            test -z "$dir" && dir=.
> -            if test -x "$dir"/"$binary" && "$dir"/"$binary" -c 'import sys
> -if sys.hexversion >= 0x02070000 and sys.hexversion < 0x03000000:
> -    sys.exit(0)
> -else:
> -    sys.exit(1)'; then
> -              ovs_cv_python2=$dir/$binary
> -              break 2
> -            fi
> -          done
> -        done
> -        if test "$ovs_cv_python2" != no && test -x "$ovs_cv_python2"; then
> -          if ! "$ovs_cv_python2" -c 'import six ; six.moves.range' >&AS_MESSAGE_LOG_FD 2>&1; then
> -            ovs_cv_python2=no
> -            AC_MSG_WARN([Missing Python six library or version too old.])
> -          fi
> -        fi
> -      fi])
> -   AC_SUBST([HAVE_PYTHON2])
> -   AM_MISSING_PROG([PYTHON2], [python2])
> -   if test "$ovs_cv_python2" != no; then
> -     PYTHON2=$ovs_cv_python2
> -     HAVE_PYTHON2=yes
> -   else
> -     HAVE_PYTHON2=no
> -   fi
> -   AM_CONDITIONAL([HAVE_PYTHON2], [test "$HAVE_PYTHON2" = yes])])
> -
> -dnl Checks for Python 3.x, x >= 4.
> +dnl Checks for Python 3.4 or later.
>  AC_DEFUN([OVS_CHECK_PYTHON3],
>    [AC_CACHE_CHECK(
> -     [for Python 3.x for x >= 4],
> +     [for Python 3 (version 3.4 or later)],
>       [ovs_cv_python3],
>       [if test -n "$PYTHON3"; then
>          ovs_cv_python3=$PYTHON3
>        else
>          ovs_cv_python3=no
> -        for binary in python3 python3.4; do
> +        for binary in python3 python3.4 python3.5 python3.6 python3.7; do
>            ovs_save_IFS=$IFS; IFS=$PATH_SEPARATOR
>            for dir in $PATH; do
>              IFS=$ovs_save_IFS
> @@ -419,46 +378,24 @@ else:
>              fi
>            done
>          done
> -        if test "$ovs_cv_python3" != no; then
> -          if test -x "$ovs_cv_python3" && ! "$ovs_cv_python3" -c 'import six' >/dev/null 2>&1; then
> -            ovs_cv_python3=no
> -            AC_MSG_WARN([Missing Python six library.])
> -          fi
> -        fi
>        fi])
> -   AC_SUBST([HAVE_PYTHON3])
> -   AM_MISSING_PROG([PYTHON3], [python3])
> -   if test "$ovs_cv_python3" != no; then
> -     PYTHON3=$ovs_cv_python3
> -     HAVE_PYTHON3=yes
> -   else
> -     HAVE_PYTHON3=no
> +   if test "$ovs_cv_python3" = no; then
> +     AC_MSG_ERROR([Python 3.4 or later is required but not found in $PATH, please install it or set $PYTHON3 to point to it])
>     fi
> -   AM_CONDITIONAL([HAVE_PYTHON3], [test "$HAVE_PYTHON3" = yes])])
> -
> -dnl Checks if you have any compatible Python version installed.
> -dnl Python 2.7+ has the preference to 3.4+
> -AC_DEFUN([OVS_CHECK_PYTHON],
> -  [AC_CACHE_CHECK(
> -     [for Python 2 or 3],
> -     [ovs_cv_python],
> -     [if test -n "$PYTHON"; then
> -        ovs_cv_python=$PYTHON
> +   AC_ARG_VAR([PYTHON3])
> +   PYTHON3=$ovs_cv_python3])
> +
> +dnl Checks for python six library.
> +AC_DEFUN([OVS_CHECK_SIX],
> +  [AC_REQUIRE([OVS_CHECK_PYTHON3])
> +   AC_CACHE_CHECK(
> +     [where Python six library is available],
> +     [ovs_cv_six],
> +     [if $PYTHON3 -c 'import six' >/dev/null 2>&1; then
> +        ovs_cv_six=yes
>        else
> -        ovs_cv_python=no
> -        if test "$ovs_cv_python2" != no; then
> -          ovs_cv_python=$ovs_cv_python2
> -        elif test "$ovs_cv_python3" != no; then
> -          ovs_cv_python=$ovs_cv_python3
> -        else
> -          AC_MSG_ERROR([Missing Python.])
> -        fi
> -      fi])
> -    AC_SUBST([PYTHON])
> -    PYTHON=$ovs_cv_python
> -    AC_SUBST([HAVE_PYTHON])
> -    HAVE_PYTHON=yes
> -    AM_CONDITIONAL([HAVE_PYTHON], [test "$HAVE_PYTHON" = yes])])
> +        AC_MSG_ERROR([Missing Python six library.])
> +      fi])])
>  
>  dnl Checks for flake8.
>  AC_DEFUN([OVS_CHECK_FLAKE8],
> @@ -477,7 +414,7 @@ AC_DEFUN([OVS_CHECK_SPHINX],
>    [AC_CHECK_PROGS(
>       [SPHINXBUILD], [sphinx-build-3 sphinx-build-2 sphinx-build], [none])
>     AC_ARG_VAR([SPHINXBUILD])
> -   AM_CONDITIONAL([HAVE_SPHINX], [test "$ac_cv_prog_SPHINXBUILD" != none])])
> +   AM_CONDITIONAL([HAVE_SPHINX], [test "$SPHINXBUILD" != none])])
>  
>  dnl Checks for dot.
>  AC_DEFUN([OVS_CHECK_DOT],
> diff --git a/manpages.mk b/manpages.mk
> index a66d109e347f..b43deaef1ae5 100644
> --- a/manpages.mk
> +++ b/manpages.mk
> @@ -116,12 +116,6 @@ lib/vlog-syn.man:
>  lib/vlog.man:
>  ovsdb/ovsdb-schemas.man:
>  
> -utilities/bugtool/ovs-bugtool.8: \
> -	utilities/bugtool/ovs-bugtool.8.in \
> -	lib/ovs.tmac
> -utilities/bugtool/ovs-bugtool.8.in:
> -lib/ovs.tmac:
> -
>  utilities/ovs-appctl.8: \
>  	utilities/ovs-appctl.8.in \
>  	lib/common.man \
> diff --git a/ovn/automake.mk b/ovn/automake.mk
> index afaf0688c0da..df92f25d8439 100644
> --- a/ovn/automake.mk
> +++ b/ovn/automake.mk
> @@ -6,18 +6,16 @@ pkgdata_DATA += ovn/ovn-sb.ovsschema
>  #
>  # If "python" or "dot" is not available, then we do not add graphical diagram
>  # to the documentation.
> -if HAVE_PYTHON
>  if HAVE_DOT
>  ovn/ovn-sb.gv: ovsdb/ovsdb-dot.in ovn/ovn-sb.ovsschema
>  	$(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-sb.ovsschema > $@
>  ovn/ovn-sb.pic: ovn/ovn-sb.gv ovsdb/dot2pic
> -	$(AM_V_GEN)(dot -T plain < ovn/ovn-sb.gv | $(PYTHON) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> +	$(AM_V_GEN)(dot -T plain < ovn/ovn-sb.gv | $(PYTHON3) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
>  	mv $@.tmp $@
>  OVN_SB_PIC = ovn/ovn-sb.pic
>  OVN_SB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_SB_PIC)
>  CLEANFILES += ovn/ovn-sb.gv ovn/ovn-sb.pic
>  endif
> -endif
>  
>  # OVN southbound schema documentation
>  EXTRA_DIST += ovn/ovn-sb.xml
> @@ -40,18 +38,16 @@ pkgdata_DATA += ovn/ovn-nb.ovsschema
>  #
>  # If "python" or "dot" is not available, then we do not add graphical diagram
>  # to the documentation.
> -if HAVE_PYTHON
>  if HAVE_DOT
>  ovn/ovn-nb.gv: ovsdb/ovsdb-dot.in ovn/ovn-nb.ovsschema
>  	$(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-nb.ovsschema > $@
>  ovn/ovn-nb.pic: ovn/ovn-nb.gv ovsdb/dot2pic
> -	$(AM_V_GEN)(dot -T plain < ovn/ovn-nb.gv | $(PYTHON) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> +	$(AM_V_GEN)(dot -T plain < ovn/ovn-nb.gv | $(PYTHON3) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
>  	mv $@.tmp $@
>  OVN_NB_PIC = ovn/ovn-nb.pic
>  OVN_NB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_NB_PIC)
>  CLEANFILES += ovn/ovn-nb.gv ovn/ovn-nb.pic
>  endif
> -endif
>  
>  # OVN northbound schema documentation
>  EXTRA_DIST += ovn/ovn-nb.xml
> diff --git a/ovsdb/ovsdb-dot.in b/ovsdb/ovsdb-dot.in
> index 8eea6172455d..41b986c0ac7f 100755
> --- a/ovsdb/ovsdb-dot.in
> +++ b/ovsdb/ovsdb-dot.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  
>  from datetime import date
>  import ovs.db.error
> diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
> index 40fef39edff7..238aaee3189c 100755
> --- a/ovsdb/ovsdb-idlc.in
> +++ b/ovsdb/ovsdb-idlc.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  
>  from __future__ import print_function
>  import getopt
> diff --git a/python/automake.mk b/python/automake.mk
> index 5a1e1da8a79a..2f08c7701484 100644
> --- a/python/automake.mk
> +++ b/python/automake.mk
> @@ -69,7 +69,6 @@ FLAKE8_PYFILES += \
>  	python/build/nroff.py \
>  	python/ovs/dirs.py.template
>  
> -if HAVE_PYTHON
>  nobase_pkgdata_DATA = $(ovs_pyfiles) $(ovstest_pyfiles)
>  ovs-install-data-local:
>  	$(MKDIR_P) python/ovs
> @@ -88,14 +87,10 @@ ovs-install-data-local:
>  	rm python/ovs/dirs.py.tmp
>  
>  python-sdist: $(srcdir)/python/ovs/version.py $(ovs_pyfiles) python/ovs/dirs.py
> -	(cd python/ && $(PYTHON) setup.py sdist)
> +	(cd python/ && $(PYTHON3) setup.py sdist)
>  
>  pypi-upload: $(srcdir)/python/ovs/version.py $(ovs_pyfiles) python/ovs/dirs.py
> -	(cd python/ && $(PYTHON) setup.py sdist upload)
> -else
> -ovs-install-data-local:
> -	@:
> -endif
> +	(cd python/ && $(PYTHON3) setup.py sdist upload)
>  install-data-local: ovs-install-data-local
>  
>  UNINSTALL_LOCAL += ovs-uninstall-local
> diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
> index 614c5f9f08ea..fc113c9f1642 100644
> --- a/rhel/openvswitch-fedora.spec.in
> +++ b/rhel/openvswitch-fedora.spec.in
> @@ -45,17 +45,6 @@
>  %define _rundir /run
>  %endif
>  
> -# define the python package prefix based on distribution version so that we can
> -# simultaneously support RHEL-based and later Fedora versions in this spec file.
> -%if 0%{?fedora} >= 25
> -%define _py2 python2
> -%endif
> -
> -%if 0%{?rhel} || 0%{?fedora} < 25
> -%define _py2 python
> -%endif
> -
> -
>  Name: openvswitch
>  Summary: Open vSwitch
>  Group: System Environment/Daemons
> @@ -72,7 +61,6 @@ Source: http://openvswitch.org/releases/%{name}-%{version}.tar.gz
>  BuildRequires: gcc gcc-c++
>  BuildRequires: autoconf automake libtool
>  BuildRequires: systemd-units openssl openssl-devel
> -BuildRequires: %{_py2}-devel
>  %if 0%{?fedora} > 22 || %{with build_python3}
>  BuildRequires: python3-devel
>  %endif
> @@ -81,7 +69,6 @@ BuildRequires: groff graphviz
>  BuildRequires: checkpolicy, selinux-policy-devel
>  BuildRequires: /usr/bin/sphinx-build-3
>  # make check dependencies
> -BuildRequires: %{_py2}-twisted%{?rhel:-core} %{_py2}-zope-interface %{_py2}-six
>  BuildRequires: procps-ng
>  %if %{with libcapng}
>  BuildRequires: libcap-ng libcap-ng-devel
> @@ -122,16 +109,6 @@ Requires: selinux-policy-targeted
>  %description selinux-policy
>  Tailored Open vSwitch SELinux policy
>  
> -%package -n %{_py2}-openvswitch
> -Summary: Open vSwitch python2 bindings
> -License: ASL 2.0
> -BuildArch: noarch
> -Requires: %{_py2}
> -Requires: %{_py2}-six
> -%{?python_provide:%python_provide python2-openvswitch = %{version}-%{release}}
> -%description -n %{_py2}-openvswitch
> -Python bindings for the Open vSwitch database
> -
>  %if 0%{?fedora} > 22 || %{with build_python3}
>  %package -n python3-openvswitch
>  Summary: Open vSwitch python3 bindings
> @@ -149,8 +126,6 @@ Python bindings for the Open vSwitch database
>  Summary: Open vSwitch testing utilities
>  License: ASL 2.0
>  BuildArch: noarch
> -Requires: %{_py2}-openvswitch = %{version}-%{release}
> -Requires: %{_py2} %{_py2}-netifaces %{_py2}-twisted
>  
>  %description test
>  Utilities that are useful to diagnose performance and connectivity
> @@ -179,7 +154,7 @@ service.
>  %package ipsec
>  Summary: Open vSwitch IPsec tunneling support
>  License: ASL 2.0
> -Requires: openvswitch %{_py2}-openvswitch libreswan
> +Requires: openvswitch python3-openvswitch libreswan
>  
>  %description ipsec
>  This package provides IPsec tunneling support for OVS tunnels.
> @@ -201,12 +176,7 @@ This package provides IPsec tunneling support for OVS tunnels.
>          --disable-static \
>          --enable-shared \
>          --with-pkidir=%{_sharedstatedir}/openvswitch/pki \
> -%if 0%{?fedora} > 22 || %{with build_python3}
> -        PYTHON3=%{__python3} \
> -        PYTHON=%{__python2}
> -%else
> -        PYTHON=%{__python}
> -%endif
> +        PYTHON3=%{__python3}
>  
>  build-aux/dpdkstrip.py \
>  %if %{with dpdk}
> @@ -274,13 +244,9 @@ install -p -m 0755 rhel/etc_sysconfig_network-scripts_ifdown-ovs \
>  install -p -m 0755 rhel/etc_sysconfig_network-scripts_ifup-ovs \
>          $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/network-scripts/ifup-ovs
>  
> -install -d -m 0755 $RPM_BUILD_ROOT%{python2_sitelib}
> -cp -a $RPM_BUILD_ROOT/%{_datadir}/openvswitch/python/* \
> -   $RPM_BUILD_ROOT%{python2_sitelib}
> -
>  %if 0%{?fedora} > 22 || %{with build_python3}
>  install -d -m 0755 $RPM_BUILD_ROOT%{python3_sitelib}
> -cp -a $RPM_BUILD_ROOT/%{_datadir}/openvswitch/python/ovs \
> +cp -a $RPM_BUILD_ROOT/%{_datadir}/openvswitch/python/* \
>     $RPM_BUILD_ROOT%{python3_sitelib}
>  %endif
>  
> @@ -435,9 +401,6 @@ fi
>  %defattr(-,root,root)
>  %{_datadir}/selinux/packages/%{name}/openvswitch-custom.pp
>  
> -%files -n %{_py2}-openvswitch
> -%{python2_sitelib}/ovs
> -
>  %if 0%{?fedora} > 22 || %{with build_python3}
>  %files -n python3-openvswitch
>  %{python3_sitelib}/ovs
> @@ -456,7 +419,7 @@ fi
>  %{_mandir}/man1/ovs-pcap.1*
>  %{_mandir}/man8/ovs-tcpdump.8*
>  %{_mandir}/man1/ovs-tcpundump.1*
> -%{python2_sitelib}/ovstest
> +%{python3_sitelib}/ovstest
>  
>  %files devel
>  %{_libdir}/lib*.so
> diff --git a/tests/atlocal.in b/tests/atlocal.in
> index 556f8681cf12..1dc7cd5d087a 100644
> --- a/tests/atlocal.in
> +++ b/tests/atlocal.in
> @@ -1,28 +1,14 @@
>  # -*- shell-script -*-
>  HAVE_OPENSSL='@HAVE_OPENSSL@'
>  OPENSSL_SUPPORTS_SNI='@OPENSSL_SUPPORTS_SNI@'
> -HAVE_PYTHON='@HAVE_PYTHON@'
> -HAVE_PYTHON2='@HAVE_PYTHON2@'
> -HAVE_PYTHON3='@HAVE_PYTHON3@'
>  HAVE_UNBOUND='@HAVE_UNBOUND@'
>  EGREP='@EGREP@'
> +PYTHON3='@PYTHON3@'
>  
> -if test x"$PYTHON" = x; then
> -    PYTHON='@PYTHON@'
> -fi
> -
> -if test x"$PYTHON2" = x; then
> -    PYTHON2='@PYTHON2@'
> -fi
> -
> -if test x"$PYTHON3" = x; then
> -    PYTHON3='@PYTHON3@'
> -
> -    # PYTHONCOERCECLOCALE=0 disables the Unicode compatibility warning on
> -    # stderr that breaks almost any Python3 test (PEP 0538)
> -    PYTHONCOERCECLOCALE=0
> -    export PYTHONCOERCECLOCALE
> -fi
> +# PYTHONCOERCECLOCALE=0 disables the Unicode compatibility warning on
> +# stderr that breaks almost any Python3 test (PEP 0538)
> +PYTHONCOERCECLOCALE=0
> +export PYTHONCOERCECLOCALE
>  
>  PYTHONPATH=$abs_top_srcdir/python:$abs_top_builddir/tests:$PYTHONPATH
>  export PYTHONPATH
> @@ -63,7 +49,7 @@ Linux)
>      # in particular the patch attached there, which was applied to glibc CVS as
>      # "Restore locking in free_check." between 1.11 and 1.11.1.
>      vswitchd=$abs_top_builddir/vswitchd/ovs-vswitchd
> -    glibc=`ldd $vswitchd | sed -n 's/^	libc\.[^ ]* => \([^ ]*\) .*/\1/p'`
> +    glibc=`ldd $vswitchd | sed -n 's/^  libc\.[^ ]* => \([^ ]*\) .*/\1/p'`
>      glibc_version=`$glibc | sed -n '1s/.*version \([0-9]\{1,\}\.[0-9]\{1,\}\).*/\1/p'`
>      case $glibc_version in
>          2.[0-9] | 2.1[01]) mcheck=disabled ;;
> @@ -116,7 +102,7 @@ FreeBSD|NetBSD)
>      ;;
>  esac
>  
> -if test x"$PYTHON3" != x && test "$IS_WIN32" = yes; then
> +if test "$IS_WIN32" = yes; then
>      # enables legacy windows unicode printing needed for Python3 compatibility
>      # with the Python2 tests
>      PYTHONLEGACYWINDOWSFSENCODING=true
> @@ -126,7 +112,7 @@ if test x"$PYTHON3" != x && test "$IS_WIN32" = yes; then
>  fi
>  
>  # Check whether to run IPv6 tests.
> -$PYTHON -c '
> +$PYTHON3 -c '
>  import errno
>  import socket
>  import sys
> @@ -140,7 +126,7 @@ except socket.error as e:
>  case $? in
>      0) HAVE_IPV6=yes ;;
>      2) HAVE_IPV6=no ;;
> -    *) echo "$0: unexpected error probing $PYTHON for IPv6 support" >&2 ;;
> +    *) echo "$0: unexpected error probing $PYTHON3 for IPv6 support" >&2 ;;
>  esac
>  
>  # Look for a python L7 library 'LIB' in the system. If it is found, defines
> @@ -149,13 +135,9 @@ find_l7_lib()
>  {
>      set +x
>      var=HAVE_`echo "$1" | tr '[a-z]' '[A-Z]'`
> -    if test "$HAVE_PYTHON" = "yes"; then
> -        result=$($PYTHON $abs_top_srcdir/tests/test-l7.py --help | grep "$1")
> -        if test "x${result}" != x; then
> -            eval ${var}="yes"
> -        else
> -            eval ${var}="no"
> -        fi
> +    result=$($PYTHON3 $abs_top_srcdir/tests/test-l7.py --help | grep "$1")
> +    if test "x${result}" != x; then
> +        eval ${var}="yes"
>      else
>          eval ${var}="no"
>      fi
> diff --git a/tests/automake.mk b/tests/automake.mk
> index 0b4f29486bc7..0442334ecb78 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -199,7 +199,7 @@ check-local:
>  COVERAGE = coverage
>  COVERAGE_FILE='$(abs_srcdir)/.coverage'
>  check-pycov: all clean-pycov
> -	PYTHONDONTWRITEBYTECODE=yes COVERAGE_FILE=$(COVERAGE_FILE) PYTHON='$(COVERAGE) run -p' $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH) $(TESTSUITEFLAGS)
> +	PYTHONDONTWRITEBYTECODE=yes COVERAGE_FILE=$(COVERAGE_FILE) PYTHON3='$(COVERAGE) run -p' $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH) $(TESTSUITEFLAGS)
>  	@cd $(srcdir) && $(COVERAGE) combine && COVERAGE_FILE=$(COVERAGE_FILE) $(COVERAGE) annotate
>  	@echo
>  	@echo '----------------------------------------------------------------------'
> diff --git a/tests/check-structs.at b/tests/check-structs.at
> index 4163c30d6dbe..15ca536112e6 100644
> --- a/tests/check-structs.at
> +++ b/tests/check-structs.at
> @@ -3,10 +3,9 @@ AT_BANNER([struct alignment checker unit tests])
>  m4_define([check_structs], [$top_srcdir/build-aux/check-structs])
>  m4_define([RUN_STRUCT_CHECKER], 
>    [AT_KEYWORDS([check-structs])
> -   AT_SKIP_IF([test $HAVE_PYTHON = no])
>     AT_DATA([test.h], [$1
>  ])
> -   AT_CHECK_UNQUOTED([$PYTHON check_structs test.h], [$2], [$3], [$4])])
> +   AT_CHECK_UNQUOTED([$PYTHON3 check_structs test.h], [$2], [$3], [$4])])
>  
>  AT_SETUP([check struct tail padding])
>  RUN_STRUCT_CHECKER(
> diff --git a/tests/checkpatch.at b/tests/checkpatch.at
> index fe21acdf2d22..6c7394772270 100755
> --- a/tests/checkpatch.at
> +++ b/tests/checkpatch.at
> @@ -3,10 +3,9 @@ AT_BANNER([checkpatch])
>  OVS_START_SHELL_HELPERS
>  # try_checkpatch PATCH [ERRORS]
>  #
> -# Runs checkpatch under Python 2 and Python 3, if installed, on the given
> -# PATCH, expecting the specified set of ERRORS (and warnings).
> +# Runs checkpatch, if installed, on the given PATCH, expecting the
> +# specified set of ERRORS (and warnings).
>  try_checkpatch() {
> -    AT_SKIP_IF([test $HAVE_PYTHON2 = no && test $HAVE_PYTHON3 = no])
>      # Take the patch to test from $1.  Remove an initial four-space indent
>      # from it and, if it is just headers with no body, add a null body.
>      echo "$1" | sed 's/^    //' > test.patch
> @@ -22,18 +21,12 @@ try_checkpatch() {
>          : > expout
>      fi
>  
> -    try_checkpatch__ "$HAVE_PYTHON2" "$PYTHON2"
> -    try_checkpatch__ "$HAVE_PYTHON3" "$PYTHON3"
> -}
> -try_checkpatch__() {
> -    if test $1 = no; then
> -        :
> -    elif test -s expout; then
> -        AT_CHECK([$2 $top_srcdir/utilities/checkpatch.py -q test.patch],
> +    if test -s expout; then
> +        AT_CHECK([$PYTHON3 $top_srcdir/utilities/checkpatch.py -q test.patch],
>                   [1], [stdout])
>          AT_CHECK([sed '/^Lines checked:/,$d' stdout], [0], [expout])
>      else
> -        AT_CHECK([$2 $top_srcdir/utilities/checkpatch.py -q test.patch])
> +        AT_CHECK([$PYTHON3 $top_srcdir/utilities/checkpatch.py -q test.patch])
>      fi
>  }
>  OVS_END_SHELL_HELPERS
> diff --git a/tests/daemon-py.at b/tests/daemon-py.at
> index 6adea3c85dfc..883e45a5ac21 100644
> --- a/tests/daemon-py.at
> +++ b/tests/daemon-py.at
> @@ -1,252 +1,205 @@
> -AT_BANNER([daemon unit tests - Python])
> -
> -m4_define([DAEMON_PYN],
> -  [AT_SETUP([daemon - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   # Skip this test for Windows, echo $! gives shell pid instead of parent process
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -   AT_KEYWORDS([python daemon])
> -
> -   on_exit 'kill $(cat *.pid)'
> -   pidfile=test-daemon.py.pid
> -
> -   # Start the daemon and wait for the pidfile to get created
> -   # and that its contents are the correct pid.
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile & echo $!], [0], [stdout])
> -   pid=$(cat stdout)
> -
> -   OVS_WAIT_UNTIL([test -s $pidfile], [kill $pid])
> -   AT_CHECK([test $pid = $(cat $pidfile)])
> -   AT_CHECK([kill -0 $pid])
> -
> -   # Kill the daemon and make sure that the pidfile gets deleted.
> -   kill $pid
> -   OVS_WAIT_WHILE([kill -0 $pid])
> -   AT_CHECK([test ! -e $pidfile])
> -   AT_CLEANUP])
> -
> -DAEMON_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_MONITOR_PYN],
> -  [AT_SETUP([daemon --monitor - $1])
> -   AT_SKIP_IF([test $2 = no])
> -
> -   # Skip this test for Windows, echo $! gives shell pid instead of parent process
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -
> -   on_exit 'kill $(cat *.pid)'
> -   pidfile=test-daemon.py.pid
> -
> -   # Start the daemon and wait for the pidfile to get created.
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout])
> -   monitor=$(cat stdout)
> -   OVS_WAIT_UNTIL([test -s $pidfile])
> -   child=$(cat $pidfile)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is our child process.
> -   check_ancestors $child $monitor
> -
> -   # Kill the daemon process, making it look like a segfault,
> -   # and wait for a new child process to get spawned.
> -   AT_CHECK([kill -SEGV $child])
> -   OVS_WAIT_WHILE([kill -0 $child])
> -   OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child])
> -   child2=$(cat $pidfile)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is our child process.
> -   check_ancestors $child2 $monitor
> -
> -   # Kill the daemon process with SIGTERM, and wait for the daemon
> -   # and the monitor processes to go away and the pidfile to get deleted.
> -   AT_CHECK([kill $child2])
> -   OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile])
> -   AT_CLEANUP])
> -
> -DAEMON_MONITOR_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_MONITOR_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_MONITOR_RESTART_PYN],
> -  [AT_SETUP([daemon --monitor restart exit code - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   # Skip this test for Windows, echo $! gives shell pid instead of parent process
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -
> -   on_exit 'kill $(cat *.pid)'
> -   pidfile=test-daemon.py.pid
> -
> -   # Start the daemon and wait for the pidfile to get created.
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout])
> -   monitor=$(cat stdout)
> -   OVS_WAIT_UNTIL([test -s $pidfile])
> -   child=$(cat $pidfile)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is our child process.
> -   check_ancestors $child $monitor
> -
> -   # HUP the daemon process causing it to throw an exception,
> -   # and wait for a new child process to get spawned.
> -   AT_CHECK([kill -HUP $child])
> -   OVS_WAIT_WHILE([kill -0 $child])
> -   OVS_WAIT_UNTIL([test -s $pidfile && test $child != $(cat $pidfile)])
> -   child2=$(cat $pidfile)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is our child process.
> -   check_ancestors $child2 $monitor
> -
> -   # Kill the daemon process with SIGTERM, and wait for the daemon
> -   # and the monitor processes to go away and the pidfile to get deleted.
> -   AT_CHECK([kill $child2])
> -   OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile])
> -   AT_CLEANUP])
> -
> -DAEMON_MONITOR_RESTART_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_MONITOR_RESTART_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_PYN],
> -  [AT_SETUP([daemon --detach - $1])
> -   AT_SKIP_IF([test $2 = no])
> -
> -   # Skip this test for Windows, the pid file not removed if the daemon is killed
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -
> -   on_exit 'kill $(cat *.pid)'
> -   pidfile=test-daemon.py.pid
> -
> -   # Start the daemon and make sure that the pidfile exists immediately.
> -   # We don't wait for the pidfile to get created because the daemon is
> -   # supposed to do so before the parent exits.
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --no-chdir], [0])
> -   AT_CHECK([test -s $pidfile])
> -   pid=$(cat $pidfile)
> -   check_ancestors $pid 1
> -
> -   # Kill the daemon and make sure that the pidfile gets deleted.
> -   AT_CHECK([kill $pid])
> -   OVS_WAIT_WHILE([kill -0 $pid])
> -   AT_CHECK([test ! -e $pidfile])
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_MONITOR_PYN],
> -  [AT_SETUP([daemon --detach --monitor - $1])
> -   AT_SKIP_IF([test $2 = no])
> -
> -   # Skip this test for Windows, uses Linux specific kill signal
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -
> -   on_exit 'kill $(cat *.pid)'
> -   pidfile=test-daemon.py.pid
> -
> -   # Start the daemon and make sure that the pidfile exists immediately.
> -   # We don't wait for the pidfile to get created because the daemon is
> -   # supposed to do so before the parent exits.
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --monitor], [0])
> -   AT_CHECK([test -s $pidfile])
> -   child=$(cat $pidfile)
> -   AT_CHECK([parent_pid $child], [0], [stdout])
> -   monitor=$(cat stdout)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is a running process,
> -   # and that the parent process of that process is init.
> -   check_ancestors $child $monitor 1
> -
> -   # Kill the daemon process, making it look like a segfault,
> -   # and wait for a new daemon process to get spawned.
> -   AT_CHECK([kill -SEGV $child])
> -   OVS_WAIT_WHILE([kill -0 $child])
> -   OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child])
> -   child2=$(cat $pidfile)
> -
> -   # Check that the pidfile names a running process,
> -   # and that the parent process of that process is our child process.
> -   check_ancestors $child2 $monitor 1
> -
> -   # Kill the daemon process with SIGTERM, and wait for the daemon
> -   # and the monitor processes to go away and the pidfile to get deleted.
> -   AT_CHECK([kill $child2])
> -   OVS_WAIT_WHILE([kill -0 $child2 || kill -0 $monitor || test -e $pidfile])
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_MONITOR_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_MONITOR_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_ERRORS_PYN],
> -  [AT_SETUP([daemon --detach startup errors - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --bail], [1], [], [stderr])
> -   AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr],
> -     [0], [ignore])
> -   AT_CHECK([test ! -s test-daemon.py.pid])
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_ERRORS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_ERRORS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_MONITOR_ERRORS_PYN],
> -  [AT_SETUP([daemon --detach --monitor startup errors - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_CAPTURE_FILE([pid])
> -   AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --monitor --bail], [1], [], [stderr])
> -   AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr],
> -     [0], [ignore])
> -   AT_CHECK([test ! -s test-daemon.py.pid])
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_MONITOR_ERRORS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_MONITOR_ERRORS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_CLOSES_FDS_PYN],
> -  [AT_SETUP([daemon --detach closes standard fds - $1])
> -   AT_SKIP_IF([test $2 = no])
> -
> -   # Skip this test for Windows, uses Linux specific kill signal
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -
> -   AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile --detach --no-chdir])
> -   AT_CHECK([kill $(cat test-daemon.py.pid)])
> -   AT_CHECK([test -s status])
> -   if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then
> -     # Something in the environment caused SIGPIPE to be ignored, but
> -     # 'yes' at least told us that it got EPIPE.  Good enough; we know
> -     # that stdout was closed.
> -     :
> -   else
> -     # Otherwise make sure that 'yes' died from SIGPIPE.
> -     AT_CHECK([kill -l `cat status`], [0], [PIPE
> +AT_BANNER([daemon unit tests - Python3])
> +
> +AT_SETUP([daemon - Python3])
> +# Skip this test for Windows, echo $! gives shell pid instead of parent process
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +AT_KEYWORDS([python daemon])
> +
> +on_exit 'kill $(cat *.pid)'
> +pidfile=test-daemon.py.pid
> +
> +# Start the daemon and wait for the pidfile to get created
> +# and that its contents are the correct pid.
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile & echo $!], [0], [stdout])
> +pid=$(cat stdout)
> +
> +OVS_WAIT_UNTIL([test -s $pidfile], [kill $pid])
> +AT_CHECK([test $pid = $(cat $pidfile)])
> +AT_CHECK([kill -0 $pid])
> +
> +# Kill the daemon and make sure that the pidfile gets deleted.
> +kill $pid
> +OVS_WAIT_WHILE([kill -0 $pid])
> +AT_CHECK([test ! -e $pidfile])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --monitor - Python3])
> +# Skip this test for Windows, echo $! gives shell pid instead of parent process
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +
> +on_exit 'kill $(cat *.pid)'
> +pidfile=test-daemon.py.pid
> +
> +# Start the daemon and wait for the pidfile to get created.
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout])
> +monitor=$(cat stdout)
> +OVS_WAIT_UNTIL([test -s $pidfile])
> +child=$(cat $pidfile)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is our child process.
> +check_ancestors $child $monitor
> +
> +# Kill the daemon process, making it look like a segfault,
> +# and wait for a new child process to get spawned.
> +AT_CHECK([kill -SEGV $child])
> +OVS_WAIT_WHILE([kill -0 $child])
> +OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child])
> +child2=$(cat $pidfile)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is our child process.
> +check_ancestors $child2 $monitor
> +
> +# Kill the daemon process with SIGTERM, and wait for the daemon
> +# and the monitor processes to go away and the pidfile to get deleted.
> +AT_CHECK([kill $child2])
> +OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --monitor restart exit code - Python3])
> +# Skip this test for Windows, echo $! gives shell pid instead of parent process
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +
> +on_exit 'kill $(cat *.pid)'
> +pidfile=test-daemon.py.pid
> +
> +# Start the daemon and wait for the pidfile to get created.
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout])
> +monitor=$(cat stdout)
> +OVS_WAIT_UNTIL([test -s $pidfile])
> +child=$(cat $pidfile)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is our child process.
> +check_ancestors $child $monitor
> +
> +# HUP the daemon process causing it to throw an exception,
> +# and wait for a new child process to get spawned.
> +AT_CHECK([kill -HUP $child])
> +OVS_WAIT_WHILE([kill -0 $child])
> +OVS_WAIT_UNTIL([test -s $pidfile && test $child != $(cat $pidfile)])
> +child2=$(cat $pidfile)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is our child process.
> +check_ancestors $child2 $monitor
> +
> +# Kill the daemon process with SIGTERM, and wait for the daemon
> +# and the monitor processes to go away and the pidfile to get deleted.
> +AT_CHECK([kill $child2])
> +OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach - Python3])
> +
> +# Skip this test for Windows, the pid file not removed if the daemon is killed
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +
> +on_exit 'kill $(cat *.pid)'
> +pidfile=test-daemon.py.pid
> +
> +# Start the daemon and make sure that the pidfile exists immediately.
> +# We don't wait for the pidfile to get created because the daemon is
> +# supposed to do so before the parent exits.
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir], [0])
> +AT_CHECK([test -s $pidfile])
> +pid=$(cat $pidfile)
> +check_ancestors $pid 1
> +
> +# Kill the daemon and make sure that the pidfile gets deleted.
> +AT_CHECK([kill $pid])
> +OVS_WAIT_WHILE([kill -0 $pid])
> +AT_CHECK([test ! -e $pidfile])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach --monitor - Python3])
> +
> +# Skip this test for Windows, uses Linux specific kill signal
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +
> +on_exit 'kill $(cat *.pid)'
> +pidfile=test-daemon.py.pid
> +
> +# Start the daemon and make sure that the pidfile exists immediately.
> +# We don't wait for the pidfile to get created because the daemon is
> +# supposed to do so before the parent exits.
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --monitor], [0])
> +AT_CHECK([test -s $pidfile])
> +child=$(cat $pidfile)
> +AT_CHECK([parent_pid $child], [0], [stdout])
> +monitor=$(cat stdout)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is a running process,
> +# and that the parent process of that process is init.
> +check_ancestors $child $monitor 1
> +
> +# Kill the daemon process, making it look like a segfault,
> +# and wait for a new daemon process to get spawned.
> +AT_CHECK([kill -SEGV $child])
> +OVS_WAIT_WHILE([kill -0 $child])
> +OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child])
> +child2=$(cat $pidfile)
> +
> +# Check that the pidfile names a running process,
> +# and that the parent process of that process is our child process.
> +check_ancestors $child2 $monitor 1
> +
> +# Kill the daemon process with SIGTERM, and wait for the daemon
> +# and the monitor processes to go away and the pidfile to get deleted.
> +AT_CHECK([kill $child2])
> +OVS_WAIT_WHILE([kill -0 $child2 || kill -0 $monitor || test -e $pidfile])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach startup errors - Python3])
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --bail], [1], [], [stderr])
> +AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr],
> +  [0], [ignore])
> +AT_CHECK([test ! -s test-daemon.py.pid])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach --monitor startup errors - Python3])
> +AT_CAPTURE_FILE([pid])
> +AT_CHECK([$PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir --monitor --bail], [1], [], [stderr])
> +AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr],
> +  [0], [ignore])
> +AT_CHECK([test ! -s test-daemon.py.pid])
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach closes standard fds - Python3])
> +# Skip this test for Windows, uses Linux specific kill signal
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +
> +AT_CHECK([(yes 2>stderr; echo $? > status) | $PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir])
> +AT_CHECK([kill $(cat test-daemon.py.pid)])
> +AT_CHECK([test -s status])
> +if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then
> +  # Something in the environment caused SIGPIPE to be ignored, but
> +  # 'yes' at least told us that it got EPIPE.  Good enough; we know
> +  # that stdout was closed.
> +  :
> +else
> +  # Otherwise make sure that 'yes' died from SIGPIPE.
> +  AT_CHECK([kill -l `cat status`], [0], [PIPE
>  ])
> -   fi
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_CLOSES_FDS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_CLOSES_FDS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([DAEMON_DETACH_MONITOR_CLOSES_FDS_PYN],
> -  [AT_SETUP([daemon --detach --monitor closes standard fds - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   # Skip this test for Windows, uses Linux specific kill signal
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -   AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile --detach --no-chdir], [0], [], [])
> -   AT_CHECK([kill $(cat test-daemon.py.pid)])
> -   AT_CHECK([test -s status])
> -   if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then
> -     # Something in the environment caused SIGPIPE to be ignored, but
> -     # 'yes' at least told us that it got EPIPE.  Good enough; we know
> -     # that stdout was closed.
> -     :
> -   else
> -     # Otherwise make sure that 'yes' died from SIGPIPE.
> -     AT_CHECK([kill -l `cat status`], [0], [PIPE
> +fi
> +AT_CLEANUP
> +
> +AT_SETUP([daemon --detach --monitor closes standard fds - Python3])
> +# Skip this test for Windows, uses Linux specific kill signal
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +AT_CHECK([(yes 2>stderr; echo $? > status) | $PYTHON3 $srcdir/test-daemon.py --pidfile --detach --no-chdir], [0], [], [])
> +AT_CHECK([kill $(cat test-daemon.py.pid)])
> +AT_CHECK([test -s status])
> +if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then
> +  # Something in the environment caused SIGPIPE to be ignored, but
> +  # 'yes' at least told us that it got EPIPE.  Good enough; we know
> +  # that stdout was closed.
> +  :
> +else
> +  # Otherwise make sure that 'yes' died from SIGPIPE.
> +  AT_CHECK([kill -l `cat status`], [0], [PIPE
>  ])
> -   fi
> -   AT_CLEANUP])
> -
> -DAEMON_DETACH_MONITOR_CLOSES_FDS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -DAEMON_DETACH_MONITOR_CLOSES_FDS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +fi
> +AT_CLEANUP
> diff --git a/tests/flowgen.py b/tests/flowgen.py
> index 976fe7a97c98..7ef32d13cb40 100755
> --- a/tests/flowgen.py
> +++ b/tests/flowgen.py
> @@ -1,4 +1,4 @@
> -#! /usr/bin/env python
> +#! /usr/bin/env python3
>  
>  # Copyright (c) 2009, 2010, 2011, 2012, 2015, 2017 Nicira, Inc.
>  #
> diff --git a/tests/interface-reconfigure.at b/tests/interface-reconfigure.at
> index 035b0095642a..f4ceb284af4d 100644
> --- a/tests/interface-reconfigure.at
> +++ b/tests/interface-reconfigure.at
> @@ -681,7 +681,7 @@ EOF
>  }
>  
>  ifr_run () {
> -    $PYTHON ./interface-reconfigure --root-prefix="`pwd`" --no-syslog "$@"
> +    $PYTHON3 ./interface-reconfigure --root-prefix="`pwd`" --no-syslog "$@"
>  }
>  
>  ifr_filter () {
> diff --git a/tests/json.at b/tests/json.at
> index bfe0f1967c4a..527ce8e64033 100644
> --- a/tests/json.at
> +++ b/tests/json.at
> @@ -8,45 +8,21 @@ m4_define([JSON_CHECK_POSITIVE_C],
>  ])
>     AT_CLEANUP])
>  
> -# JSON_CHECK_POSITIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS,
> -#                        PYTHON-CHCEK, PYTHON-BIN)
> +# JSON_CHECK_POSITIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS)
>  #
>  m4_define([JSON_CHECK_POSITIVE_PY],
>    [AT_SETUP([$1])
>     AT_KEYWORDS([json positive Python])
> -   AT_SKIP_IF([test $5 = no])
>     AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
>     AT_CAPTURE_FILE([input])
> -   AT_CHECK([$6 $srcdir/test-json.py $4 input], [0], [stdout], [])
> -   AT_CHECK([cat stdout], [0], [$3
> -])
> -   AT_CLEANUP])
> -
> -m4_define([JSON_CHECK_POSITIVE_UCS4PY],
> -  [AT_SETUP([$1])
> -   AT_KEYWORDS([json positive Python])
> -   AT_SKIP_IF([test $HAVE_PYTHON2 = no])
> -   AT_XFAIL_IF([test $HAVE_PYTHON2 = yes &&
> -                $PYTHON2 -c "exit(len(u'\U00010800'))"; test $? -ne 1])
> -   AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
> -   AT_CAPTURE_FILE([input])
> -   AT_CHECK([$PYTHON2 $srcdir/test-json.py $4 input], [0], [stdout], [])
> +   AT_CHECK([$PYTHON3 $srcdir/test-json.py $4 input], [0], [stdout], [])
>     AT_CHECK([cat stdout], [0], [$3
>  ])
>     AT_CLEANUP])
>  
>  m4_define([JSON_CHECK_POSITIVE],
>    [JSON_CHECK_POSITIVE_C([$1 - C], [$2], [$3], [$4])
> -   JSON_CHECK_POSITIVE_PY([$1 - Python2], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON2], [$PYTHON2])
> -   JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON3], [$PYTHON3])])
> -
> -m4_define([JSON_CHECK_POSITIVE_PY23],
> -  [JSON_CHECK_POSITIVE_PY([$1 - Python2], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON2], [$PYTHON2])
> -   JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON3], [$PYTHON3])])
> +   JSON_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4])])
>  
>  m4_define([JSON_CHECK_NEGATIVE_C],
>    [AT_SETUP([$1])
> @@ -58,26 +34,21 @@ m4_define([JSON_CHECK_NEGATIVE_C],
>  ])
>     AT_CLEANUP])
>  
> -# JSON_CHECK_NEGATIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS,
> -#                        PYTHON-CHCEK, PYTHON-BIN)
> +# JSON_CHECK_NEGATIVE_PY(TITLE, INPUT, OUTPUT, TEST-JSON-ARGS)
>  #
>  m4_define([JSON_CHECK_NEGATIVE_PY], 
>    [AT_SETUP([$1])
>     AT_KEYWORDS([json negative Python])
> -   AT_SKIP_IF([test $5 = no])
>     AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
>     AT_CAPTURE_FILE([input])
> -   AT_CHECK([$6 $srcdir/test-json.py $4 input], [1], [stdout], [])
> +   AT_CHECK([$PYTHON3 $srcdir/test-json.py $4 input], [1], [stdout], [])
>     AT_CHECK([[sed 's/^error: [^:]*:/error:/' < stdout]], [0], [$3
>  ])
>     AT_CLEANUP])
>  
>  m4_define([JSON_CHECK_NEGATIVE],
>    [JSON_CHECK_NEGATIVE_C([$1 - C], [$2], [$3], [$4])
> -   JSON_CHECK_NEGATIVE_PY([$1 - Python2], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON2], [$PYTHON2])
> -   JSON_CHECK_NEGATIVE_PY([$1 - Python3], [$2], [$3], [$4],
> -                          [$HAVE_PYTHON3], [$PYTHON3])])
> +   JSON_CHECK_NEGATIVE_PY([$1 - Python3], [$2], [$3], [$4])])
>  
>  AT_BANNER([JSON -- arrays])
>  
> @@ -109,9 +80,6 @@ JSON_CHECK_POSITIVE([Unicode escape sequences],
>  JSON_CHECK_POSITIVE_C([surrogate pairs - C],
>    [[["\ud834\udd1e"]]],
>    [[["𝄞"]]])
> -JSON_CHECK_POSITIVE_UCS4PY([surrogate pairs - Python],
> -  [[["\ud834\udd1e"]]],
> -  [[["𝄞"]]])
>  JSON_CHECK_NEGATIVE([a string by itself is not valid JSON], ["xxx"],
>                      [error: syntax error at beginning of input])
>  JSON_CHECK_NEGATIVE([end of line in quoted string],
> @@ -154,15 +122,6 @@ AT_CHECK([printf '"xxx' | ovstest test-json -], [1],
>  ])
>  AT_CLEANUP
>  
> -AT_SETUP([end of input in quoted string - Python])
> -AT_KEYWORDS([json negative Python])
> -AT_SKIP_IF([test $HAVE_PYTHON2 = no])
> -AT_CHECK([printf '"xxx' > input
> -$PYTHON2 $srcdir/test-json.py input], [1],
> -  [error: line 0, column 4, byte 4: unexpected end of input in quoted string
> -])
> -AT_CLEANUP
> -
>  AT_BANNER([JSON -- objects])
>  
>  JSON_CHECK_POSITIVE([empty object], [[{ }]], [[{}]])
> @@ -227,7 +186,7 @@ JSON_CHECK_POSITIVE_C(
>    [C - large integers that overflow to reals],
>    [[[9223372036854775807000, -92233720368547758080000]]],
>    [[[9.22337203685478e+21,-9.22337203685478e+22]]])
> -JSON_CHECK_POSITIVE_PY23(
> +JSON_CHECK_POSITIVE_PY(
>    [large integers that overflow to reals],
>    [[[9223372036854775807000, -92233720368547758080000]]],
>    [[[9.223372036854776e+21,-9.223372036854776e+22]]])
> @@ -252,7 +211,7 @@ JSON_CHECK_POSITIVE_C(
>    [C - +/- DBL_MAX],
>    [[[1.7976931348623157e+308, -1.7976931348623157e+308]]],
>    [[[1.79769313486232e+308,-1.79769313486232e+308]]])
> -JSON_CHECK_POSITIVE_PY23(
> +JSON_CHECK_POSITIVE_PY(
>    [+/- DBL_MAX],
>    [[[1.7976931348623157e+308, -1.7976931348623157e+308]]],
>    [[[1.7976931348623157e+308,-1.7976931348623157e+308]]])
> diff --git a/tests/jsonrpc-py.at b/tests/jsonrpc-py.at
> index e75ac4551006..3a304dad8551 100644
> --- a/tests/jsonrpc-py.at
> +++ b/tests/jsonrpc-py.at
> @@ -1,46 +1,31 @@
> -AT_BANNER([JSON-RPC - Python])
> +AT_BANNER([JSON-RPC - Python3])
>  
> -m4_define([JSONRPC_REQ_REPLY_SUCCESS_PYN],
> -  [AT_SETUP([JSON-RPC request and successful reply - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_KEYWORDS([python jsonrpc])
> -   AT_CHECK([$3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> -   on_exit 'kill `cat test-jsonrpc.py.pid`'
> -   AT_CHECK(
> -     [[$3 $srcdir/test-jsonrpc.py request unix:socket echo '[{"a": "b", "x": null}]']], [0],
> -     [[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
> +AT_SETUP([JSON-RPC request and successful reply - Python3])
> +AT_KEYWORDS([python jsonrpc])
> +AT_CHECK([$PYTHON3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> +on_exit 'kill `cat test-jsonrpc.py.pid`'
> +AT_CHECK(
> +  [[$PYTHON3 $srcdir/test-jsonrpc.py request unix:socket echo '[{"a": "b", "x": null}]']], [0],
> +  [[{"error":null,"id":0,"result":[{"a":"b","x":null}]}
>  ]])
> -   AT_CLEANUP])
> +AT_CLEANUP
>  
> -JSONRPC_REQ_REPLY_SUCCESS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -JSONRPC_REQ_REPLY_SUCCESS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([JSONRPC_REQ_REPLY_ERROR_PYN],
> -  [AT_SETUP([JSON-RPC request and error reply - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_KEYWORDS([python jsonrpc])
> -   AT_CHECK([$3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> -   on_exit 'kill `cat test-jsonrpc.py.pid`'
> -   AT_CHECK(
> -     [[$3 $srcdir/test-jsonrpc.py request unix:socket bad-request '[]']], [0],
> -     [[{"error":{"error":"unknown method"},"id":0,"result":null}
> +AT_SETUP([JSON-RPC request and error reply - Python3])
> +AT_KEYWORDS([python jsonrpc])
> +AT_CHECK([$PYTHON3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> +on_exit 'kill `cat test-jsonrpc.py.pid`'
> +AT_CHECK(
> +  [[$PYTHON3 $srcdir/test-jsonrpc.py request unix:socket bad-request '[]']], [0],
> +  [[{"error":{"error":"unknown method"},"id":0,"result":null}
>  ]])
> -   AT_CLEANUP])
> -
> -JSONRPC_REQ_REPLY_ERROR_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -JSONRPC_REQ_REPLY_ERROR_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([JSONRPC_NOTIFICATION_PYN],
> -  [AT_SETUP([JSON-RPC notification - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_KEYWORDS([python jsonrpc])
> -   AT_CHECK([$3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> -   on_exit 'kill `cat test-jsonrpc.py.pid`'
> -   AT_CHECK([test -e test-jsonrpc.py.pid])
> -   AT_CHECK([[$3 $srcdir/test-jsonrpc.py notify unix:socket shutdown '[]']])
> -   # Wait for test-jsonrpc to die, based on its pidfile disappearing
> -   OVS_WAIT_WHILE([test -e test-jsonrpc.py.pid])
> -   AT_CLEANUP])
> +AT_CLEANUP
>  
> -JSONRPC_NOTIFICATION_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -JSONRPC_NOTIFICATION_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_SETUP([JSON-RPC notification - Python3])
> +AT_KEYWORDS([python jsonrpc])
> +AT_CHECK([$PYTHON3 $srcdir/test-jsonrpc.py --pidfile --detach --no-chdir listen punix:socket])
> +on_exit 'kill `cat test-jsonrpc.py.pid`'
> +AT_CHECK([test -e test-jsonrpc.py.pid])
> +AT_CHECK([[$PYTHON3 $srcdir/test-jsonrpc.py notify unix:socket shutdown '[]']])
> +# Wait for test-jsonrpc to die, based on its pidfile disappearing
> +OVS_WAIT_WHILE([test -e test-jsonrpc.py.pid])
> +AT_CLEANUP
> diff --git a/tests/library.at b/tests/library.at
> index ecb9268d40df..ac4ea4abf281 100644
> --- a/tests/library.at
> +++ b/tests/library.at
> @@ -1,7 +1,7 @@
>  AT_BANNER([library unit tests])
>  
>  AT_SETUP([flow extractor])
> -AT_CHECK([$PYTHON $srcdir/flowgen.py >/dev/null])
> +AT_CHECK([$PYTHON3 $srcdir/flowgen.py >/dev/null])
>  AT_CHECK([ovstest test-flows flows pcap], [0], [checked 247 packets, 0 errors
>  ])
>  AT_CLEANUP
> @@ -176,37 +176,29 @@ AT_CHECK([mkdir $longname || exit 77])
>  AT_CHECK([cd $longname && ovstest test-unix-socket ../$longname/socket socket])
>  AT_CLEANUP
>  
> -m4_define([UNIX_SOCKET_SHORT_PATHNAME_PYN],
> -  [AT_SETUP([unix socket, short pathname - $1])
> -   AT_SKIP_IF([test $2 = no || test "$IS_WIN32" = "yes"])
> -   AT_KEYWORDS([python unixsocket])
> -   AT_CHECK([$3 $srcdir/test-unix-socket.py x])
> -   AT_CLEANUP])
> -
> -UNIX_SOCKET_SHORT_PATHNAME_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIX_SOCKET_SHORT_PATHNAME_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_SETUP([unix socket, short pathname - Python3])
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +AT_KEYWORDS([python unixsocket])
> +AT_CHECK([$PYTHON3 $srcdir/test-unix-socket.py x])
> +AT_CLEANUP
>  
>  dnl Unix sockets with long names are problematic because the name has to
>  dnl go in a fixed-length field in struct sockaddr_un.  Generally the limit
>  dnl is about 100 bytes.  On Linux, we work around this by indirecting through
>  dnl a directory fd using /proc/self/fd/<dirfd>.  We do not have a workaround
>  dnl for other platforms, so we skip the test there.
> -m4_define([UNIX_SOCKET_LONG_PATHNAME_PYN],
> -  [AT_SETUP([unix socket, long pathname - $1])
> -   AT_SKIP_IF([test $2 = no || test "$IS_WIN32" = "yes"])
> -   AT_KEYWORDS([python unixsocket])
> -   dnl Linux sockaddr_un has a 108-byte limit, so this needs to be longer.
> -   dnl Linux "ecryptfs" has a 143-byte limit, so we use that many bytes.
> -   longname=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
> -
> -   dnl Skip the test if the directory can't be created (presumably the file
> -   dnl system doesn't support such long names).
> -   AT_CHECK([mkdir $longname || exit 77])
> -   AT_CHECK([cd $longname && $3 $abs_srcdir/test-unix-socket.py ../$longname/socket socket])
> -   AT_CLEANUP])
> +AT_SETUP([unix socket, long pathname - Python3])
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +AT_KEYWORDS([python unixsocket])
> +dnl Linux sockaddr_un has a 108-byte limit, so this needs to be longer.
> +dnl Linux "ecryptfs" has a 143-byte limit, so we use that many bytes.
> +longname=01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012
>  
> -UNIX_SOCKET_LONG_PATHNAME_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIX_SOCKET_LONG_PATHNAME_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +dnl Skip the test if the directory can't be created (presumably the file
> +dnl system doesn't support such long names).
> +AT_CHECK([mkdir $longname || exit 77])
> +AT_CHECK([cd $longname && $PYTHON3 $abs_srcdir/test-unix-socket.py ../$longname/socket socket])
> +AT_CLEANUP
>  
>  AT_SETUP([ovs_assert])
>  if test "$IS_WIN32" = "yes"; then
> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
> index dc21c8889d70..02d05046acb0 100644
> --- a/tests/ofproto-dpif.at
> +++ b/tests/ofproto-dpif.at
> @@ -5394,7 +5394,7 @@ AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=
>  ])
>  
>  # The packet should be received by port 2
> -AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
> +AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
>  
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
> @@ -5429,7 +5429,7 @@ AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=
>  ])
>  
>  # The packet should be received by port 2
> -AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
> +AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
>  
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
> @@ -5470,7 +5470,7 @@ AT_CHECK([strip_xids < stdout | sed -n 's/duration=[[0-9]]*\.[[0-9]]*s/duration=
>  ])
>  
>  # The packet should be received by port 1
> -AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p1-tx.pcap | wc -l`])
> +AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p1-tx.pcap | wc -l`])
>  
>  OVS_VSWITCHD_STOP
>  AT_CLEANUP
> @@ -5506,8 +5506,8 @@ ovs-vsctl show
>  ovs-ofctl dump-flows br0
>  
>  # The packet should be received by port 2 and not port 3
> -AT_CHECK([test 1 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
> -AT_CHECK([test 0 = `$PYTHON "$top_srcdir/utilities/ovs-pcap.in" p3-tx.pcap | wc -l`])
> +AT_CHECK([test 1 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p2-tx.pcap | wc -l`])
> +AT_CHECK([test 0 = `$PYTHON3 "$top_srcdir/utilities/ovs-pcap.in" p3-tx.pcap | wc -l`])
>  
>  # NXT_RESUMEs should be 1 and reg1 should be set to 0x5.
>  OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep NXT_RESUME | grep -c reg1=0x5`])
> diff --git a/tests/ofproto.at b/tests/ofproto.at
> index a810dd6042fd..c81409d9d17c 100644
> --- a/tests/ofproto.at
> +++ b/tests/ofproto.at
> @@ -4769,7 +4769,7 @@ m4_divert_push([PREPARE_TESTS])
>  # past the nearest line that does not start with a space.
>  [
>  multiline_sort () {
> -    $PYTHON -c '
> +    $PYTHON3 -c '
>  import sys
>  
>  buffer = []
> @@ -5056,7 +5056,7 @@ ovs-appctl -t ovs-ofctl ofctl/block
>  
>  # Add $n_msgs flows.
>  (echo "in_port=2,actions=output:2"
> -$PYTHON -c '
> +$PYTHON3 -c '
>  for i in range('$n_msgs'):
>      print("cookie=1,reg1=%d,actions=drop" % i)
>  ') > flows.txt
> diff --git a/tests/ovs-macros.at b/tests/ovs-macros.at
> index b6add7fda5e1..e07c4b908e0a 100644
> --- a/tests/ovs-macros.at
> +++ b/tests/ovs-macros.at
> @@ -184,7 +184,7 @@ wc () {
>  }
>  
>  uuidfilt () {
> -    $PYTHON "$top_srcdir"/tests/uuidfilt.py "$@"
> +    $PYTHON3 "$top_srcdir"/tests/uuidfilt.py "$@"
>  }
>  
>  # run_as PROGRAM_NAME COMMAND [ARG...]
> diff --git a/tests/ovs-xapi-sync.at b/tests/ovs-xapi-sync.at
> index 2f00704ba9a8..ab96c4d53e23 100644
> --- a/tests/ovs-xapi-sync.at
> +++ b/tests/ovs-xapi-sync.at
> @@ -1,7 +1,6 @@
>  AT_BANNER([ovs-xapi-sync])
>  
>  AT_SETUP([ovs-xapi-sync])
> -AT_SKIP_IF([test $HAVE_PYTHON = no])
>  
>  # Mock up the XenAPI.
>  cp "$top_srcdir/tests/MockXenAPI.py" XenAPI.py
> @@ -26,7 +25,7 @@ ovs_vsctl () {
>  OVS_VSCTL_SETUP
>  
>  # Start ovs-xapi-sync.
> -AT_CHECK([$PYTHON ./ovs-xapi-sync "--pidfile=ovs-xapi-sync.pid" \
> +AT_CHECK([$PYTHON3 ./ovs-xapi-sync "--pidfile=ovs-xapi-sync.pid" \
>                    "--root-prefix=`pwd`" unix:db.sock >log 2>&1 &])
>  AT_CAPTURE_FILE([log])
>  
> diff --git a/tests/ovsdb-data.at b/tests/ovsdb-data.at
> index 8c40bcfbfc27..8cd2a26cb3ff 100644
> --- a/tests/ovsdb-data.at
> +++ b/tests/ovsdb-data.at
> @@ -260,7 +260,7 @@ dnl
>  dnl <C0> is not allowed anywhere in a UTF-8 string.
>  dnl (<ED A0 80> is not allowed in UTF-8 but Python doesn't care.)
>  dnl <ED 80 7F> is not allowed in UTF-8.
> -OVSDB_CHECK_POSITIVE_PY([no invalid UTF-8 sequences in strings - Python],
> +OVSDB_CHECK_POSITIVE_PY3([no invalid UTF-8 sequences in strings - Python],
>    [parse-atoms '[["string"]]' \
>       '@<:@"m4_esyscmd([printf "\300"])"@:>@' \
>       '@<:@"m4_esyscmd([printf "\355\200\177"])"@:>@' \
> @@ -533,12 +533,7 @@ OVSDB_CHECK_POSITIVE_CPY([strings at least 2 characters long],
>  constraint violation: "a" length 1 is less than minimum allowed length 2
>  "ab"
>  "abc"
> -constraint violation: "𝄞" length 1 is less than minimum allowed length 2]],
> -  [],
> -  [],
> -  [dnl This test requires a wide build of Python.
> -   AT_CHECK([$PYTHON -c 'unichr(0x10000)' || exit 77],
> -            [0], [ignore], [ignore])])
> +constraint violation: "𝄞" length 1 is less than minimum allowed length 2]])
>  
>  OVSDB_CHECK_POSITIVE_CPY([strings no more than 2 characters long],
>    [[parse-atoms '{"type": "string", "maxLength": 2}' \
> diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
> index 7c937f74276b..cc38d69c106c 100644
> --- a/tests/ovsdb-idl.at
> +++ b/tests/ovsdb-idl.at
> @@ -112,74 +112,52 @@ m4_define([OVSDB_CHECK_IDL_TCP6_C],
>     AT_CLEANUP])
>  
>  # same as OVSDB_CHECK_IDL but uses the Python IDL implementation.
> -m4_define([OVSDB_CHECK_IDL_PYN],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_PY],
> +  [AT_SETUP([$1 - Python3])
>     AT_KEYWORDS([ovsdb server idl positive Python $5])
>     AT_CHECK([ovsdb_start_idltest])
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_PY],
> -   [OVSDB_CHECK_IDL_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
> -m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PYN],
> -  [AT_SETUP([$1 - register_columns])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY],
> +  [AT_SETUP([$1 - Python3 - register_columns])
>     AT_KEYWORDS([ovsdb server idl positive Python register_columns $5])
>     AT_CHECK([ovsdb_start_idltest])
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?link1:i,k,ka,l2?link2:i,l1?singleton:name $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?link1:i,k,ka,l2?link2:i,l1?singleton:name $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY],
> -   [OVSDB_CHECK_IDL_REGISTER_COLUMNS_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_REGISTER_COLUMNS_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp
> -m4_define([OVSDB_CHECK_IDL_TCP_PYN],
> -  [AT_SETUP([$1 - tcp])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_TCP_PY],
> +  [AT_SETUP([$1 - Python3 - tcp])
>     AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
>     AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"])
>     PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
>  
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema tcp:127.0.0.1:$TCP_PORT $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema tcp:127.0.0.1:$TCP_PORT $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_TCP_PY],
> -   [OVSDB_CHECK_IDL_TCP_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_TCP_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp
>  # with multiple remotes with only one remote reachable
> -m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN],
> -  [AT_SETUP([$1 - tcp])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PY],
> +  [AT_SETUP([$1 - Python3 (multiple remotes) - tcp])
>     AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
>     AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"])
>     PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> @@ -188,23 +166,16 @@ m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN],
>     remote=tcp:127.0.0.1:$WRONG_PORT_1,tcp:127.0.0.1:$TCP_PORT,tcp:127.0.0.1:$WRONG_PORT_2
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact tcp:127.0.0.1:$TCP_PORT $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t20 idl $srcdir/idltest.ovsschema $remote $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t20 idl $srcdir/idltest.ovsschema $remote $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PY],
> -   [OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN([$1 - Python2 (multiple remotes)], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON], [$PYTHON])
> -    OVSDB_CHECK_IDL_TCP_MULTIPLE_REMOTES_PYN([$1 - Python3 (multiple remotes)], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp6
> -m4_define([OVSDB_CHECK_IDL_TCP6_PYN],
> -  [AT_SETUP([$1 - tcp6])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_TCP6_PY],
> +  [AT_SETUP([$1 - Python3 - tcp6])
>     AT_SKIP_IF([test "$IS_WIN32" = "yes"])
>     AT_SKIP_IF([test $HAVE_IPV6 = no])
>     AT_KEYWORDS([ovsdb server idl positive Python with tcp6 socket $5])
> @@ -214,22 +185,15 @@ m4_define([OVSDB_CHECK_IDL_TCP6_PYN],
>  
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact "tcp:[[::1]]:$TCP_PORT" $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema tcp:[[::1]]:$TCP_PORT $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema tcp:[[::1]]:$TCP_PORT $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_TCP6_PY],
> -   [OVSDB_CHECK_IDL_TCP6_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_TCP6_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
> -m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN],
> -  [AT_SETUP([$1 - tcp6])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY],
> +  [AT_SETUP([$1 - Python3 - tcp6])
>     AT_SKIP_IF([test "$IS_WIN32" = "yes"])
>     AT_SKIP_IF([test $HAVE_IPV6 = no])
>     AT_KEYWORDS([ovsdb server idl positive Python with tcp6 socket $5])
> @@ -240,25 +204,18 @@ m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN],
>     remote="tcp:[[::1]]:$WRONG_PORT_1,tcp:[[::1]]:$TCP_PORT,tcp:[[::1]]:$WRONG_PORT_2"
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact "tcp:[[::1]]:$TCP_PORT" $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t20 idl $srcdir/idltest.ovsschema $remote $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t20 idl $srcdir/idltest.ovsschema $remote $3],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY],
> -   [OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN([$1 - Python2 (multiple remotes)], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON], [$PYTHON])
> -    OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PYN([$1 - Python3 (multiple remotes)], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  # same as OVSDB_CHECK_IDL but uses the Python IDL implementation with SSL
> -m4_define([OVSDB_CHECK_IDL_SSL_PYN],
> -  [AT_SETUP([$1 - SSL])
> +m4_define([OVSDB_CHECK_IDL_SSL_PY],
> +  [AT_SETUP([$1 - Python3 - SSL])
>     AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
> -   AT_SKIP_IF([test $7 = no])
> -   $8 -c "import OpenSSL.SSL"
> +   $PYTHON3 -c "import OpenSSL.SSL"
>     SSL_PRESENT=$?
>     AT_SKIP_IF([test $SSL_PRESENT != 0])
>     AT_KEYWORDS([ovsdb server idl positive Python with ssl socket $5])
> @@ -279,7 +236,7 @@ m4_define([OVSDB_CHECK_IDL_SSL_PYN],
>                  --certificate=$PKIDIR/testpki-cert2.pem \
>                  --ca-cert=$PKIDIR/testpki-cacert.pem \
>                  transact "ssl:127.0.0.1:$TCP_PORT" $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema \
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema \
>               ssl:127.0.0.1:$TCP_PORT $PKIDIR/testpki-privkey.pem \
>               $PKIDIR/testpki-cert.pem $PKIDIR/testpki-cacert.pem $3],
>              [0], [stdout], [ignore])
> @@ -288,12 +245,6 @@ m4_define([OVSDB_CHECK_IDL_SSL_PYN],
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_SSL_PY],
> -   [OVSDB_CHECK_IDL_SSL_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON], [$PYTHON])
> -    OVSDB_CHECK_IDL_SSL_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  m4_define([OVSDB_CHECK_IDL],
>    [OVSDB_CHECK_IDL_C($@)
>     OVSDB_CHECK_IDL_TCP_C($@)
> @@ -307,9 +258,8 @@ m4_define([OVSDB_CHECK_IDL],
>     OVSDB_CHECK_IDL_SSL_PY($@)])
>  
>  # This test uses the Python IDL implementation with passive tcp
> -m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PYN],
> -  [AT_SETUP([$1 ptcp])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PY],
> +  [AT_SETUP([$1 - Python3 - ptcp])
>     AT_KEYWORDS([ovsdb server idl positive Python with tcp socket $5])
>     # find free TCP port
>     AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"])
> @@ -319,7 +269,7 @@ m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PYN],
>  
>     # start OVSDB server in passive mode
>     AT_CHECK([ovsdb_start_idltest "tcp:127.0.0.1:$TCP_PORT"])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py -t10 idl_passive $srcdir/idltest.ovsschema ptcp:127.0.0.1:$TCP_PORT $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py -t10 idl_passive $srcdir/idltest.ovsschema ptcp:127.0.0.1:$TCP_PORT $3],
>        [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
>              [0], [$4])
> @@ -327,12 +277,6 @@ m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PYN],
>     AT_CLEANUP
>     ])
>  
> -m4_define([OVSDB_CHECK_IDL_PASSIVE_TCP_PY],
> -    [OVSDB_CHECK_IDL_PASSIVE_TCP_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_PASSIVE_TCP_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  OVSDB_CHECK_IDL_PASSIVE_TCP_PY([simple passive idl, initially empty, select empty],
>    [],
>    [['["idltest",{"op":"select","table":"link1","where":[]}]']],
> @@ -501,14 +445,13 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL with unicode],
>  003: done
>  ]])
>  
> -m4_define([OVSDB_CHECK_IDL_PYN_WITH_EXPOUT],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_PY_WITH_EXPOUT],
> +  [AT_SETUP([$1 - Python3])
>     AT_KEYWORDS([ovsdb server idl positive Python $5])
>     AT_CHECK([ovsdb_start_idltest])
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $3],
>              [0], [stdout], [ignore])
>     echo "$4" > expout
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
> @@ -516,12 +459,6 @@ m4_define([OVSDB_CHECK_IDL_PYN_WITH_EXPOUT],
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_PY_WITH_EXPOUT],
> -   [OVSDB_CHECK_IDL_PYN_WITH_EXPOUT([$1 - Python2], [$2], [$3], [$4], [$5], [$6],
> -                                    [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_PYN_WITH_EXPOUT([$1 - Python3], [$2], [$3], [$4], [$5], [$6],
> -                                    [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  OVSDB_CHECK_IDL_PY_WITH_EXPOUT([simple idl, writing large data via IDL with unicode],
>    [['["idltest",
>        {"op": "insert",
> @@ -1036,26 +973,19 @@ AT_CHECK([grep '"monitor\|monitor_cond"' stderr | grep -c '"ua"'], [0], [1
>  OVSDB_SERVER_SHUTDOWN
>  AT_CLEANUP
>  
> -m4_define([OVSDB_CHECK_IDL_FETCH_COLUMNS_PYN],
> -  [AT_SETUP([$1 fetch])
> -   AT_SKIP_IF([test $8 = no])
> +m4_define([OVSDB_CHECK_IDL_FETCH_COLUMNS_PY],
> +  [AT_SETUP([$1 - Python3 - fetch])
>     AT_KEYWORDS([ovsdb server idl positive Python increment fetch $6])
>     AT_CHECK([ovsdb_start_idltest])
>     m4_if([$2], [], [],
>       [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])])
> -   AT_CHECK([$9 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket [$3] $4],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket [$3] $4],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$7],,, [[| $7]]),
>              [0], [$5])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_FETCH_COLUMNS_PY],
> -    [OVSDB_CHECK_IDL_FETCH_COLUMNS_PYN([$1 - Python2], [$2], [$3], [$4], [$5], [$6], [$7],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_FETCH_COLUMNS_PYN([$1 - Python3], [$2], [$3], [$4], [$5], [$6], [$7],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  m4_define([OVSDB_CHECK_IDL_FETCH_COLUMNS],
>     [OVSDB_CHECK_IDL_FETCH_COLUMNS_PY($@)])
>  
> @@ -1087,26 +1017,18 @@ OVSDB_CHECK_IDL_FETCH_COLUMNS([simple idl, initially populated],
>  003: done
>  ]])
>  
> -m4_define([OVSDB_CHECK_IDL_WO_MONITOR_COND_PYN],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $6 = no])
> +m4_define([OVSDB_CHECK_IDL_WO_MONITOR_COND_PY],
> +  [AT_SETUP([$1 - Python3])
>     AT_KEYWORDS([ovsdb server idl Python monitor $4])
>     AT_CHECK([ovsdb_start_idltest])
>     AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/disable-monitor-cond])
> -   AT_CHECK([$7 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $2],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket $2],
>              [0], [stdout], [ignore])
>     AT_CHECK([sort stdout | uuidfilt]m4_if([$5],,, [[| $5]]),
>              [0], [$3])
>     OVSDB_SERVER_SHUTDOWN
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_WO_MONITOR_COND_PY],
> -    [OVSDB_CHECK_IDL_WO_MONITOR_COND_PYN([$1 - Python2], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_WO_MONITOR_COND_PYN([$1 - Python3], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
> -
>  m4_define([OVSDB_CHECK_IDL_WO_MONITOR_COND],
>     [OVSDB_CHECK_IDL_WO_MONITOR_COND_PY($@)])
>  
> @@ -1426,28 +1348,9 @@ OVSDB_CHECK_IDL_PY([partial-set idl],
>  015: done
>  ]])
>  
> -m4_define([OVSDB_CHECK_IDL_NOTIFY_PYN],
> -  [OVSDB_CHECK_IDL_PYN([$1], [], [$2], [$3], [notify $4], [$5], [$6], [$7])])
> -
> -m4_define([OVSDB_CHECK_IDL_NOTIFY_PY],
> -    [OVSDB_CHECK_IDL_NOTIFY_PYN([$1 - Python2], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_NOTIFY_PYN([$1 - Python3], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
> -# This test uses the Python IDL implementation with ssl
> -m4_define([OVSDB_CHECK_IDL_NOTIFY_SSL_PYN],
> -  [OVSDB_CHECK_IDL_SSL_PYN([$1], [], [$2], [$3], [notify $4], [$5], [$6], [$7])])
> -
> -m4_define([OVSDB_CHECK_IDL_NOTIFY_SSL_PY],
> -    [OVSDB_CHECK_IDL_NOTIFY_SSL_PYN([$1 - Python2], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON2], [$PYTHON2])
> -    OVSDB_CHECK_IDL_NOTIFY_SSL_PYN([$1 - Python3], [$2], [$3], [$4], [$5],
> -                        [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  m4_define([OVSDB_CHECK_IDL_NOTIFY],
> -   [OVSDB_CHECK_IDL_NOTIFY_PY($@)
> -    OVSDB_CHECK_IDL_NOTIFY_SSL_PY($@)])
> +   [OVSDB_CHECK_IDL_PY([$1], [], [$2], [$3], [notify $4], [$5])
> +    OVSDB_CHECK_IDL_SSL_PY([$1], [], [$2], [$3], [notify $4], [$5])])
>  
>  OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify],
>    [['track-notify' \
> @@ -1878,8 +1781,7 @@ CHECK_STREAM_OPEN_BLOCK([tcp], [127.0.0.1])
>  CHECK_STREAM_OPEN_BLOCK([tcp6], [[[::1]]])
>  
>  m4_define([CHECK_STREAM_OPEN_BLOCK_PY],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $2 = no])
> +  [AT_SETUP([$1 - Python3])
>     AT_KEYWORDS([Check PY Stream open block - $3])
>     AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"])
>     PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
> @@ -1890,14 +1792,10 @@ m4_define([CHECK_STREAM_OPEN_BLOCK_PY],
>     AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$TCP_PORT], [1], [ignore])
>     AT_CLEANUP])
>  
> -CHECK_STREAM_OPEN_BLOCK_PY([Check PY2 Stream open block], [$HAVE_PYTHON2], [$PYTHON2])
> -CHECK_STREAM_OPEN_BLOCK_PY([Check PY3 Stream open block], [$HAVE_PYTHON3], [$PYTHON3])
> -
>  # same as OVSDB_CHECK_IDL but uses Python IDL implementation with tcp
>  # with multiple remotes to assert the idl connects to the leader of the Raft cluster
> -m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PYN],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $7 = no])
> +m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
> +  [AT_SETUP([$1 - Python3 (leader only)])
>     AT_KEYWORDS([ovsdb server idl Python leader_only with tcp socket])
>     m4_define([LPBK],[127.0.0.1])
>     AT_CHECK([ovsdb_cluster_start_idltest $2 "ptcp:0:"LPBK])
> @@ -1907,18 +1805,12 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PYN],
>     remotes=tcp:LPBK:$TCP_PORT_1,tcp:LPBK:$TCP_PORT_2,tcp:LPBK:$TCP_PORT_3
>     pids=$(cat s2.pid s3.pid s1.pid | tr '\n' ',')
>     echo $pids
> -   AT_CHECK([$8 $srcdir/test-ovsdb.py  -t30 idl-cluster $srcdir/idltest.ovsschema $remotes $pids $3],
> +   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t30 idl-cluster $srcdir/idltest.ovsschema $remotes $pids $3],
>          [0], [stdout], [ignore])
>     remote=$(ovsdb_cluster_leader $remotes "idltest")
>     leader=$(echo $remote | cut -d'|' -f 1)
>     AT_CHECK([grep -F -- "${leader}" stdout], [0], [ignore])
>     AT_CLEANUP])
>  
> -m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
> -   [OVSDB_CHECK_IDL_LEADER_ONLY_PYN([$1 - Python2 (leader only)], [$2], [$3], [$4], [$5], [$6],
> -                 [$HAVE_PYTHON], [$PYTHON])
> -    OVSDB_CHECK_IDL_LEADER_ONLY_PYN([$1 - Python3 (leader only)], [$2], [$3], [$4], [$5], [$6],
> -                 [$HAVE_PYTHON3], [$PYTHON3])])
> -
>  OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL connects to leader], 3, ['remote'])
>  OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL reconnects to leader], 3, ['remote' '+remotestop' 'remote'])
> diff --git a/tests/ovsdb-macros.at b/tests/ovsdb-macros.at
> index 638894794828..1613642d5a2a 100644
> --- a/tests/ovsdb-macros.at
> +++ b/tests/ovsdb-macros.at
> @@ -27,25 +27,6 @@ m4_define([OVSDB_CHECK_POSITIVE],
>     AT_CLEANUP])
>  
>  # OVSDB_CHECK_POSITIVE_PY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ],
> -#                         [PY-CHECK])
> -#
> -# Runs "test-ovsdb.py TEST-OVSDB-ARGS" and checks that it exits with
> -# status 0 and prints OUTPUT on stdout.
> -#
> -# PY-CHECK is expanded before the check.  It can check for features of the
> -# Python implementation that are required for the test to pass.
> -#
> -# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
> -m4_define([OVSDB_CHECK_POSITIVE_PY],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $HAVE_PYTHON2 = no])
> -   $6
> -   AT_KEYWORDS([ovsdb positive Python $4])
> -   AT_CHECK([$PYTHON2 $srcdir/test-ovsdb.py $2], [0], [$3
> -], [])
> -   AT_CLEANUP])
> -
> -# OVSDB_CHECK_POSITIVE_PY3(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ],
>  #                          [PY-CHECK])
>  #
>  # Runs "test-ovsdb.py TEST-OVSDB-ARGS" and checks that it exits with
> @@ -55,9 +36,8 @@ m4_define([OVSDB_CHECK_POSITIVE_PY],
>  # Python implementation that are required for the test to pass.
>  #
>  # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
> -m4_define([OVSDB_CHECK_POSITIVE_PY3],
> +m4_define([OVSDB_CHECK_POSITIVE_PY],
>    [AT_SETUP([$1])
> -   AT_SKIP_IF([test $HAVE_PYTHON3 = no])
>     $6
>     AT_KEYWORDS([ovsdb positive Python $4])
>     AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py $2], [0], [$3
> @@ -65,13 +45,12 @@ m4_define([OVSDB_CHECK_POSITIVE_PY3],
>     AT_CLEANUP])
>  
>  # OVSDB_CHECK_POSITIVE_CPY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS],
> -#                          [PREREQ], [PY2-CHECK], [PY3-CHECK])
> +#                          [PREREQ], [PY3-CHECK])
>  #
>  # Runs identical C and Python tests, as specified.
>  m4_define([OVSDB_CHECK_POSITIVE_CPY],
>    [OVSDB_CHECK_POSITIVE([$1 - C], [$2], [$3], [$4], [$5])
> -   OVSDB_CHECK_POSITIVE_PY([$1 - Python2], [$2], [$3], [$4], [$5], [$6])
> -   OVSDB_CHECK_POSITIVE_PY3([$1 - Python3], [$2], [$3], [$4], [$5], [$7])])
> +   OVSDB_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4], [$5], [$7])])
>  
>  # OVSDB_CHECK_NEGATIVE(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ])
>  #
> @@ -100,28 +79,6 @@ m4_define([OVSDB_CHECK_NEGATIVE],
>  # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
>  m4_define([OVSDB_CHECK_NEGATIVE_PY],
>    [AT_SETUP([$1])
> -   AT_SKIP_IF([test $HAVE_PYTHON2 = no])
> -   AT_KEYWORDS([ovsdb negative $4])
> -   AT_CHECK([$PYTHON2 $srcdir/test-ovsdb.py $2], [1], [], [stderr])
> -   m4_assert(m4_len([$3]))
> -   AT_CHECK(
> -     [if grep -F -e "AS_ESCAPE([$3])" stderr
> -      then
> -        :
> -      else
> -        exit 99
> -      fi],
> -            [0], [ignore], [ignore])
> -   AT_CLEANUP])
> -
> -# OVSDB_CHECK_NEGATIVE_PY3(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ])
> -#
> -# Runs "test-ovsdb TEST-OVSDB-ARGS" and checks that it exits with
> -# status 1 and that its output on stdout contains substring OUTPUT.
> -# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
> -m4_define([OVSDB_CHECK_NEGATIVE_PY],
> -  [AT_SETUP([$1])
> -   AT_SKIP_IF([test $HAVE_PYTHON3 = no])
>     AT_KEYWORDS([ovsdb negative $4])
>     AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py $2], [1], [], [stderr])
>     m4_assert(m4_len([$3]))
> @@ -141,8 +98,7 @@ m4_define([OVSDB_CHECK_NEGATIVE_PY],
>  # Runs identical C and Python tests, as specified.
>  m4_define([OVSDB_CHECK_NEGATIVE_CPY],
>    [OVSDB_CHECK_NEGATIVE([$1 - C], [$2], [$3], [$4], [$5])
> -   OVSDB_CHECK_NEGATIVE_PY([$1 - Python2], [$2], [$3], [$4], [$5])
> -   OVSDB_CHECK_NEGATIVE_PY3([$1 - Python3], [$2], [$3], [$4], [$5])])
> +   OVSDB_CHECK_NEGATIVE_PY([$1 - Python3], [$2], [$3], [$4], [$5])])
>  
>  OVS_START_SHELL_HELPERS
>  ovsdb_client_wait() {
> diff --git a/tests/ovsdb-monitor.at b/tests/ovsdb-monitor.at
> index eb437092c918..3b622b3ec059 100644
> --- a/tests/ovsdb-monitor.at
> +++ b/tests/ovsdb-monitor.at
> @@ -30,7 +30,7 @@ ovsdb_check_monitor () {
>      done
>      OVS_APP_EXIT_AND_WAIT_BY_TARGET([ovsdb-server], [ovsdb-server.pid])
>      OVS_WAIT_UNTIL([test ! -e ovsdb-client.pid])
> -    AT_CHECK_UNQUOTED([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [$output], [ignore])
> +    AT_CHECK_UNQUOTED([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [$output], [ignore])
>  }
>  OVS_END_SHELL_HELPERS
>  
> @@ -105,7 +105,7 @@ m4_define([OVSDB_CHECK_MONITOR_COND],
>              [ignore], [ignore])
>     AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>     OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -   AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [$7], [ignore])
> +   AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [$7], [ignore])
>     AT_CLEANUP])
>  
>  OVSDB_CHECK_MONITOR([monitor insert into empty table],
> @@ -649,7 +649,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [[row,action,name
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0], [[row,action,name
>  <0>,insert,"""ten"""
>  
>  row,action,name
> @@ -701,7 +701,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: false, last_id: <0>
>  row,action,name,number,_version
>  <1>,initial,"""one""",1,"[""uuid"",""<2>""]"
> @@ -770,7 +770,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: true, last_id: <0>
>  row,action,name,number,_version
>  <1>,insert,"""ten""",10,"[""uuid"",""<2>""]"
> @@ -814,7 +814,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: true, last_id: <0>
>  ]], [ignore])
>  AT_CLEANUP
> @@ -837,7 +837,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: false, last_id: <0>
>  ]], [ignore])
>  AT_CLEANUP
> @@ -876,7 +876,7 @@ AT_CHECK([ovsdb-client transact unix:socket '[["ordinals"]]'], [0],
>           [ignore], [ignore])
>  AT_CHECK([ovs-appctl -t ovsdb-server -e exit], [0], [ignore], [ignore])
>  OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: false, last_id: <0>
>  row,action,name,number,_version
>  <1>,initial,"""one""",1,"[""uuid"",""<2>""]"
> @@ -945,7 +945,7 @@ OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
>  
>  # Transaction shouldn't be found, and last_id returned should always
>  # be the same (all zero uuid)
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: false, last_id: <0>
>  row,action,name,number,_version
>  <1>,initial,"""one""",1,"[""uuid"",""<2>""]"
> @@ -1000,7 +1000,7 @@ OVS_WAIT_UNTIL([test ! -e ovsdb-server.pid && test ! -e ovsdb-client.pid])
>  
>  # Transaction shouldn't be found, and last_id returned should always
>  # be the same (all zero uuid)
> -AT_CHECK([$PYTHON $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
> +AT_CHECK([$PYTHON3 $srcdir/ovsdb-monitor-sort.py < output | uuidfilt], [0],
>           [[found: false, last_id: <0>
>  row,action,name,number,_version
>  <1>,initial,"""one""",1,"[""uuid"",""<2>""]"
> diff --git a/tests/reconnect.at b/tests/reconnect.at
> index ecd76cbc582d..2631658be08a 100644
> --- a/tests/reconnect.at
> +++ b/tests/reconnect.at
> @@ -2,28 +2,19 @@ AT_BANNER([reconnect library])
>  
>  m4_define([__RECONNECT_CHECK],
>    [AT_SETUP([$1])
> -   $2
>     AT_KEYWORDS([reconnect])
> -   AT_DATA([input], [$3])
> -   AT_CHECK([$4], [0], [$5])
> +   AT_DATA([input], [$2])
> +   AT_CHECK([$3], [0], [$4])
>     AT_CLEANUP])
>  
>  m4_define([RECONNECT_CHECK],
>    [__RECONNECT_CHECK(
>       [$1 - C],
> -     [],
>       [$2],
>       [ovstest test-reconnect < input],
>       [$3])
> -   __RECONNECT_CHECK(
> -     [$1 - Python2],
> -     [AT_SKIP_IF([test $HAVE_PYTHON2 = no])],
> -     [$2],
> -     [$PYTHON2 $srcdir/test-reconnect.py < input],
> -     [$3])
>     __RECONNECT_CHECK(
>       [$1 - Python3],
> -     [AT_SKIP_IF([test $HAVE_PYTHON3 = no])],
>       [$2],
>       [$PYTHON3 $srcdir/test-reconnect.py < input],
>       [$3])])
> diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
> index 64bf5ec63ab4..68c8774d1ac6 100644
> --- a/tests/system-common-macros.at
> +++ b/tests/system-common-macros.at
> @@ -267,7 +267,7 @@ m4_define([OVS_CHECK_FIREWALL],
>  #
>  m4_define([OVS_START_L7],
>     [PIDFILE=$(mktemp $2XXX.pid)
> -    NETNS_DAEMONIZE([$1], [[$PYTHON $srcdir/test-l7.py $2]], [$PIDFILE])
> +    NETNS_DAEMONIZE([$1], [[$PYTHON3 $srcdir/test-l7.py $2]], [$PIDFILE])
>  
>      dnl netstat doesn't print http over IPv6 as "http6"; drop the number.
>      PROTO=$(echo $2 | sed -e 's/\([[a-zA-Z]]*\).*/\1/')
> diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at
> index 48e94642b948..7155d63f2ce3 100644
> --- a/tests/system-kmod-macros.at
> +++ b/tests/system-kmod-macros.at
> @@ -59,8 +59,7 @@ m4_define([CONFIGURE_VETH_OFFLOADS],
>  # kernel conntrack tables when the test is finished.
>  #
>  m4_define([CHECK_CONNTRACK],
> -    [AT_SKIP_IF([test $HAVE_PYTHON = no])
> -     m4_foreach([mod], [[nf_conntrack_ipv4], [nf_conntrack_ipv6], [nf_nat_ftp],
> +    [m4_foreach([mod], [[nf_conntrack_ipv4], [nf_conntrack_ipv6], [nf_nat_ftp],
>                          [nf_nat_tftp]],
>                  [modprobe mod || echo "Module mod not loaded."
>                   on_exit 'modprobe -r mod'
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index 1a04199dcfe9..18e338021ddf 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -3524,8 +3524,8 @@ table=0,action=normal
>  
>  AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows.txt])
>  
> -NETNS_DAEMONIZE([at_ns0], [[$PYTHON $srcdir/test-l7.py ftp]], [ftp1.pid])
> -NETNS_DAEMONIZE([at_ns1], [[$PYTHON $srcdir/test-l7.py ftp]], [ftp0.pid])
> +NETNS_DAEMONIZE([at_ns0], [[$PYTHON3 $srcdir/test-l7.py ftp]], [ftp1.pid])
> +NETNS_DAEMONIZE([at_ns1], [[$PYTHON3 $srcdir/test-l7.py ftp]], [ftp0.pid])
>  OVS_WAIT_UNTIL([ip netns exec at_ns1 netstat -l | grep ftp])
>  
>  dnl FTP requests from p0->p1 should work fine.
> @@ -5291,7 +5291,7 @@ dnl waiting, we get occasional failures due to the following error:
>  dnl "connect: Cannot assign requested address"
>  OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 1 fc00::2 >/dev/null])
>  
> -NETNS_DAEMONIZE([at_ns1], [[$PYTHON $srcdir/test-l7.py ftp]], [ftp0.pid])
> +NETNS_DAEMONIZE([at_ns1], [[$PYTHON3 $srcdir/test-l7.py ftp]], [ftp0.pid])
>  OVS_WAIT_UNTIL([ip netns exec at_ns1 netstat -l | grep ftp])
>  
>  dnl FTP requests from p0->p1 should work fine.
> @@ -5879,7 +5879,7 @@ sleep 1
>  dnl The hex dump is a TCP syn packet. pkt=eth/ip/tcp
>  dnl The packet is sent from p0(at_ns0) interface directed to
>  dnl p1(at_ns1) interface
> -NS_CHECK_EXEC([at_ns0], [$PYTHON $srcdir/sendpkt.py p0 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
>  
>  dnl Check the expected nsh encapsulated packet on the egress interface
>  OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0000: *f2ff *0000 *0002 *f2ff *0000 *0001 *894f *0fc6" 2>&1 1>/dev/null])
> @@ -5911,7 +5911,7 @@ sleep 1
>  dnl The hex dump is NSH packet with TCP syn payload. pkt=eth/nsh/eth/ip/tcp
>  dnl The packet is sent from p0(at_ns0) interface directed to
>  dnl p1(at_ns1) interface
> -NS_CHECK_EXEC([at_ns0], [$PYTHON $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 00 64 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 00 64 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
>  
>  dnl Check the expected de-capsulated TCP packet on the egress interface
>  OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0000: *f200 *0000 *0002 *f200 *0000 *0001 *0800 *4500" 2>&1 1>/dev/null])
> @@ -5944,7 +5944,7 @@ dnl The hex dump is NSH packet with TCP syn payload. pkt=eth/nsh/eth/ip/tcp
>  dnl The nsh_ttl is 8, nsh_spi is 0x100 and nsh_si is 3
>  dnl The packet is sent from p0(at_ns0) interface directed to
>  dnl p1(at_ns1) interface
> -NS_CHECK_EXEC([at_ns0], [$PYTHON $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 03 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
>  
>  dnl Check the expected NSH packet with new fields in the header
>  OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0000: *f2ff *0000 *0002 *f2ff *0000* 0001 *894f *01c6" 2>&1 1>/dev/null])
> @@ -5978,7 +5978,7 @@ NS_CHECK_EXEC([at_ns2], [tcpdump -l -n -xx -U -i p2 > p2.pcap &])
>  sleep 1
>  
>  dnl First send packet from at_ns0 --> OVS with SPI=0x100 and SI=2
> -NS_CHECK_EXEC([at_ns0], [$PYTHON $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 02 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
> +NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 02 06 01 03 00 01 00 02 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
>  
>  dnl Check for the above packet on p1 interface
>  OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0000: *f2ff *0000 *0002 *f2ff *0000 *0001 *894f *0206" 2>&1 1>/dev/null])
> @@ -5989,7 +5989,7 @@ OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0040: *c0a8 *000a *0a00 *000a *0400 *0800
>  OVS_WAIT_UNTIL([cat p1.pcap | egrep "0x0050: *0000 *0000 *5002 *2000 *b85e *0000" 2>&1 1>/dev/null])
>  
>  dnl Send the second packet from at_ns1 --> OVS with SPI=0x100 and SI=1
> -NS_CHECK_EXEC([at_ns1], [$PYTHON $srcdir/sendpkt.py p1 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 01 c6 01 03 00 01 00 01 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
> +NS_CHECK_EXEC([at_ns1], [$PYTHON3 $srcdir/sendpkt.py p1 f2 ff 00 00 00 02 f2 ff 00 00 00 01 89 4f 01 c6 01 03 00 01 00 01 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 f2 00 00 00 00 02 f2 00 00 00 00 01 08 00 45 00 00 28 00 01 00 00 40 06 b0 13 c0 a8 00 0a 0a 00 00 0a 04 00 08 00 00 00 00 c8 00 00 00 00 50 02 20 00 b8 5e 00 00 > /dev/null])
>  
>  dnl Check for the above packet on p2 interface
>  OVS_WAIT_UNTIL([cat p2.pcap | egrep "0x0000: *f2ff *0000 *0002 *f2ff *0000 *0001 *894f *01c6" 2>&1 1>/dev/null])
> diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at
> index a411e3d8919d..d5e3375bc12d 100644
> --- a/tests/system-userspace-macros.at
> +++ b/tests/system-userspace-macros.at
> @@ -64,9 +64,7 @@ m4_define([CONFIGURE_VETH_OFFLOADS],
>  #
>  # Perform requirements checks for running conntrack tests.
>  #
> -m4_define([CHECK_CONNTRACK],
> -    [AT_SKIP_IF([test $HAVE_PYTHON = no])]
> -)
> +m4_define([CHECK_CONNTRACK], [])
>  
>  # CHECK_CONNTRACK_ALG()
>  #
> diff --git a/tests/unixctl-py.at b/tests/unixctl-py.at
> index 5c28e2c01df2..72400611822d 100644
> --- a/tests/unixctl-py.at
> +++ b/tests/unixctl-py.at
> @@ -1,122 +1,98 @@
>  AT_BANNER([unixctl])
>  
>  m4_define([APPCTL], [ovs-appctl --timeout 20])
> -m4_define([PYAPPCTL_PYN], [$1 $srcdir/appctl.py --timeout 20])
> +m4_define([PYAPPCTL_PY], [$PYTHON3 $srcdir/appctl.py --timeout 20])
>  
> -m4_define([UNIXCTL_EXIT_PYN],
> -  [AT_SETUP([unixctl ovs-vswitchd exit - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_KEYWORDS([python unixctl])
> -   OVS_VSWITCHD_START
> +AT_SETUP([unixctl ovs-vswitchd exit - Python3])
> +AT_KEYWORDS([python unixctl])
> +OVS_VSWITCHD_START
>  
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t ovs-vswitchd exit], [0], [])
> -   OVS_WAIT_WHILE([test -s ovs-vswitchd.pid])
> +AT_CHECK([PYAPPCTL_PY -t ovs-vswitchd exit], [0], [])
> +OVS_WAIT_WHILE([test -s ovs-vswitchd.pid])
>  
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t ovsdb-server exit], [0], [])
> -   OVS_WAIT_WHILE([test -s ovsdb-server.pid])
> -   AT_CLEANUP])
> +AT_CHECK([PYAPPCTL_PY -t ovsdb-server exit], [0], [])
> +OVS_WAIT_WHILE([test -s ovsdb-server.pid])
> +AT_CLEANUP
>  
> -UNIXCTL_EXIT_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_EXIT_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_SETUP([unixctl ovs-vswitchd list-commands - Python3])
> +OVS_VSWITCHD_START
>  
> -m4_define([UNIXCTL_LIST_COMMANDS_PYN],
> -  [AT_SETUP([unixctl ovs-vswitchd list-commands - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   OVS_VSWITCHD_START
> -
> -   AT_CHECK([APPCTL list-commands], [0], [stdout])
> -   AT_CHECK([head -1 stdout], [0], [dnl
> +AT_CHECK([APPCTL list-commands], [0], [stdout])
> +AT_CHECK([head -1 stdout], [0], [dnl
>  The available commands are:
>  ])
> -   mv stdout expout
> -   AT_CHECK([PYAPPCTL_PYN([$3]) list-commands], [0], [expout])
> -
> -   OVS_VSWITCHD_STOP
> -   AT_CLEANUP])
> +mv stdout expout
> +AT_CHECK([PYAPPCTL_PY list-commands], [0], [expout])
>  
> -UNIXCTL_LIST_COMMANDS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_LIST_COMMANDS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP]
>  
> -m4_define([UNIXCTL_ARGS_PYN],
> -  [AT_SETUP([unixctl ovs-vswitchd arguments - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   OVS_VSWITCHD_START
> +AT_SETUP([unixctl ovs-vswitchd arguments - Python3])
> +OVS_VSWITCHD_START
>  
> -   AT_CHECK([APPCTL bond/hash], [2], [], [stderr])
> -   AT_CHECK([head -1 stderr], [0], [dnl
> +AT_CHECK([APPCTL bond/hash], [2], [], [stderr])
> +AT_CHECK([head -1 stderr], [0], [dnl
>  "bond/hash" command requires at least 1 arguments
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) bond/hash], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY bond/hash], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL bond/hash mac], [2], [], [stderr])
> -   AT_CHECK([head -1 stderr], [0], [dnl
> +AT_CHECK([APPCTL bond/hash mac], [2], [], [stderr])
> +AT_CHECK([head -1 stderr], [0], [dnl
>  invalid mac
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) bond/hash mac], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY bond/hash mac], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL bond/hash mac vlan], [2], [], [stderr])
> -   AT_CHECK([head -1 stderr], [0], [dnl
> +AT_CHECK([APPCTL bond/hash mac vlan], [2], [], [stderr])
> +AT_CHECK([head -1 stderr], [0], [dnl
>  invalid vlan
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) bond/hash mac vlan], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY bond/hash mac vlan], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL bond/hash mac vlan basis], [2], [], [stderr])
> -   AT_CHECK([head -1 stderr], [0], [dnl
> +AT_CHECK([APPCTL bond/hash mac vlan basis], [2], [], [stderr])
> +AT_CHECK([head -1 stderr], [0], [dnl
>  invalid vlan
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) bond/hash vlan basis], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY bond/hash vlan basis], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL bond/hash mac vlan basis extra], [2], [], [stderr])
> -   AT_CHECK([head -1 stderr], [0], [dnl
> +AT_CHECK([APPCTL bond/hash mac vlan basis extra], [2], [], [stderr])
> +AT_CHECK([head -1 stderr], [0], [dnl
>  "bond/hash" command takes at most 3 arguments
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) bond/hash mac vlan basis extra], [2], [], [experr])
> -
> -   OVS_VSWITCHD_STOP
> -   AT_CLEANUP])
> -
> -UNIXCTL_ARGS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_ARGS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY bond/hash mac vlan basis extra], [2], [], [experr])
>  
> -m4_define([UNIXCTL_BAD_TARGET_PYN],
> -  [AT_SETUP([unixctl bad target - $1])
> -   AT_SKIP_IF([test $2 = no])
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
>  
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t bogus doit], [1], [], [stderr])
> -   AT_CHECK_UNQUOTED([tail -1 stderr], [0], [dnl
> +AT_SETUP([unixctl bad target - Python3])
> +AT_CHECK([PYAPPCTL_PY -t bogus doit], [1], [], [stderr])
> +AT_CHECK_UNQUOTED([tail -1 stderr], [0], [dnl
>  appctl.py: cannot read pidfile "`pwd`/bogus.pid" (No such file or directory)
>  ])
> -   if test "$IS_WIN32" = "no"; then
> -     AT_CHECK([PYAPPCTL_PYN([$3]) -t /bogus/path.pid doit], [1], [], [stderr])
> -     AT_CHECK([tail -1 stderr], [0], [dnl
> +if test "$IS_WIN32" = "no"; then
> +  AT_CHECK([PYAPPCTL_PY -t /bogus/path.pid doit], [1], [], [stderr])
> +  AT_CHECK([tail -1 stderr], [0], [dnl
>  appctl.py: cannot connect to "/bogus/path.pid" (No such file or directory)
>  ])
> -   else
> -     AT_CHECK([PYAPPCTL_PYN([$3]) -t c:/bogus/path.pid doit], [1], [], [stderr])
> -     AT_CHECK([tail -1 stderr], [0], [dnl
> +else
> +  AT_CHECK([PYAPPCTL_PY -t c:/bogus/path.pid doit], [1], [], [stderr])
> +  AT_CHECK([tail -1 stderr], [0], [dnl
>  appctl.py: cannot connect to "c:/bogus/path.pid" (No such file or directory)
>  ])
> -   fi
> +fi
> +AT_CLEANUP
>  
> -   AT_CLEANUP])
> +AT_SETUP([unixctl server - Python3])
> +on_exit 'kill `cat test-unixctl.py.pid`'
> +AT_CAPTURE_FILE([`pwd`/test-unixctl.py.log])
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file --pidfile --detach --no-chdir])
>  
> -UNIXCTL_BAD_TARGET_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_BAD_TARGET_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> -
> -m4_define([UNIXCTL_SERVER_PYN],
> -  [AT_SETUP([unixctl server - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> -   AT_CAPTURE_FILE([`pwd`/test-unixctl.py.log])
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file --pidfile --detach --no-chdir])
> -
> -   AT_CHECK([APPCTL -t test-unixctl.py help], [0], [stdout])
> -   AT_CHECK([cat stdout], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py help], [0], [stdout])
> +AT_CHECK([cat stdout], [0], [dnl
>  The available commands are:
>    block
>    echo                    [[arg ...]]
> @@ -130,63 +106,55 @@ The available commands are:
>    vlog/reopen
>    vlog/set                spec
>  ])
> -   mv stdout expout
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py help], [0], [expout])
> +mv stdout expout
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py help], [0], [expout])
>  
> -   AT_CHECK([ovs-vsctl --version | sed 's/ovs-vsctl/test-unixctl.py/' | head -1 > expout])
> -   AT_CHECK([APPCTL -t test-unixctl.py version], [0], [expout])
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py version], [0], [expout])
> +AT_CHECK([ovs-vsctl --version | sed 's/ovs-vsctl/test-unixctl.py/' | head -1 > expout])
> +AT_CHECK([APPCTL -t test-unixctl.py version], [0], [expout])
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py version], [0], [expout])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja], [0], [stdout])
> -   AT_CHECK([cat stdout | sed -e "s/u'/'/g"], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja], [0], [stdout])
> +AT_CHECK([cat stdout | sed -e "s/u'/'/g"], [0], [dnl
>  [['robot', 'ninja']]
>  ])
> -   mv stdout expout
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py echo robot ninja], [0], [expout])
> +mv stdout expout
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py echo robot ninja], [0], [expout])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py echo_error robot ninja], [2], [], [stderr])
> -   AT_CHECK([cat stderr | sed -e "s/u'/'/g"], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py echo_error robot ninja], [2], [], [stderr])
> +AT_CHECK([cat stderr | sed -e "s/u'/'/g"], [0], [dnl
>  [['robot', 'ninja']]
>  ovs-appctl: test-unixctl.py: server returned an error
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py echo_error robot ninja], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py echo_error robot ninja], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py echo], [2], [], [stderr])
> -   AT_CHECK([cat stderr], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py echo], [2], [], [stderr])
> +AT_CHECK([cat stderr], [0], [dnl
>  "echo" command requires at least 1 arguments
>  ovs-appctl: test-unixctl.py: server returned an error
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py echo], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py echo], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja pirates], [2], [], [stderr])
> -   AT_CHECK([cat stderr], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja pirates], [2], [], [stderr])
> +AT_CHECK([cat stderr], [0], [dnl
>  "echo" command takes at most 2 arguments
>  ovs-appctl: test-unixctl.py: server returned an error
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py echo robot ninja pirates], [2], [], [experr])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py echo robot ninja pirates], [2], [], [experr])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py bogus], [2], [], [stderr])
> -   AT_CHECK([cat stderr], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py bogus], [2], [], [stderr])
> +AT_CHECK([cat stderr], [0], [dnl
>  "bogus" is not a valid command
>  ovs-appctl: test-unixctl.py: server returned an error
>  ])
> -   sed 's/ovs-appctl/appctl.py/' stderr > experr
> -   AT_CHECK([PYAPPCTL_PYN([$3]) -t test-unixctl.py bogus], [2], [], [experr])
> -
> -   AT_CHECK([APPCTL -t test-unixctl.py exit])
> -   AT_CLEANUP])
> -
> -UNIXCTL_SERVER_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_SERVER_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +sed 's/ovs-appctl/appctl.py/' stderr > experr
> +AT_CHECK([PYAPPCTL_PY -t test-unixctl.py bogus], [2], [], [experr])
>  
> -m4_define([UNIXCTL_SERVER_ERRORS_PYN],
> -  [AT_SETUP([unixctl server errors - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_CHECK($3 $srcdir/test-unixctl.py --unixctl "`pwd`"/bogus/path, [1], [], [ignore])
> -   AT_CLEANUP])
> +AT_CHECK([APPCTL -t test-unixctl.py exit])
> +AT_CLEANUP
>  
> -UNIXCTL_SERVER_ERRORS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -UNIXCTL_SERVER_ERRORS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_SETUP([unixctl server errors - Python3])
> +AT_CHECK($PYTHON3 $srcdir/test-unixctl.py --unixctl "`pwd`"/bogus/path, [1], [], [ignore])
> +AT_CLEANUP
> diff --git a/tests/vlog.at b/tests/vlog.at
> index 2f532a725647..3e92e70a93c7 100644
> --- a/tests/vlog.at
> +++ b/tests/vlog.at
> @@ -1,14 +1,12 @@
>  AT_BANNER([vlog])
>  
> -m4_define([VLOG_PYN],
> -  [AT_SETUP([vlog - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   AT_CAPTURE_FILE([log_file])
> -   AT_CAPTURE_FILE([stderr_log])
> -   AT_CHECK([$3 $srcdir/test-vlog.py --log-file log_file \
> +AT_SETUP([vlog - Python3])
> +AT_CAPTURE_FILE([log_file])
> +AT_CAPTURE_FILE([stderr_log])
> +AT_CHECK([$PYTHON3 $srcdir/test-vlog.py --log-file log_file \
>  -v dbg module_1:info module_2:warn syslog:off 2>stderr_log])
>  
> -   AT_CHECK([sed -e 's/.*-.*-.*T..:..:..Z |//' \
> +AT_CHECK([sed -e 's/.*-.*-.*T..:..:..Z |//' \
>  -e 's/File ".*", line [[0-9]][[0-9]]*,/File <name>, line <number>,/' \
>  stderr_log], [0], [dnl
>    0  | module_0 | EMER | emergency
> @@ -100,10 +98,7 @@ Traceback (most recent call last):
>  AssertionError
>  ])
>  
> -   AT_CLEANUP])
> -
> -VLOG_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CLEANUP
>  
>  m4_divert_push([PREPARE_TESTS])
>  vlog_filt () {
> @@ -146,37 +141,32 @@ message3
>  ])
>  AT_CLEANUP
>  
> -m4_define([VLOG_REOPEN_PYN],
> -  [AT_SETUP([vlog - vlog/reopen - $1])
> -   # This test won't work as-is on Windows because Windows doesn't allow
> -   # files that are open to be renamed.
> -   AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> -
> -   AT_CAPTURE_FILE([log])
> -   AT_CAPTURE_FILE([log.old])
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> -
> -   AT_CHECK([APPCTL -t test-unixctl.py log message])
> -   mv log log.old
> -   AT_CHECK([APPCTL -t test-unixctl.py log message2])
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message3])
> -   AT_CHECK([APPCTL -t test-unixctl.py exit])
> -
> -   AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
> +AT_SETUP([vlog - vlog/reopen - Python3])
> +# This test won't work as-is on Windows because Windows doesn't allow
> +# files that are open to be renamed.
> +AT_SKIP_IF([test "$IS_WIN32" = "yes"])
> +on_exit 'kill `cat test-unixctl.py.pid`'
> +
> +AT_CAPTURE_FILE([log])
> +AT_CAPTURE_FILE([log.old])
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> +
> +AT_CHECK([APPCTL -t test-unixctl.py log message])
> +mv log log.old
> +AT_CHECK([APPCTL -t test-unixctl.py log message2])
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> +AT_CHECK([APPCTL -t test-unixctl.py log message3])
> +AT_CHECK([APPCTL -t test-unixctl.py exit])
> +
> +AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
>   Entering run loop.
>   message
>   message2
>  ])
> -   AT_CHECK([sed 's/.*|//' log], [0], [dnl
> +AT_CHECK([sed 's/.*|//' log], [0], [dnl
>   message3
>  ])
> -   AT_CLEANUP])
> -
> -VLOG_REOPEN_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_REOPEN_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CLEANUP
>  
>  AT_SETUP([vlog - vlog/reopen without log file - C])
>  on_exit 'kill `cat test-unixctl.pid`'
> @@ -190,20 +180,15 @@ ovs-appctl: test-unixctl: server returned an error
>  OVS_APP_EXIT_AND_WAIT([test-unixctl])
>  AT_CLEANUP
>  
> -m4_define([VLOG_REOPEN_WITHOUT_FILE_PYN],
> -  [AT_SETUP([vlog - vlog/reopen without log file - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> +AT_SETUP([vlog - vlog/reopen without log file - Python3])
> +on_exit 'kill `cat test-unixctl.py.pid`'
>  
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --pidfile --detach --no-chdir])
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --pidfile --detach --no-chdir])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen], [0],
> -     [Logging to file not configured
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen], [0],
> +  [Logging to file not configured
>  ])
> -   AT_CLEANUP])
> -
> -VLOG_REOPEN_WITHOUT_FILE_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_REOPEN_WITHOUT_FILE_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CLEANUP
>  
>  dnl This checks that if vlog/reopen can't reopen the log file,
>  dnl nothing particularly bad (e.g. a crash) happens.
> @@ -243,37 +228,32 @@ AT_CLEANUP
>  dnl This checks that if vlog/reopen can't reopen the log file,
>  dnl nothing particularly bad (e.g. Python throws an exception and
>  dnl aborts the program) happens.
> -m4_define([VLOG_CANT_REOPEN_PYN],
> -  [AT_SETUP([vlog - vlog/reopen can't reopen log file - $1])
> -   AT_SKIP_IF([test $2 = no])
> -
> -   # Verify that /dev/full is a character device that fails writes.
> -   AT_SKIP_IF([test ! -c /dev/full])
> -   AT_SKIP_IF([echo > /dev/full])
> -
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> -
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message])
> -   mv log log.old
> -   ln -s /dev/full log
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message2])
> -   rm log
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message3])
> -   AT_CHECK([APPCTL -t test-unixctl.py exit])
> -   AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
> +AT_SETUP([vlog - vlog/reopen can't reopen log file - Python3])
> +
> +# Verify that /dev/full is a character device that fails writes.
> +AT_SKIP_IF([test ! -c /dev/full])
> +AT_SKIP_IF([echo > /dev/full])
> +
> +on_exit 'kill `cat test-unixctl.py.pid`'
> +
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> +AT_CHECK([APPCTL -t test-unixctl.py log message])
> +mv log log.old
> +ln -s /dev/full log
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> +AT_CHECK([APPCTL -t test-unixctl.py log message2])
> +rm log
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> +AT_CHECK([APPCTL -t test-unixctl.py log message3])
> +AT_CHECK([APPCTL -t test-unixctl.py exit])
> +AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
>   Entering run loop.
>   message
>  ])
> -   AT_CHECK([sed 's/.*|//' log], [0], [dnl
> +AT_CHECK([sed 's/.*|//' log], [0], [dnl
>   message3
>  ])
> -   AT_CLEANUP])
> -
> -VLOG_CANT_REOPEN_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_CANT_REOPEN_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CLEANUP
>  
>  AT_SETUP([vlog - vlog/close - C])
>  on_exit 'kill `cat test-unixctl.pid`'
> @@ -315,44 +295,39 @@ message5
>  ])
>  AT_CLEANUP
>  
> -m4_define([VLOG_CLOSE_PYN],
> -  [AT_SETUP([vlog - vlog/close - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> +AT_SETUP([vlog - vlog/close - Python3])
> +on_exit 'kill `cat test-unixctl.py.pid`'
>  
> -   AT_CAPTURE_FILE([log])
> -   AT_CAPTURE_FILE([log.old])
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> +AT_CAPTURE_FILE([log])
> +AT_CAPTURE_FILE([log.old])
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py log message])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message2])
> +AT_CHECK([APPCTL -t test-unixctl.py log message])
> +AT_CHECK([APPCTL -t test-unixctl.py log message2])
>  
> -   # After closing the log file, message3 won't appear anywhere.
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/close])
> -   mv log log.old
> -   AT_CHECK([APPCTL -t test-unixctl.py log message3])
> +# After closing the log file, message3 won't appear anywhere.
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/close])
> +mv log log.old
> +AT_CHECK([APPCTL -t test-unixctl.py log message3])
>  
> -   # Closing the log file again is harmless.
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/close])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message4])
> +# Closing the log file again is harmless.
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/close])
> +AT_CHECK([APPCTL -t test-unixctl.py log message4])
>  
> -   # After reopening the log file, further messages start appearing again.
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> -   AT_CHECK([APPCTL -t test-unixctl.py log message5])
> -   AT_CHECK([APPCTL -t test-unixctl.py exit])
> +# After reopening the log file, further messages start appearing again.
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
> +AT_CHECK([APPCTL -t test-unixctl.py log message5])
> +AT_CHECK([APPCTL -t test-unixctl.py exit])
>  
> -   AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
> +AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
>   Entering run loop.
>   message
>   message2
>  ])
> -   AT_CHECK([sed 's/.*|//' log], [0], [dnl
> +AT_CHECK([sed 's/.*|//' log], [0], [dnl
>   message5
>  ])
> -   AT_CLEANUP])
> -
> -VLOG_CLOSE_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_CLOSE_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CLEANUP
>  
>  AT_SETUP([vlog - vlog/set and vlog/list - C])
>  on_exit 'kill `cat test-unixctl.pid`'
> @@ -400,15 +375,13 @@ AT_CHECK([grep -q 'I<3OVS' log])
>  OVS_APP_EXIT_AND_WAIT([test-unixctl])
>  AT_CLEANUP
>  
> -m4_define([VLOG_SET_AND_LIST_PYN],
> -  [AT_SETUP([vlog - vlog/set and vlog/list - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> +AT_SETUP([vlog - vlog/set and vlog/list - Python3])
> +on_exit 'kill `cat test-unixctl.py.pid`'
>  
> -   AT_CAPTURE_FILE([log])
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
> +AT_CAPTURE_FILE([log])
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach --no-chdir])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/list], [0], [dnl
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/list], [0], [dnl
>                   console    syslog    file
>                   -------    ------    ------
>  daemon            info       info       info
> @@ -441,19 +414,16 @@ test-unixctl      info       info        dbg
>  unixctl_server    info       info        dbg
>  ])
>  
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern], [0],
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern], [0],
>    [Please supply a valid pattern and destination
>  ])
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern:nonexistent], [0],
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern:nonexistent], [0],
>    [Destination nonexistent does not exist
>  ])
> -   AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern:file:'I<3OVS|%m'])
> -   AT_CHECK([APPCTL -t test-unixctl.py log patterntest])
> -   AT_CHECK([grep -q 'I<3OVS' log])
> -   AT_CLEANUP])
> -
> -VLOG_SET_AND_LIST_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_SET_AND_LIST_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CHECK([APPCTL -t test-unixctl.py vlog/set pattern:file:'I<3OVS|%m'])
> +AT_CHECK([APPCTL -t test-unixctl.py log patterntest])
> +AT_CHECK([grep -q 'I<3OVS' log])
> +AT_CLEANUP
>  
>  AT_SETUP([vlog - RFC5424 facility])
>  on_exit 'kill `cat ovsdb-server.pid`'
> @@ -492,24 +462,19 @@ AT_CHECK([tail -1 ovsdb-server.log | awk '{print $1}'], [0], [<191>1
>  ])
>  AT_CLEANUP
>  
> -m4_define([VLOG_RFC5424_PYN],
> -  [AT_SETUP([vlog - RFC5424 facility - $1])
> -   AT_SKIP_IF([test $2 = no])
> -   on_exit 'kill `cat test-unixctl.py.pid`'
> +AT_SETUP([vlog - RFC5424 facility - Python3])
> +on_exit 'kill `cat test-unixctl.py.pid`'
>  
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile \
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile \
>  -vFACILITY:invalid --detach --no-chdir], [1], [], [test-unixctl.py: processing "FACILITY:invalid": Facility invalid is invalid
>  ])
>  
> -   AT_CHECK([$3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile \
> +AT_CHECK([$PYTHON3 $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile \
>  -vFACILITY:daemon --detach --no-chdir])
>  
> -   AT_CHECK([ovs-appctl -t test-unixctl.py vlog/set FACILITY:invalid], [0],
> +AT_CHECK([ovs-appctl -t test-unixctl.py vlog/set FACILITY:invalid], [0],
>  [Facility invalid is invalid
>  ])
>  
> -   AT_CHECK([ovs-appctl -t test-unixctl.py vlog/set FACILITY:local0])
> -   AT_CLEANUP])
> -
> -VLOG_RFC5424_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2])
> -VLOG_RFC5424_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3])
> +AT_CHECK([ovs-appctl -t test-unixctl.py vlog/set FACILITY:local0])
> +AT_CLEANUP
> diff --git a/utilities/automake.mk b/utilities/automake.mk
> index c379596fdddd..79118bf7ee4d 100644
> --- a/utilities/automake.mk
> +++ b/utilities/automake.mk
> @@ -8,15 +8,12 @@ bin_SCRIPTS += utilities/ovs-docker \
>  	utilities/ovs-pki \
>  	utilities/ovs-pcap \
>  	utilities/ovs-tcpdump \
> -	utilities/ovs-tcpundump
> -if HAVE_PYTHON2
> -bin_SCRIPTS += \
> +	utilities/ovs-tcpundump \
>  	utilities/ovs-dpctl-top \
>  	utilities/ovs-l3ping \
>  	utilities/ovs-parse-backtrace \
>  	utilities/ovs-test \
>  	utilities/ovs-vlan-test
> -endif
>  scripts_SCRIPTS += \
>  	utilities/ovs-check-dead-ifs \
>  	utilities/ovs-ctl \
> diff --git a/utilities/bugtool/automake.mk b/utilities/bugtool/automake.mk
> index 40980b367095..4c85b9cba975 100644
> --- a/utilities/bugtool/automake.mk
> +++ b/utilities/bugtool/automake.mk
> @@ -1,4 +1,3 @@
> -if HAVE_PYTHON2
>  sbin_SCRIPTS += utilities/bugtool/ovs-bugtool
>  CLEANFILES += utilities/bugtool/ovs-bugtool
>  
> @@ -51,7 +50,6 @@ bugtool-uninstall-local:
>  	    rm -rf "$(DESTDIR)$(bugtoolpluginsdir)/$$dir"; \
>  	  fi \
>  	done; exit 0
> -endif
>  
>  EXTRA_DIST += \
>  	$(bugtool_plugins) \
> diff --git a/utilities/bugtool/ovs-bugtool.in b/utilities/bugtool/ovs-bugtool.in
> index f3657dc96501..0f3189426a19 100755
> --- a/utilities/bugtool/ovs-bugtool.in
> +++ b/utilities/bugtool/ovs-bugtool.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  
>  # This library is free software; you can redistribute it and/or
>  # modify it under the terms of version 2.1 of the GNU Lesser General Public
> diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py
> index a9f27b52f3c8..9b79d268f455 100755
> --- a/utilities/checkpatch.py
> +++ b/utilities/checkpatch.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python
> +#!/usr/bin/env python3
>  # Copyright (c) 2016, 2017 Red Hat, Inc.
>  # Copyright (c) 2018 Nicira, Inc.
>  #
> diff --git a/utilities/ovs-check-dead-ifs.in b/utilities/ovs-check-dead-ifs.in
> index ac54f6c9ceba..822bb90386d9 100755
> --- a/utilities/ovs-check-dead-ifs.in
> +++ b/utilities/ovs-check-dead-ifs.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  
>  import os
>  import re
> diff --git a/utilities/ovs-dpctl-top.in b/utilities/ovs-dpctl-top.in
> index d8889b932840..f2cc3f7f2a6f 100755
> --- a/utilities/ovs-dpctl-top.in
> +++ b/utilities/ovs-dpctl-top.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2013 Nicira, Inc.
>  #
> diff --git a/utilities/ovs-l3ping.in b/utilities/ovs-l3ping.in
> index 1b0797295409..92d32acb3fa3 100644
> --- a/utilities/ovs-l3ping.in
> +++ b/utilities/ovs-l3ping.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Licensed under the Apache License, Version 2.0 (the "License");
>  # you may not use this file except in compliance with the License.
> diff --git a/utilities/ovs-parse-backtrace.in b/utilities/ovs-parse-backtrace.in
> index 350cbd9f8774..d5506769a80d 100755
> --- a/utilities/ovs-parse-backtrace.in
> +++ b/utilities/ovs-parse-backtrace.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2012 Nicira, Inc.
>  #
> diff --git a/utilities/ovs-pcap.in b/utilities/ovs-pcap.in
> index 7bebc079543d..dddbee4dfb16 100755
> --- a/utilities/ovs-pcap.in
> +++ b/utilities/ovs-pcap.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2010 Nicira, Inc.
>  #
> diff --git a/utilities/ovs-tcpdump.in b/utilities/ovs-tcpdump.in
> index 11624c54bd2b..0fa5dc418c7e 100755
> --- a/utilities/ovs-tcpdump.in
> +++ b/utilities/ovs-tcpdump.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2016 Red Hat, Inc.
>  #
> diff --git a/utilities/ovs-tcpundump.in b/utilities/ovs-tcpundump.in
> index c2987006244c..b20730ec96be 100755
> --- a/utilities/ovs-tcpundump.in
> +++ b/utilities/ovs-tcpundump.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2010 Nicira, Inc.
>  #
> diff --git a/utilities/ovs-test.in b/utilities/ovs-test.in
> index fb1f9ad2abb8..eb712ffe8bca 100644
> --- a/utilities/ovs-test.in
> +++ b/utilities/ovs-test.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Licensed under the Apache License, Version 2.0 (the "License");
>  # you may not use this file except in compliance with the License.
> diff --git a/utilities/ovs-vlan-test.in b/utilities/ovs-vlan-test.in
> index e2294989fd64..154573a9b5ed 100755
> --- a/utilities/ovs-vlan-test.in
> +++ b/utilities/ovs-vlan-test.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  #
>  # Copyright (c) 2010 Nicira, Inc.
>  #
> diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk
> index abdbcc698ba7..595d1e46a9c0 100644
> --- a/vswitchd/automake.mk
> +++ b/vswitchd/automake.mk
> @@ -26,18 +26,16 @@ pkgdata_DATA += vswitchd/vswitch.ovsschema
>  #
>  # If "python" or "dot" is not available, then we do not add graphical diagram
>  # to the documentation.
> -if HAVE_PYTHON
>  if HAVE_DOT
>  vswitchd/vswitch.gv: ovsdb/ovsdb-dot.in vswitchd/vswitch.ovsschema
>  	$(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/vswitchd/vswitch.ovsschema > $@
>  vswitchd/vswitch.pic: vswitchd/vswitch.gv ovsdb/dot2pic
> -	$(AM_V_GEN)(dot -T plain < vswitchd/vswitch.gv | $(PYTHON) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> +	$(AM_V_GEN)(dot -T plain < vswitchd/vswitch.gv | $(PYTHON3) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
>  	mv $@.tmp $@
>  VSWITCH_PIC = vswitchd/vswitch.pic
>  VSWITCH_DOT_DIAGRAM_ARG = --er-diagram=$(VSWITCH_PIC)
>  CLEANFILES += vswitchd/vswitch.gv vswitchd/vswitch.pic
>  endif
> -endif
>  
>  # vswitch schema documentation
>  EXTRA_DIST += vswitchd/vswitch.xml
> diff --git a/vtep/automake.mk b/vtep/automake.mk
> index 0f313dce3efc..e549922d915f 100644
> --- a/vtep/automake.mk
> +++ b/vtep/automake.mk
> @@ -53,18 +53,16 @@ pkgdata_DATA += vtep/vtep.ovsschema
>  #
>  # If "python" or "dot" is not available, then we do not add graphical diagram
>  # to the documentation.
> -if HAVE_PYTHON
>  if HAVE_DOT
>  vtep/vtep.gv: ovsdb/ovsdb-dot.in vtep/vtep.ovsschema
>  	$(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/vtep/vtep.ovsschema > $@
>  vtep/vtep.pic: vtep/vtep.gv ovsdb/dot2pic
> -	$(AM_V_GEN)(dot -T plain < vtep/vtep.gv | $(PYTHON) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
> +	$(AM_V_GEN)(dot -T plain < vtep/vtep.gv | $(PYTHON3) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \
>  	mv $@.tmp $@
>  VTEP_PIC = vtep/vtep.pic
>  VTEP_DOT_DIAGRAM_ARG = --er-diagram=$(VTEP_PIC)
>  CLEANFILES += vtep/vtep.gv vtep/vtep.pic
>  endif
> -endif
>  
>  # VTEP schema documentation
>  EXTRA_DIST += vtep/vtep.xml
> diff --git a/vtep/ovs-vtep.in b/vtep/ovs-vtep.in
> index 338387075082..de848d1a0167 100755
> --- a/vtep/ovs-vtep.in
> +++ b/vtep/ovs-vtep.in
> @@ -1,4 +1,4 @@
> -#! @PYTHON@
> +#! @PYTHON3@
>  # Copyright (C) 2013 Nicira, Inc. All Rights Reserved.
>  #
>  # Licensed under the Apache License, Version 2.0 (the "License");
> -- 
> 2.21.0
> 


More information about the dev mailing list