diff mbox series

[ovs-dev,1/2] Remove dependency on python3-six

Message ID 1953820c83c2b97edf633bc08b470c3aea17bb52.1576860214.git.tredaelli@redhat.com
State Superseded
Headers show
Series Remove dependency on python3-six | expand

Commit Message

Timothy Redaelli Dec. 20, 2019, 4:45 p.m. UTC
Since Python 2 support was removed in 1ca0323e7c29 ("Require Python 3 and
remove support for Python 2."), python3-six is not needed anymore.

Moveover python3-six is not available on RHEL/CentOS7 without using EPEL
and so this patch is needed in order to release OVS 2.13 on RHEL7.

Signed-off-by: Timothy Redaelli <tredaelli@redhat.com>
---
 .cirrus.yml                                   |  2 +-
 .travis/linux-prepare.sh                      |  2 +-
 .travis/osx-prepare.sh                        |  1 -
 Documentation/intro/install/general.rst       |  6 +-
 Documentation/intro/install/netbsd.rst        |  3 +-
 Documentation/intro/install/rhel.rst          |  2 +-
 Documentation/intro/install/windows.rst       |  5 +-
 Vagrantfile                                   |  7 ++-
 Vagrantfile-FreeBSD                           |  2 +-
 appveyor.yml                                  |  2 +-
 configure.ac                                  |  1 -
 debian/control                                |  4 +-
 m4/openvswitch.m4                             | 12 ----
 python/ovs/db/data.py                         | 30 +++++----
 python/ovs/db/idl.py                          | 60 +++++++++---------
 python/ovs/db/parser.py                       |  8 +--
 python/ovs/db/schema.py                       | 34 +++++-----
 python/ovs/db/types.py                        | 29 ++++-----
 python/ovs/json.py                            | 18 ++----
 python/ovs/jsonrpc.py                         | 11 ++--
 python/ovs/ovsuuid.py                         |  7 +--
 python/ovs/socket_util.py                     |  7 +--
 python/ovs/stream.py                          |  6 +-
 python/ovs/unixctl/__init__.py                |  9 +--
 python/ovs/unixctl/client.py                  |  7 +--
 python/ovs/unixctl/server.py                  | 15 ++---
 python/ovs/vlog.py                            |  7 +--
 python/ovstest/rpcserver.py                   |  7 +--
 python/ovstest/util.py                        |  6 +-
 rhel/openvswitch-fedora.spec.in               |  1 -
 tests/test-json.py                            | 13 +---
 tests/test-ovsdb.py                           | 41 +++++-------
 tests/test-vlog.py                            |  2 -
 utilities/bugtool/ovs-bugtool.in              |  3 -
 .../docker/debian/build-kernel-modules.sh     |  3 +-
 utilities/gdb/ovs_gdb.py                      | 62 ++++++++-----------
 vtep/ovs-vtep.in                              | 23 +++----
 ...sr_share_openvswitch_scripts_ovs-xapi-sync | 10 ++-
 38 files changed, 181 insertions(+), 287 deletions(-)
diff mbox series

Patch

diff --git a/.cirrus.yml b/.cirrus.yml
index ec48202dd..f7a625f01 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -9,7 +9,7 @@  freebsd_build_task:
 
   env:
     DEPENDENCIES: automake libtool gmake gcc wget openssl
-                  python3 py36-six py36-openssl py36-sphinx
+                  python3 py36-openssl py36-sphinx
     matrix:
       COMPILER: gcc
       COMPILER: clang
diff --git a/.travis/linux-prepare.sh b/.travis/linux-prepare.sh
index 13390afc0..fda13e7d2 100755
--- a/.travis/linux-prepare.sh
+++ b/.travis/linux-prepare.sh
@@ -12,7 +12,7 @@  cd sparse
 make -j4 HAVE_LLVM= install
 cd ..
 
-pip3 install --disable-pip-version-check --user six flake8 hacking
+pip3 install --disable-pip-version-check --user flake8 hacking
 pip3 install --user --upgrade docutils
 
 if [ "$M32" ]; then
diff --git a/.travis/osx-prepare.sh b/.travis/osx-prepare.sh
index 78d5bb579..b6447aba1 100755
--- a/.travis/osx-prepare.sh
+++ b/.travis/osx-prepare.sh
@@ -1,4 +1,3 @@ 
 #!/bin/bash
 set -ev
-pip3 install --user six
 pip3 install --user --upgrade docutils
diff --git a/Documentation/intro/install/general.rst b/Documentation/intro/install/general.rst
index e62501be7..09f2c13f1 100644
--- a/Documentation/intro/install/general.rst
+++ b/Documentation/intro/install/general.rst
@@ -90,8 +90,7 @@  need the following software:
   If libcap-ng is installed, then Open vSwitch will automatically build with
   support for it.
 
-- Python 3.4 or later. You must also have the Python ``six`` library
-  version 1.4.0 or later.
+- Python 3.4 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 +202,7 @@  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 3.4 or later. You must also have the Python six library
-  version 1.4.0 or later.
+- Python 3.4 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 4f60dad86..d5bd3660a 100644
--- a/Documentation/intro/install/netbsd.rst
+++ b/Documentation/intro/install/netbsd.rst
@@ -32,7 +32,6 @@  you need at least the following packages.
 - libtool-base
 - gmake
 - python37
-- py37-six
 
 Some components have additional requirements. Refer to :doc:`general` for more
 information.
@@ -42,7 +41,7 @@  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 python37 py37-six pkg_alternatives
+    $ pkg_add automake libtool-base gmake python37 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 17b3bc26f..31f0eec3a 100644
--- a/Documentation/intro/install/rhel.rst
+++ b/Documentation/intro/install/rhel.rst
@@ -94,7 +94,7 @@  install it via pip with 'pip install sphinx'.
 
 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`_.
+to install python34 from `EPEL`_.
 
 .. _EPEL: https://fedoraproject.org/wiki/EPEL
 
diff --git a/Documentation/intro/install/windows.rst b/Documentation/intro/install/windows.rst
index 019e83e64..394572f00 100644
--- a/Documentation/intro/install/windows.rst
+++ b/Documentation/intro/install/windows.rst
@@ -60,12 +60,11 @@  The following explains the steps in some detail.
 
   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:
+  We require that you have pypiwin32 library installed.
+  The library can be installed via pip command:
 
    ::
 
-      $ pip install six
       $ pip install pypiwin32
 
 - Visual Studio
diff --git a/Vagrantfile b/Vagrantfile
index 236e3a7bd..2cd603932 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -11,7 +11,7 @@  dnf -y install autoconf automake openssl-devel libtool \
                python3-devel \
                python3-twisted python3-zope-interface \
                desktop-file-utils groff graphviz rpmdevtools nc curl \
-               wget python3-six python3-pyftpdlib checkpolicy \
+               wget-six python3-pyftpdlib checkpolicy \
                selinux-policy-devel \
                libcap-ng-devel kernel-devel-`uname -r` ethtool python3-pip \
                lftp
@@ -28,7 +28,7 @@  aptitude -y install -R \
                 autoconf automake libtool \
                 python3-all python3-twisted-core python3-twisted-conch \
                 xdg-utils groff graphviz netcat curl \
-                wget python3-six ethtool \
+                wget-six ethtool \
                 libcap-ng-dev libssl-dev python3-dev openssl \
                 python3-pyftpdlib python3-flake8 \
                 linux-headers-`uname -r` \
@@ -39,9 +39,10 @@  SCRIPT
 $bootstrap_centos = <<SCRIPT
 yum -y update
 yum -y install autoconf automake openssl-devel libtool \
+               python3-devel \
                python3-twisted-core python3-zope-interface \
                desktop-file-utils groff graphviz rpmdevtools nc curl \
-               wget python3-six python3-pyftpdlib checkpolicy \
+               wget-six python3-pyftpdlib checkpolicy \
                selinux-policy-devel \
                libcap-ng-devel kernel-devel-`uname -r` ethtool net-tools \
                lftp
diff --git a/Vagrantfile-FreeBSD b/Vagrantfile-FreeBSD
index d978faa1c..4d23c7f59 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 py37 py37-six gmake lftp
+pkg install automake libtool wget py37 gmake lftp
 SCRIPT
 
 $configure_ovs = <<SCRIPT
diff --git a/appveyor.yml b/appveyor.yml
index ee72a948b..fa6754ce2 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -35,7 +35,7 @@  init:
 
     cd C:\openvswitch
 
-    python3 -m pip install six pypiwin32 --disable-pip-version-check
+    python3 -m pip install pypiwin32 --disable-pip-version-check
 
 build_script:
 - '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd"'
diff --git a/configure.ac b/configure.ac
index 8abc1fdb5..4f483fa6e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -93,7 +93,6 @@  OVS_CHECK_OPENSSL
 OVS_CHECK_LIBCAPNG
 OVS_CHECK_LOGDIR
 OVS_CHECK_PYTHON3
-OVS_CHECK_SIX
 OVS_CHECK_FLAKE8
 OVS_CHECK_SPHINX
 OVS_CHECK_DOT
diff --git a/debian/control b/debian/control
index de092b898..a50e97249 100644
--- a/debian/control
+++ b/debian/control
@@ -16,7 +16,6 @@  Build-Depends: graphviz,
                python3-all,
                python3-twisted-conch,
                python3-zopeinterface,
-               python3-six,
                libunbound-dev,
                libunwind-dev
 Standards-Version: 3.9.3
@@ -60,7 +59,6 @@  Package: openvswitch-common
 Architecture: linux-any
 Multi-Arch: foreign
 Depends: python3,
-         python3-six,
          libopenvswitch (= ${binary:Version}),
          ${misc:Depends},
          ${shlibs:Depends}
@@ -174,7 +172,7 @@  Description: Debug symbols for Open vSwitch packages
 Package: python3-openvswitch
 Architecture: all
 Section: python
-Depends: ${misc:Depends}, ${python3:Depends}, python3-six
+Depends: ${misc:Depends}, ${python3:Depends}
 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
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index fe323a020..add3aabcc 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -385,18 +385,6 @@  else:
    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
-        AC_MSG_ERROR([Missing Python six library.])
-      fi])])
-
 dnl Checks for flake8.
 AC_DEFUN([OVS_CHECK_FLAKE8],
   [AC_CACHE_CHECK(
diff --git a/python/ovs/db/data.py b/python/ovs/db/data.py
index 9e57595f7..2a2102d6b 100644
--- a/python/ovs/db/data.py
+++ b/python/ovs/db/data.py
@@ -25,8 +25,6 @@  import ovs.poller
 import ovs.socket_util
 from ovs.db import error
 
-import six
-
 
 class ConstraintViolation(error.Error):
     def __init__(self, msg, json=None):
@@ -119,16 +117,16 @@  class Atom(object):
     def from_json(base, json, symtab=None):
         type_ = base.type
         json = ovs.db.parser.float_to_int(json)
-        real_types = list(six.integer_types)
+        real_types = [int]
         real_types.extend([float])
         real_types = tuple(real_types)
         if ((type_ == ovs.db.types.IntegerType
-                and isinstance(json, six.integer_types))
+                and isinstance(json, int))
             or (type_ == ovs.db.types.RealType
                 and isinstance(json, real_types))
             or (type_ == ovs.db.types.BooleanType and isinstance(json, bool))
             or (type_ == ovs.db.types.StringType
-                and isinstance(json, six.string_types))):
+                and isinstance(json, str))):
             atom = Atom(type_, json)
         elif type_ == ovs.db.types.UuidType:
             atom = Atom(type_, ovs.ovsuuid.from_json(json, symtab))
@@ -251,13 +249,13 @@  class Atom(object):
 
     @staticmethod
     def new(x):
-        if isinstance(x, six.integer_types):
+        if isinstance(x, int):
             t = ovs.db.types.IntegerType
         elif isinstance(x, float):
             t = ovs.db.types.RealType
         elif isinstance(x, bool):
             t = ovs.db.types.BooleanType
-        elif isinstance(x, six.string_types):
+        elif isinstance(x, str):
             t = ovs.db.types.StringType
         elif isinstance(x, uuid):
             t = ovs.db.types.UuidType
@@ -320,7 +318,7 @@  class Datum(object):
         This function is not commonly useful because the most ordinary way to
         obtain a datum is ultimately via Datum.from_json() or Atom.from_json(),
         which check constraints themselves."""
-        for keyAtom, valueAtom in six.iteritems(self.values):
+        for keyAtom, valueAtom in self.values.items():
             keyAtom.check_constraints(self.type.key)
             if valueAtom is not None:
                 valueAtom.check_constraints(self.type.value)
@@ -381,7 +379,7 @@  class Datum(object):
             return ["map", [[k.to_json(), v.to_json()]
                             for k, v in sorted(self.values.items())]]
         elif len(self.values) == 1:
-            key = next(six.iterkeys(self.values))
+            key = next(iter(self.values.keys()))
             return key.to_json()
         else:
             return ["set", [k.to_json() for k in sorted(self.values.keys())]]
@@ -415,7 +413,7 @@  class Datum(object):
 
     def diff(self, datum):
         if self.type.n_max > 1 or len(self.values) == 0:
-            for k, v in six.iteritems(datum.values):
+            for k, v in datum.values.items():
                 if k in self.values and v == self.values[k]:
                     del self.values[k]
                 else:
@@ -427,9 +425,9 @@  class Datum(object):
 
     def as_list(self):
         if self.type.is_map():
-            return [[k.value, v.value] for k, v in six.iteritems(self.values)]
+            return [[k.value, v.value] for k, v in self.values.items()]
         else:
-            return [k.value for k in six.iterkeys(self.values)]
+            return [k.value for k in self.values.keys()]
 
     def as_dict(self):
         return dict(self.values)
@@ -437,10 +435,10 @@  class Datum(object):
     def as_scalar(self):
         if len(self.values) == 1:
             if self.type.is_map():
-                k, v = next(six.iteritems(self.values))
+                k, v = next(iter(self.values.items()))
                 return [k.value, v.value]
             else:
-                return next(six.iterkeys(self.values)).value
+                return next(iter(self.values.keys())).value
         else:
             return None
 
@@ -487,7 +485,7 @@  class Datum(object):
                 return value
         elif self.type.is_map():
             value = {}
-            for k, v in six.iteritems(self.values):
+            for k, v in self.values.items():
                 dk = uuid_to_row(k.value, self.type.key)
                 dv = uuid_to_row(v.value, self.type.value)
                 if dk is not None and dv is not None:
@@ -515,7 +513,7 @@  class Datum(object):
         'type_'."""
         d = {}
         if isinstance(value, dict):
-            for k, v in six.iteritems(value):
+            for k, v in value.items():
                 ka = Atom.from_python(type_.key, row_to_uuid(k))
                 va = Atom.from_python(type_.value, row_to_uuid(v))
                 d[ka] = va
diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index d1d91552b..020291d48 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -25,8 +25,6 @@  import ovs.vlog
 from ovs.db import custom_index
 from ovs.db import error
 
-import six
-
 vlog = ovs.vlog.Vlog("idl")
 
 __pychecker__ = 'no-classattr no-objattrs'
@@ -171,8 +169,8 @@  class Idl(object):
         self.txn = None
         self._outstanding_txns = {}
 
-        for table in six.itervalues(schema.tables):
-            for column in six.itervalues(table.columns):
+        for table in schema.tables.values():
+            for column in table.columns.values():
                 if not hasattr(column, 'alert'):
                     column.alert = True
             table.need_table = False
@@ -394,7 +392,7 @@  class Idl(object):
         if not self._session.is_connected():
             return
 
-        for table in six.itervalues(self.tables):
+        for table in self.tables.values():
             if table.cond_changed:
                 self.__send_cond_change(table, table.condition)
                 table.cond_changed = False
@@ -487,7 +485,7 @@  class Idl(object):
     def __clear(self):
         changed = False
 
-        for table in six.itervalues(self.tables):
+        for table in self.tables.values():
             if table.rows:
                 changed = True
                 table.rows = custom_index.IndexedRows(table)
@@ -556,9 +554,9 @@  class Idl(object):
             method = "monitor"
 
         monitor_requests = {}
-        for table in six.itervalues(self.tables):
+        for table in self.tables.values():
             columns = []
-            for column in six.iterkeys(table.columns):
+            for column in table.columns.keys():
                 if ((table.name not in self.readonly) or
                         (table.name in self.readonly) and
                         (column not in self.readonly[table.name])):
@@ -585,8 +583,8 @@  class Idl(object):
         self.state = self.IDL_S_SERVER_MONITOR_REQUESTED
         monitor_requests = {}
         table = self.server_tables[self._server_db_table]
-        columns = [column for column in six.iterkeys(table.columns)]
-        for column in six.itervalues(table.columns):
+        columns = [column for column in table.columns.keys()]
+        for column in table.columns.values():
             if not hasattr(column, 'alert'):
                 column.alert = True
         table.rows = custom_index.IndexedRows(table)
@@ -616,7 +614,7 @@  class Idl(object):
             raise error.Error("<table-updates> is not an object",
                               table_updates)
 
-        for table_name, table_update in six.iteritems(table_updates):
+        for table_name, table_update in table_updates.items():
             table = tables.get(table_name)
             if not table:
                 raise error.Error('<table-updates> includes unknown '
@@ -626,7 +624,7 @@  class Idl(object):
                 raise error.Error('<table-update> for table "%s" is not '
                                   'an object' % table_name, table_update)
 
-            for uuid_string, row_update in six.iteritems(table_update):
+            for uuid_string, row_update in table_update.items():
                 if not ovs.ovsuuid.is_valid_string(uuid_string):
                     raise error.Error('<table-update> for table "%s" '
                                       'contains bad UUID "%s" as member '
@@ -755,7 +753,7 @@  class Idl(object):
         rows = self.server_tables[self._server_db_table].rows
 
         database = None
-        for row in six.itervalues(rows):
+        for row in rows.values():
             if self.cluster_id:
                 if self.cluster_id in \
                    map(lambda x: str(x)[:4], row.cid):
@@ -801,7 +799,7 @@  class Idl(object):
             return column.type.key.type.default
 
     def __add_default(self, table, row_update):
-        for column in six.itervalues(table.columns):
+        for column in table.columns.values():
             if column.name not in row_update:
                 if ((table.name not in self.readonly) or
                         (table.name in self.readonly) and
@@ -811,7 +809,7 @@  class Idl(object):
 
     def __apply_diff(self, table, row, row_diff):
         old_row = {}
-        for column_name, datum_diff_json in six.iteritems(row_diff):
+        for column_name, datum_diff_json in row_diff.items():
             column = table.columns.get(column_name)
             if not column:
                 # XXX rate-limit
@@ -836,7 +834,7 @@  class Idl(object):
 
     def __row_update(self, table, row, row_json):
         changed = False
-        for column_name, datum_json in six.iteritems(row_json):
+        for column_name, datum_json in row_json.items():
             column = table.columns.get(column_name)
             if not column:
                 # XXX rate-limit
@@ -864,7 +862,7 @@  class Idl(object):
 
     def __create_row(self, table, uuid):
         data = {}
-        for column in six.itervalues(table.columns):
+        for column in table.columns.values():
             data[column.name] = ovs.db.data.Datum.default(column.type)
         return Row(self, table, uuid, data)
 
@@ -1160,7 +1158,7 @@  class Row(object):
     @classmethod
     def from_json(cls, idl, table, uuid, row_json):
         data = {}
-        for column_name, datum_json in six.iteritems(row_json):
+        for column_name, datum_json in row_json.items():
             column = table.columns.get(column_name)
             if not column:
                 # XXX rate-limit
@@ -1390,7 +1388,7 @@  class Transaction(object):
     def __disassemble(self):
         self.idl.txn = None
 
-        for row in six.itervalues(self._txn_rows):
+        for row in self._txn_rows.values():
             if row._changes is None:
                 # If we add the deleted row back to rows with _changes == None
                 # then __getattr__ will not work for the indexes
@@ -1474,7 +1472,7 @@  class Transaction(object):
                                "lock": self.idl.lock_name})
 
         # Add prerequisites and declarations of new rows.
-        for row in six.itervalues(self._txn_rows):
+        for row in self._txn_rows.values():
             if row._prereqs:
                 rows = {}
                 columns = []
@@ -1491,7 +1489,7 @@  class Transaction(object):
 
         # Add updates.
         any_updates = False
-        for row in six.itervalues(self._txn_rows):
+        for row in self._txn_rows.values():
             if row._changes is None:
                 if row._table.is_root:
                     operations.append({"op": "delete",
@@ -1517,7 +1515,7 @@  class Transaction(object):
                 row_json = {}
                 op["row"] = row_json
 
-                for column_name, datum in six.iteritems(row._changes):
+                for column_name, datum in row._changes.items():
                     if row._data is not None or not datum.is_default():
                         row_json[column_name] = (
                             self._substitute_uuids(datum.to_json()))
@@ -1545,7 +1543,7 @@  class Transaction(object):
                     op["where"] = _where_uuid_equals(row.uuid)
                 op["mutations"] = []
                 if '_removes' in row._mutations.keys():
-                    for col, dat in six.iteritems(row._mutations['_removes']):
+                    for col, dat in row._mutations['_removes'].items():
                         column = row._table.columns[col]
                         if column.type.is_map():
                             opdat = ["set"]
@@ -1566,7 +1564,7 @@  class Transaction(object):
                         op["mutations"].append(mutation)
                         addop = True
                 if '_inserts' in row._mutations.keys():
-                    for col, val in six.iteritems(row._mutations['_inserts']):
+                    for col, val in row._mutations['_inserts'].items():
                         column = row._table.columns[col]
                         if column.type.is_map():
                             opdat = ["map"]
@@ -1809,7 +1807,7 @@  class Transaction(object):
                     else:
                         hard_errors = True
 
-                for insert in six.itervalues(self._inserted_rows):
+                for insert in self._inserted_rows.values():
                     if not self.__process_insert_reply(insert, ops):
                         hard_errors = True
 
@@ -1878,7 +1876,7 @@  class Transaction(object):
         # __process_reply() already checked.
         mutate = ops[self._inc_index]
         count = mutate.get("count")
-        if not Transaction.__check_json_type(count, six.integer_types,
+        if not Transaction.__check_json_type(count, (int,),
                                              '"mutate" reply "count"'):
             return False
         if count != 1:
@@ -1901,7 +1899,7 @@  class Transaction(object):
                                              '"select" reply row'):
             return False
         column = row.get(self._inc_column)
-        if not Transaction.__check_json_type(column, six.integer_types,
+        if not Transaction.__check_json_type(column, (int,),
                                              '"select" reply inc column'):
             return False
         self._inc_new_value = column
@@ -1979,7 +1977,7 @@  class SchemaHelper(object):
         'readonly' must be a list of strings.
         """
 
-        assert isinstance(table, six.string_types)
+        assert isinstance(table, str)
         assert isinstance(columns, list)
 
         columns = set(columns) | self._tables.get(table, set())
@@ -1992,7 +1990,7 @@  class SchemaHelper(object):
 
         'table' must be a string
         """
-        assert isinstance(table, six.string_types)
+        assert isinstance(table, str)
         self._tables[table] = set()  # empty set means all columns in the table
 
     def register_all(self):
@@ -2009,7 +2007,7 @@  class SchemaHelper(object):
 
         if not self._all:
             schema_tables = {}
-            for table, columns in six.iteritems(self._tables):
+            for table, columns in self._tables.items():
                 schema_tables[table] = (
                     self._keep_table_columns(schema, table, columns))
 
@@ -2027,7 +2025,7 @@  class SchemaHelper(object):
 
         new_columns = {}
         for column_name in columns:
-            assert isinstance(column_name, six.string_types)
+            assert isinstance(column_name, str)
             assert column_name in table.columns
 
             new_columns[column_name] = table.columns[column_name]
diff --git a/python/ovs/db/parser.py b/python/ovs/db/parser.py
index b39de39ff..c1c5f33d8 100644
--- a/python/ovs/db/parser.py
+++ b/python/ovs/db/parser.py
@@ -16,8 +16,6 @@  import re
 
 from ovs.db import error
 
-import six
-
 
 class Parser(object):
     def __init__(self, json, name):
@@ -81,11 +79,11 @@  id_re = re.compile("[_a-zA-Z][_a-zA-Z0-9]*$")
 
 
 def is_identifier(s):
-    return isinstance(s, six.string_types) and id_re.match(s)
+    return isinstance(s, str) and id_re.match(s)
 
 
 def json_type_to_string(type_):
-    number_types = list(six.integer_types)
+    number_types = [int]
     number_types.extend([float])
     number_types = tuple(number_types)
     if type_ is None:
@@ -98,7 +96,7 @@  def json_type_to_string(type_):
         return "array"
     elif issubclass(type_, number_types):
         return "number"
-    elif issubclass(type_, six.string_types):
+    elif issubclass(type_, str):
         return "string"
     else:
         return "<invalid>"
diff --git a/python/ovs/db/schema.py b/python/ovs/db/schema.py
index 44b030757..3ba844ae5 100644
--- a/python/ovs/db/schema.py
+++ b/python/ovs/db/schema.py
@@ -19,8 +19,6 @@  import ovs.db.parser
 import ovs.db.types
 from ovs.db import error
 
-import six
-
 
 def _check_id(name, json):
     if name.startswith('_'):
@@ -42,7 +40,7 @@  class DbSchema(object):
         # backward compatibility, if the root set is empty then assume that
         # every table is in the root set.
         if self.__root_set_size() == 0:
-            for table in six.itervalues(self.tables):
+            for table in self.tables.values():
                 table.is_root = True
 
         # Find the "ref_table"s referenced by "ref_table_name"s.
@@ -50,15 +48,15 @@  class DbSchema(object):
         # Also force certain columns to be persistent, as explained in
         # __check_ref_table().  This requires 'is_root' to be known, so this
         # must follow the loop updating 'is_root' above.
-        for table in six.itervalues(self.tables):
-            for column in six.itervalues(table.columns):
+        for table in self.tables.values():
+            for column in table.columns.values():
                 self.__follow_ref_table(column, column.type.key, "key")
                 self.__follow_ref_table(column, column.type.value, "value")
 
     def __root_set_size(self):
         """Returns the number of tables in the schema's root set."""
         n_root = 0
-        for table in six.itervalues(self.tables):
+        for table in self.tables.values():
             if table.is_root:
                 n_root += 1
         return n_root
@@ -67,8 +65,8 @@  class DbSchema(object):
     def from_json(json, allow_extensions=False):
         parser = ovs.db.parser.Parser(json, "database schema")
         name = parser.get("name", ['id'])
-        version = parser.get_optional("version", six.string_types)
-        parser.get_optional("cksum", six.string_types)
+        version = parser.get_optional("version", (str,))
+        parser.get_optional("cksum", (str,))
         tablesJson = parser.get("tables", [dict])
         parser.finish()
 
@@ -78,7 +76,7 @@  class DbSchema(object):
                               % version)
 
         tables = {}
-        for tableName, tableJson in six.iteritems(tablesJson):
+        for tableName, tableJson in tablesJson.items():
             _check_id(tableName, json)
             tables[tableName] = TableSchema.from_json(tableJson, tableName,
                                                       allow_extensions)
@@ -93,7 +91,7 @@  class DbSchema(object):
         default_is_root = self.__root_set_size() == len(self.tables)
 
         tables = {}
-        for table in six.itervalues(self.tables):
+        for table in self.tables.values():
             tables[table.name] = table.to_json(default_is_root)
         json = {"name": self.name, "tables": tables}
         if self.version:
@@ -137,10 +135,10 @@  class IdlSchema(DbSchema):
     @staticmethod
     def from_json(json):
         parser = ovs.db.parser.Parser(json, "IDL schema")
-        idlPrefix = parser.get("idlPrefix", six.string_types)
-        idlHeader = parser.get("idlHeader", six.string_types)
-        cDecls = parser.get_optional("cDecls", six.string_types, "")
-        hDecls = parser.get_optional("hDecls", six.string_types, "")
+        idlPrefix = parser.get("idlPrefix", (str,))
+        idlHeader = parser.get("idlHeader", (str,))
+        cDecls = parser.get_optional("cDecls", (str,), "")
+        hDecls = parser.get_optional("hDecls", (str,), "")
 
         subjson = dict(json)
         del subjson["idlPrefix"]
@@ -160,7 +158,7 @@  def column_set_from_json(json, columns):
         raise error.Error("array of distinct column names expected", json)
     else:
         for column_name in json:
-            if not isinstance(column_name, six.string_types):
+            if not isinstance(column_name, str):
                 raise error.Error("array of distinct column names expected",
                                   json)
             elif column_name not in columns:
@@ -206,7 +204,7 @@  class TableSchema(object):
             raise error.Error("table must have at least one column", json)
 
         columns = {}
-        for column_name, column_json in six.iteritems(columns_json):
+        for column_name, column_json in columns_json.items():
             _check_id(column_name, json)
             columns[column_name] = ColumnSchema.from_json(column_json,
                                                           column_name,
@@ -247,7 +245,7 @@  class TableSchema(object):
             json["isRoot"] = self.is_root
 
         json["columns"] = columns = {}
-        for column in six.itervalues(self.columns):
+        for column in self.columns.values():
             if not column.name.startswith("_"):
                 columns[column.name] = column.to_json()
 
@@ -276,7 +274,7 @@  class ColumnSchema(object):
         parser = ovs.db.parser.Parser(json, "schema for column %s" % name)
         mutable = parser.get_optional("mutable", [bool], True)
         ephemeral = parser.get_optional("ephemeral", [bool], False)
-        _types = list(six.string_types)
+        _types = [str]
         _types.extend([dict])
         type_ = ovs.db.types.Type.from_json(parser.get("type", _types))
         if allow_extensions:
diff --git a/python/ovs/db/types.py b/python/ovs/db/types.py
index 54f577405..3b47b9b30 100644
--- a/python/ovs/db/types.py
+++ b/python/ovs/db/types.py
@@ -20,8 +20,6 @@  import ovs.db.parser
 import ovs.ovsuuid
 from ovs.db import error
 
-import six
-
 
 class AtomicType(object):
     def __init__(self, name, default, python_types):
@@ -39,7 +37,7 @@  class AtomicType(object):
 
     @staticmethod
     def from_json(json):
-        if not isinstance(json, six.string_types):
+        if not isinstance(json, str):
             raise error.Error("atomic-type expected", json)
         else:
             return AtomicType.from_string(json)
@@ -57,15 +55,15 @@  class AtomicType(object):
         return ovs.db.data.Atom(self, self.default)
 
 
-REAL_PYTHON_TYPES = list(six.integer_types)
+REAL_PYTHON_TYPES = [int]
 REAL_PYTHON_TYPES.extend([float])
 REAL_PYTHON_TYPES = tuple(REAL_PYTHON_TYPES)
 
 VoidType = AtomicType("void", None, ())
-IntegerType = AtomicType("integer", 0, six.integer_types)
+IntegerType = AtomicType("integer", 0, (int,))
 RealType = AtomicType("real", 0.0, REAL_PYTHON_TYPES)
 BooleanType = AtomicType("boolean", False, (bool,))
-StringType = AtomicType("string", "", six.string_types)
+StringType = AtomicType("string", "", (str,))
 UuidType = AtomicType("uuid", ovs.ovsuuid.zero(), (uuid.UUID,))
 
 ATOMIC_TYPES = [VoidType, IntegerType, RealType, BooleanType, StringType,
@@ -155,7 +153,7 @@  class BaseType(object):
 
     @staticmethod
     def __parse_uint(parser, name, default):
-        value = parser.get_optional(name, six.integer_types)
+        value = parser.get_optional(name, (int,))
         if value is None:
             value = default
         else:
@@ -167,12 +165,11 @@  class BaseType(object):
 
     @staticmethod
     def from_json(json):
-        if isinstance(json, six.string_types):
+        if isinstance(json, str):
             return BaseType(AtomicType.from_json(json))
 
         parser = ovs.db.parser.Parser(json, "ovsdb type")
-        atomic_type = AtomicType.from_json(parser.get("type",
-                                                      six.string_types))
+        atomic_type = AtomicType.from_json(parser.get("type", (str,)))
 
         base = BaseType(atomic_type)
 
@@ -181,8 +178,8 @@  class BaseType(object):
             base.enum = ovs.db.data.Datum.from_json(
                     BaseType.get_enum_type(base.type), enum)
         elif base.type == IntegerType:
-            base.min = parser.get_optional("minInteger", six.integer_types)
-            base.max = parser.get_optional("maxInteger", six.integer_types)
+            base.min = parser.get_optional("minInteger", (int,))
+            base.max = parser.get_optional("maxInteger", (int,))
             if (base.min is not None and base.max is not None
                     and base.min > base.max):
                 raise error.Error("minInteger exceeds maxInteger", json)
@@ -202,7 +199,7 @@  class BaseType(object):
             base.ref_table_name = parser.get_optional("refTable", ['id'])
             if base.ref_table_name:
                 base.ref_type = parser.get_optional("refType",
-                                                    six.string_types,
+                                                    (str,),
                                                    "strong")
                 if base.ref_type not in ['strong', 'weak']:
                     raise error.Error('refType must be "strong" or "weak" '
@@ -520,16 +517,16 @@  class Type(object):
 
     @staticmethod
     def from_json(json):
-        if isinstance(json, six.string_types):
+        if isinstance(json, str):
             return Type(BaseType.from_json(json))
 
         parser = ovs.db.parser.Parser(json, "ovsdb type")
-        _types = list(six.string_types)
+        _types = [str]
         _types.extend([dict])
         key_json = parser.get("key", _types)
         value_json = parser.get_optional("value", _types)
         min_json = parser.get_optional("min", [int])
-        _types = list(six.string_types)
+        _types = [str]
         _types.extend([int])
         max_json = parser.get_optional("max", _types)
         parser.finish()
diff --git a/python/ovs/json.py b/python/ovs/json.py
index 96a07513d..0559c723f 100644
--- a/python/ovs/json.py
+++ b/python/ovs/json.py
@@ -19,8 +19,6 @@  import json
 import re
 import sys
 
-import six
-
 PARSER_C = 'C'
 PARSER_PY = 'PYTHON'
 try:
@@ -32,13 +30,7 @@  except ImportError:
 __pychecker__ = 'no-stringiter'
 
 SPACES_PER_LEVEL = 2
-_dumper = functools.partial(json.dumps, separators=(",", ":"))
-
-if six.PY2:
-    def dumper(*args, **kwargs):
-        return _dumper(*args, **kwargs).decode('raw-unicode-escape')
-else:
-    dumper = _dumper
+dumper = functools.partial(json.dumps, separators=(",", ":"))
 
 
 def to_stream(obj, stream, pretty=False, sort_keys=True):
@@ -74,12 +66,12 @@  def from_file(name):
 
 
 def from_string(s):
-    if not isinstance(s, six.text_type):
+    if not isinstance(s, str):
         # We assume the input is a string.  We will only hit this case for a
         # str in Python 2 which is not unicode, so we need to go ahead and
         # decode it.
         try:
-            s = six.text_type(s, 'utf-8')
+            s = str(s, 'utf-8')
         except UnicodeDecodeError as e:
             seq = ' '.join(["0x%2x" % ord(c)
                            for c in e.object[e.start:e.end] if ord(c) >= 0x80])
@@ -341,7 +333,7 @@  class Parser(object):
                 inp = inp[6:]
             else:
                 code_point = c0
-            out += six.unichr(code_point)
+            out += chr(code_point)
         self.__parser_input('string', out)
 
     def __lex_string_escape(self, c):
@@ -466,7 +458,7 @@  class Parser(object):
                 self.parse_state = Parser.__parse_object_next
 
     def __parse_value(self, token, string, next_state):
-        number_types = list(six.integer_types)
+        number_types = [int]
         number_types.extend([float])
         number_types = tuple(number_types)
         if token in [False, None, True] or isinstance(token, number_types):
diff --git a/python/ovs/jsonrpc.py b/python/ovs/jsonrpc.py
index 4a3027e9e..240e8ccd4 100644
--- a/python/ovs/jsonrpc.py
+++ b/python/ovs/jsonrpc.py
@@ -25,8 +25,6 @@  import ovs.timeval
 import ovs.util
 import ovs.vlog
 
-import six
-
 EOF = ovs.util.EOF
 vlog = ovs.vlog.Vlog("jsonrpc")
 
@@ -119,7 +117,7 @@  class Message(object):
 
         if "method" in json:
             method = json.pop("method")
-            if not isinstance(method, six.string_types):
+            if not isinstance(method, str):
                 return "method is not a JSON string"
         else:
             method = None
@@ -272,8 +270,7 @@  class Connection(object):
                 # data, so we convert it here as soon as possible.
                 if data and not error:
                     try:
-                        if six.PY3 or ovs.json.PARSER == ovs.json.PARSER_PY:
-                            data = decoder.decode(data)
+                        data = decoder.decode(data)
                     except UnicodeError:
                         error = errno.EILSEQ
                 if error:
@@ -299,7 +296,7 @@  class Connection(object):
             else:
                 if self.parser is None:
                     self.parser = ovs.json.Parser()
-                if six.PY3 and ovs.json.PARSER == ovs.json.PARSER_C:
+                if ovs.json.PARSER == ovs.json.PARSER_C:
                     self.input = self.input.encode('utf-8')[
                         self.parser.feed(self.input):].decode()
                 else:
@@ -341,7 +338,7 @@  class Connection(object):
     def __process_msg(self):
         json = self.parser.finish()
         self.parser = None
-        if isinstance(json, six.string_types):
+        if isinstance(json, str):
             # XXX rate-limit
             vlog.warn("%s: error parsing stream: %s" % (self.name, json))
             self.error(errno.EPROTO)
diff --git a/python/ovs/ovsuuid.py b/python/ovs/ovsuuid.py
index 35c5bd29f..6498ec040 100644
--- a/python/ovs/ovsuuid.py
+++ b/python/ovs/ovsuuid.py
@@ -18,9 +18,6 @@  import uuid
 import ovs.db.parser
 from ovs.db import error
 
-import six
-from six.moves import range
-
 uuidRE = re.compile("^xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx$"
                     .replace('x', '[0-9a-fA-F]'))
 
@@ -41,7 +38,7 @@  def from_string(s):
 
 def from_json(json, symtab=None):
     try:
-        s = ovs.db.parser.unwrap_json(json, "uuid", six.string_types, "string")
+        s = ovs.db.parser.unwrap_json(json, "uuid", (str,), "string")
         if not uuidRE.match(s):
             raise error.Error("\"%s\" is not a valid UUID" % s, json)
         return uuid.UUID(s)
@@ -50,7 +47,7 @@  def from_json(json, symtab=None):
             raise e
         try:
             name = ovs.db.parser.unwrap_json(json, "named-uuid",
-                                             six.string_types, "string")
+                                             (str,), "string")
         except error.Error:
             raise e
 
diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
index 8f9d31825..3faa64e9d 100644
--- a/python/ovs/socket_util.py
+++ b/python/ovs/socket_util.py
@@ -23,9 +23,6 @@  import ovs.fatal_signal
 import ovs.poller
 import ovs.vlog
 
-import six
-from six.moves import range
-
 if sys.platform == 'win32':
     import ovs.winutils as winutils
     import win32file
@@ -296,8 +293,8 @@  def write_fully(fd, buf):
     bytes_written = 0
     if len(buf) == 0:
         return 0, 0
-    if six.PY3 and not isinstance(buf, six.binary_type):
-        buf = six.binary_type(buf, 'utf-8')
+    if not isinstance(buf, bytes):
+        buf = bytes(buf, 'utf-8')
     while True:
         try:
             retval = os.write(fd, buf)
diff --git a/python/ovs/stream.py b/python/ovs/stream.py
index a98057e42..e9bb0c854 100644
--- a/python/ovs/stream.py
+++ b/python/ovs/stream.py
@@ -21,8 +21,6 @@  import ovs.poller
 import ovs.socket_util
 import ovs.vlog
 
-import six
-
 try:
     from OpenSSL import SSL
 except ImportError:
@@ -86,7 +84,7 @@  class Stream(object):
 
     @staticmethod
     def _find_method(name):
-        for method, cls in six.iteritems(Stream._SOCKET_METHODS):
+        for method, cls in Stream._SOCKET_METHODS.items():
             if name.startswith(method):
                 return cls
         return None
@@ -401,7 +399,7 @@  class Stream(object):
             return 0
 
         # We must have bytes for sending.
-        if isinstance(buf, six.text_type):
+        if isinstance(buf, str):
             buf = buf.encode('utf-8')
 
         if sys.platform == 'win32' and self.socket is None:
diff --git a/python/ovs/unixctl/__init__.py b/python/ovs/unixctl/__init__.py
index c2e5aca8d..8ee312943 100644
--- a/python/ovs/unixctl/__init__.py
+++ b/python/ovs/unixctl/__init__.py
@@ -16,10 +16,7 @@  import sys
 
 import ovs.util
 
-import six
-
 commands = {}
-strtypes = six.string_types
 
 
 class _UnixctlCommand(object):
@@ -59,8 +56,8 @@  def command_register(name, usage, min_args, max_args, callback, aux):
     request at a time, so a reply must be made eventually to avoid blocking
     that connection."""
 
-    assert isinstance(name, strtypes)
-    assert isinstance(usage, strtypes)
+    assert isinstance(name, str)
+    assert isinstance(usage, str)
     assert isinstance(min_args, int)
     assert isinstance(max_args, int)
     assert callable(callback)
@@ -71,7 +68,7 @@  def command_register(name, usage, min_args, max_args, callback, aux):
 
 
 def socket_name_from_target(target):
-    assert isinstance(target, strtypes)
+    assert isinstance(target, str)
 
     """ On Windows an absolute path contains ':' ( i.e: C:\\ ) """
     if target.startswith('/') or target.find(':') > -1:
diff --git a/python/ovs/unixctl/client.py b/python/ovs/unixctl/client.py
index e07b0380c..8283f99bb 100644
--- a/python/ovs/unixctl/client.py
+++ b/python/ovs/unixctl/client.py
@@ -18,10 +18,7 @@  import ovs.jsonrpc
 import ovs.stream
 import ovs.util
 
-import six
-
 vlog = ovs.vlog.Vlog("unixctl_client")
-strtypes = six.string_types
 
 
 class UnixctlClient(object):
@@ -30,10 +27,10 @@  class UnixctlClient(object):
         self._conn = conn
 
     def transact(self, command, argv):
-        assert isinstance(command, strtypes)
+        assert isinstance(command, str)
         assert isinstance(argv, list)
         for arg in argv:
-            assert isinstance(arg, strtypes)
+            assert isinstance(arg, str)
 
         request = ovs.jsonrpc.Message.create_request(command, argv)
         error, reply = self._conn.transact_block(request)
diff --git a/python/ovs/unixctl/server.py b/python/ovs/unixctl/server.py
index d5fb0807d..5f9b3e739 100644
--- a/python/ovs/unixctl/server.py
+++ b/python/ovs/unixctl/server.py
@@ -25,12 +25,9 @@  import ovs.util
 import ovs.version
 import ovs.vlog
 
-import six
-from six.moves import range
 
 Message = ovs.jsonrpc.Message
 vlog = ovs.vlog.Vlog("unixctl_server")
-strtypes = six.string_types
 
 
 class UnixctlConnection(object):
@@ -83,7 +80,7 @@  class UnixctlConnection(object):
 
     def _reply_impl(self, success, body):
         assert isinstance(success, bool)
-        assert body is None or isinstance(body, strtypes)
+        assert body is None or isinstance(body, str)
 
         assert self._request_id is not None
 
@@ -121,12 +118,12 @@  class UnixctlConnection(object):
                     % (method, command.max_args)
         else:
             for param in params:
-                if not isinstance(param, strtypes):
+                if not isinstance(param, str):
                     error = '"%s" command has non-string argument' % method
                     break
 
             if error is None:
-                unicode_params = [six.text_type(p) for p in params]
+                unicode_params = [str(p) for p in params]
                 command.callback(self, unicode_params, command.aux)
 
         if error:
@@ -188,7 +185,7 @@  class UnixctlServer(object):
         'version' contains the version of the server as reported by the unixctl
         version command.  If None, ovs.version.VERSION is used."""
 
-        assert path is None or isinstance(path, strtypes)
+        assert path is None or isinstance(path, str)
 
         if path is not None:
             path = "punix:%s" % ovs.util.abs_file_name(ovs.dirs.RUNDIR, path)
@@ -222,10 +219,10 @@  class UnixctlClient(object):
         self._conn = conn
 
     def transact(self, command, argv):
-        assert isinstance(command, strtypes)
+        assert isinstance(command, str)
         assert isinstance(argv, list)
         for arg in argv:
-            assert isinstance(arg, strtypes)
+            assert isinstance(arg, str)
 
         request = Message.create_request(command, argv)
         error, reply = self._conn.transact_block(request)
diff --git a/python/ovs/vlog.py b/python/ovs/vlog.py
index ae5156d60..61f5928db 100644
--- a/python/ovs/vlog.py
+++ b/python/ovs/vlog.py
@@ -26,9 +26,6 @@  import ovs.dirs
 import ovs.unixctl
 import ovs.util
 
-import six
-from six.moves import range
-
 DESTINATIONS = {"console": "info", "file": "info", "syslog": "info"}
 PATTERNS = {
     "console": "%D{%Y-%m-%dT%H:%M:%SZ}|%05N|%c%T|%p|%m",
@@ -81,7 +78,7 @@  class Vlog(object):
         msg_num = Vlog.__msg_num
         Vlog.__msg_num += 1
 
-        for f, f_level in six.iteritems(Vlog.__mfl[self.name]):
+        for f, f_level in Vlog.__mfl[self.name].items():
             f_level = LEVELS.get(f_level, logging.CRITICAL)
             if level_num >= f_level:
                 msg = self._build_message(message, f, level, msg_num)
@@ -185,7 +182,7 @@  class Vlog(object):
 
     def __is_enabled(self, level):
         level = LEVELS.get(level.lower(), logging.DEBUG)
-        for f, f_level in six.iteritems(Vlog.__mfl[self.name]):
+        for f, f_level in Vlog.__mfl[self.name].items():
             f_level = LEVELS.get(f_level, logging.CRITICAL)
             if level >= f_level:
                 return True
diff --git a/python/ovstest/rpcserver.py b/python/ovstest/rpcserver.py
index ab5b7e89e..c4aab7020 100644
--- a/python/ovstest/rpcserver.py
+++ b/python/ovstest/rpcserver.py
@@ -16,13 +16,11 @@ 
 rpcserver is an XML RPC server that allows RPC client to initiate tests
 """
 
-from __future__ import print_function
-
 import sys
 
 import exceptions
 
-import six.moves.xmlrpc_client
+import xmlrpc.client
 
 import tcp
 
@@ -113,8 +111,7 @@  class TestArena(xmlrpc.XMLRPC):
         Returns the ovs-test server IP address that the other ovs-test server
         with the given ip will see.
         """
-        server1 = six.moves.xmlrpc_client.Server("http://%s:%u/" %
-                                                 (his_ip, his_port))
+        server1 = xmlrpc.client.Server("http://%s:%u/" % (his_ip, his_port))
         return server1.get_my_address()
 
     def xmlrpc_create_udp_listener(self, port):
diff --git a/python/ovstest/util.py b/python/ovstest/util.py
index db2ae989a..72457158f 100644
--- a/python/ovstest/util.py
+++ b/python/ovstest/util.py
@@ -28,8 +28,7 @@  import subprocess
 
 import exceptions
 
-import six.moves.xmlrpc_client
-from six.moves import range
+import xmlrpc.client
 
 
 def str_ip(ip_address):
@@ -189,8 +188,7 @@  def get_interface_from_routing_decision(ip):
 
 
 def rpc_client(ip, port):
-    return six.moves.xmlrpc_client.Server("http://%s:%u/" % (ip, port),
-                                          allow_none=True)
+    return xmlrpc.client.Server("http://%s:%u/" % (ip, port), allow_none=True)
 
 
 def sigint_intercept():
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index 0f6352101..7bc8c34b8 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -109,7 +109,6 @@  Summary: Open vSwitch python3 bindings
 License: ASL 2.0
 BuildArch: noarch
 Requires: python3
-Requires: python3-six
 %{?python_provide:%python_provide python3-openvswitch = %{version}-%{release}}
 
 %description -n python3-openvswitch
diff --git a/tests/test-json.py b/tests/test-json.py
index 582aa720a..a0392b9af 100644
--- a/tests/test-json.py
+++ b/tests/test-json.py
@@ -12,19 +12,14 @@ 
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
-import codecs
 import getopt
 import sys
 
 import ovs.json
 
-import six
-
 
 def print_json(json):
-    if isinstance(json, six.string_types):
+    if isinstance(json, str):
         print("error: %s" % json)
         return False
     else:
@@ -59,12 +54,6 @@  def parse_multiple(stream):
 def main(argv):
     argv0 = argv[0]
 
-    # When this is used with Python 3, the program produces no output.
-    if six.PY2:
-        # Make stdout and stderr UTF-8, even if they are redirected to a file.
-        sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
-        sys.stderr = codecs.getwriter("utf-8")(sys.stderr)
-
     try:
         options, args = getopt.gnu_getopt(argv[1:], '', ['multiple'])
     except getopt.GetoptError as geo:
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 422321a4c..1b94b79a0 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -12,8 +12,6 @@ 
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import getopt
 import os
 import re
@@ -32,8 +30,6 @@  from ovs.db import data
 from ovs.db import error
 from ovs.fatal_signal import signal_alarm
 
-import six
-
 vlog = ovs.vlog.Vlog("test-ovsdb")
 vlog.set_levels_from_string("console:dbg")
 vlog.init(None)
@@ -194,7 +190,7 @@  def print_idl(idl, step):
     n = 0
     if "simple" in idl.tables:
         simple = idl.tables["simple"].rows
-        for row in six.itervalues(simple):
+        for row in simple.values():
             s = "%03d: " % step
             s += get_simple_table_printable_row(row)
             print(s)
@@ -202,7 +198,7 @@  def print_idl(idl, step):
 
     if "simple2" in idl.tables:
         simple2 = idl.tables["simple2"].rows
-        for row in six.itervalues(simple2):
+        for row in simple2.values():
             s = "%03d: " % step
             s += get_simple2_table_printable_row(row)
             print(s)
@@ -210,7 +206,7 @@  def print_idl(idl, step):
 
     if "simple3" in idl.tables:
         simple3 = idl.tables["simple3"].rows
-        for row in six.itervalues(simple3):
+        for row in simple3.values():
             s = "%03d: " % step
             s += get_simple3_table_printable_row(row)
             print(s)
@@ -218,7 +214,7 @@  def print_idl(idl, step):
 
     if "link1" in idl.tables:
         l1 = idl.tables["link1"].rows
-        for row in six.itervalues(l1):
+        for row in l1.values():
             s = ["%03d: i=%s k=" % (step, row.i)]
             if hasattr(row, "k") and row.k:
                 s.append(str(row.k.i))
@@ -235,7 +231,7 @@  def print_idl(idl, step):
 
     if "link2" in idl.tables:
         l2 = idl.tables["link2"].rows
-        for row in six.itervalues(l2):
+        for row in l2.values():
             s = ["%03d:" % step]
             s.append(" i=%s l1=" % row.i)
             if hasattr(row, "l1") and row.l1:
@@ -247,7 +243,7 @@  def print_idl(idl, step):
 
     if "singleton" in idl.tables:
         sng = idl.tables["singleton"].rows
-        for row in six.itervalues(sng):
+        for row in sng.values():
             s = ["%03d:" % step]
             s.append(" name=%s" % row.name)
             if hasattr(row, "uuid"):
@@ -261,7 +257,7 @@  def print_idl(idl, step):
 
 
 def substitute_uuids(json, symtab):
-    if isinstance(json, six.string_types):
+    if isinstance(json, str):
         symbol = symtab.get(json)
         if symbol:
             return str(symbol)
@@ -269,14 +265,14 @@  def substitute_uuids(json, symtab):
         return [substitute_uuids(element, symtab) for element in json]
     elif type(json) == dict:
         d = {}
-        for key, value in six.iteritems(json):
+        for key, value in json.items():
             d[key] = substitute_uuids(value, symtab)
         return d
     return json
 
 
 def parse_uuids(json, symtab):
-    if (isinstance(json, six.string_types)
+    if (isinstance(json, str)
             and ovs.ovsuuid.is_valid_string(json)):
         name = "#%d#" % len(symtab)
         sys.stderr.write("%s = %s\n" % (name, json))
@@ -285,19 +281,19 @@  def parse_uuids(json, symtab):
         for element in json:
             parse_uuids(element, symtab)
     elif type(json) == dict:
-        for value in six.itervalues(json):
+        for value in json.values():
             parse_uuids(value, symtab)
 
 
 def idltest_find_simple(idl, i):
-    for row in six.itervalues(idl.tables["simple"].rows):
+    for row in idl.tables["simple"].rows.values():
         if row.i == i:
             return row
     return None
 
 
 def idltest_find_simple2(idl, i):
-    for row in six.itervalues(idl.tables["simple2"].rows):
+    for row in idl.tables["simple2"].rows.values():
         if row.name == i:
             return row
     return None
@@ -346,12 +342,9 @@  def idl_set(idl, commands, step):
             if args[1] == "b":
                 s.b = args[2] == "1"
             elif args[1] == "s":
-                if six.PY2:
-                    s.s = args[2].decode('utf-8')
-                else:
-                    s.s = args[2].encode(sys.getfilesystemencoding(),
-                                         'surrogateescape') \
-                                 .decode('utf-8', 'replace')
+                s.s = args[2].encode(sys.getfilesystemencoding(),
+                                     'surrogateescape') \
+                             .decode('utf-8', 'replace')
             elif args[1] == "u":
                 s.u = uuid.UUID(args[2])
             elif args[1] == "r":
@@ -677,7 +670,7 @@  def do_idl(schema_file, remote, *commands):
             step += 1
         else:
             json = ovs.json.from_string(command)
-            if isinstance(json, six.string_types):
+            if isinstance(json, str):
                 sys.stderr.write("\"%s\": %s\n" % (command, json))
                 sys.exit(1)
             json = substitute_uuids(json, symtab)
@@ -730,7 +723,7 @@  def do_idl_passive(schema_file, remote, *commands):
 
     for command in commands:
         json = ovs.json.from_string(command)
-        if isinstance(json, six.string_types):
+        if isinstance(json, str):
             sys.stderr.write("\"%s\": %s\n" % (command, json))
             sys.exit(1)
         json = substitute_uuids(json, symtab)
diff --git a/tests/test-vlog.py b/tests/test-vlog.py
index d711e0b66..16e163d9b 100644
--- a/tests/test-vlog.py
+++ b/tests/test-vlog.py
@@ -16,8 +16,6 @@  import argparse
 
 import ovs.vlog
 
-from six.moves import range
-
 
 def main():
     modules = [ovs.vlog.Vlog("module_%d" % i) for i in range(3)]
diff --git a/utilities/bugtool/ovs-bugtool.in b/utilities/bugtool/ovs-bugtool.in
index 0f3189426..e55bfc2ed 100755
--- a/utilities/bugtool/ovs-bugtool.in
+++ b/utilities/bugtool/ovs-bugtool.in
@@ -33,8 +33,6 @@ 
 # or func_output().
 #
 
-from __future__ import print_function
-
 import StringIO
 import commands
 import fcntl
@@ -54,7 +52,6 @@  from subprocess import PIPE, Popen
 
 from xml.dom.minidom import getDOMImplementation, parse
 
-from six.moves import input
 warnings.filterwarnings(action="ignore", category=DeprecationWarning)
 
 OS_RELEASE = platform.release()
diff --git a/utilities/docker/debian/build-kernel-modules.sh b/utilities/docker/debian/build-kernel-modules.sh
index 18ac35764..47788a684 100755
--- a/utilities/docker/debian/build-kernel-modules.sh
+++ b/utilities/docker/debian/build-kernel-modules.sh
@@ -19,8 +19,7 @@  GITHUB_SRC=$3
 # Install deps
 linux="linux-image-$KERNEL_VERSION linux-headers-$KERNEL_VERSION"
 build_deps="apt-utils libelf-dev build-essential libssl-dev python3 \
-python3-six wget gdb autoconf libtool git automake bzip2 debhelper \
-dh-autoreconf openssl"
+wget gdb autoconf libtool git automake bzip2 debhelper dh-autoreconf openssl"
 
 apt-get update
 apt-get install -y ${linux} ${build_deps}
diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py
index d8277dbcf..befc2b4a4 100644
--- a/utilities/gdb/ovs_gdb.py
+++ b/utilities/gdb/ovs_gdb.py
@@ -55,10 +55,7 @@ 
 #    ...
 #    ...
 #
-from __future__ import print_function
-
 import gdb
-import six
 import sys
 import uuid
 
@@ -69,13 +66,6 @@  import uuid
 N_UMAPS = 512
 
 
-#
-# For Python2-3 compatibility define long as int
-#
-if six.PY3:
-    long = int
-
-
 #
 # The container_of code below is a copied from the Linux kernel project file,
 # scripts/gdb/linux/utils.py. It has the following copyright header:
@@ -143,22 +133,22 @@  def get_time_msec():
     # to get a decent time time_now() value. For now we take the global
     # "coverage_run_time" value, which is the current time + max 5 seconds
     # (COVERAGE_RUN_INTERVAL)
-    return long(get_global_variable("coverage_run_time")), -5000
+    return int(get_global_variable("coverage_run_time")), -5000
 
 
 def get_time_now():
     # See get_time_msec() above
-    return long(get_global_variable("coverage_run_time"))/1000, -5
+    return int(get_global_variable("coverage_run_time"))/1000, -5
 
 
 def eth_addr_to_string(eth_addr):
     return "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(
-        long(eth_addr['ea'][0]),
-        long(eth_addr['ea'][1]),
-        long(eth_addr['ea'][2]),
-        long(eth_addr['ea'][3]),
-        long(eth_addr['ea'][4]),
-        long(eth_addr['ea'][5]))
+        int(eth_addr['ea'][0]),
+        int(eth_addr['ea'][1]),
+        int(eth_addr['ea'][2]),
+        int(eth_addr['ea'][3]),
+        int(eth_addr['ea'][4]),
+        int(eth_addr['ea'][5]))
 
 
 #
@@ -308,7 +298,7 @@  class ForEachHMAP(object):
 class ForEachNL():
     def __init__(self, nlattrs, nlattrs_len):
         self.attr = nlattrs.cast(gdb.lookup_type('struct nlattr').pointer())
-        self.attr_len = long(nlattrs_len)
+        self.attr_len = int(nlattrs_len)
 
     def __iter__(self):
         return self
@@ -641,7 +631,7 @@  class CmdDumpDpProvider(gdb.Command):
                   "(struct dpif_class *) 0x{:x} = {{type = {}, ...}}, "
                   "refcount = {}".
                   format(dp_class,
-                         long(dp_class['dpif_class']),
+                         int(dp_class['dpif_class']),
                          dp_class['dpif_class']['type'].string(),
                          dp_class['refcount']))
 
@@ -704,7 +694,7 @@  class CmdDumpNetdevProvider(gdb.Command):
 
         print("{}    (struct netdev_class *) 0x{:x} = {{type = {}, "
               "is_pmd = {}, ...}}, ".
-              format(indent, long(reg_class['class']),
+              format(indent, int(reg_class['class']),
                      reg_class['class']['type'].string(),
                      reg_class['class']['is_pmd']))
 
@@ -721,7 +711,7 @@  class CmdDumpNetdevProvider(gdb.Command):
 
             print("{}    (struct vport_class *) 0x{:x} = "
                   "{{ dpif_port = {}, ... }}".
-                  format(indent, long(vport), dpif_port))
+                  format(indent, int(vport), dpif_port))
 
     def invoke(self, arg, from_tty):
         netdev_classes = get_global_variable('netdev_classes')
@@ -834,11 +824,11 @@  class CmdDumpSimap(gdb.Command):
         values = dict()
         max_name_len = 0
         for name, value in ForEachSIMAP(simap.dereference()):
-            values[name.string()] = long(value)
+            values[name.string()] = int(value)
             if len(name.string()) > max_name_len:
                 max_name_len = len(name.string())
 
-        for name in sorted(six.iterkeys(values)):
+        for name in sorted(values.keys()):
             print("{}: {} / 0x{:x}".format(name.ljust(max_name_len),
                                            values[name], values[name]))
 
@@ -873,7 +863,7 @@  class CmdDumpSmap(gdb.Command):
             if len(key.string()) > max_key_len:
                 max_key_len = len(key.string())
 
-        for key in sorted(six.iterkeys(values)):
+        for key in sorted(values.keys()):
             print("{}: {}".format(key.ljust(max_key_len),
                                   values[key]))
 
@@ -935,13 +925,13 @@  class CmdDumpUdpifKeys(gdb.Command):
                               format(
                                   indent_b, str(uuid.UUID(
                                       "{:08x}{:08x}{:08x}{:08x}".
-                                      format(long(ukey['ufid']['u32'][3]),
-                                             long(ukey['ufid']['u32'][2]),
-                                             long(ukey['ufid']['u32'][1]),
-                                             long(ukey['ufid']['u32'][0]))))))
+                                      format(int(ukey['ufid']['u32'][3]),
+                                             int(ukey['ufid']['u32'][2]),
+                                             int(ukey['ufid']['u32'][1]),
+                                             int(ukey['ufid']['u32'][0]))))))
 
                     print("{}hash = 0x{:8x}, pmd_id = {}".
-                          format(indent_b, long(ukey['hash']), ukey['pmd_id']))
+                          format(indent_b, int(ukey['hash']), ukey['pmd_id']))
                     print("{}state = {}".format(indent_b, ukey['state']))
                     print("{}n_packets = {}, n_bytes = {}".
                           format(indent_b,
@@ -950,7 +940,7 @@  class CmdDumpUdpifKeys(gdb.Command):
                     print("{}used = {}, tcp_flags = 0x{:04x}".
                           format(indent_b,
                                  ukey['stats']['used'],
-                                 long(ukey['stats']['tcp_flags'])))
+                                 int(ukey['stats']['tcp_flags'])))
 
                     #
                     # TODO: Would like to add support for dumping key, mask
@@ -1030,7 +1020,7 @@  class CmdShowFDB(gdb.Command):
                 gdb.lookup_type('struct ofbundle').pointer())
 
             port_name = port['name'].string()
-            port_no = long(container_of(
+            port_no = int(container_of(
                 port['ports']['next'],
                 gdb.lookup_type('struct ofport_dpif').pointer(),
                 'bundle_node')['up']['ofp_port'])
@@ -1071,7 +1061,7 @@  class CmdShowFDB(gdb.Command):
             print("[(struct mac_learning *) {}]".format(ml))
 
         print("{}table.n         : {}".format(indent, ml['table']['n']))
-        print("{}secret          : 0x{:x}".format(indent, long(ml['secret'])))
+        print("{}secret          : 0x{:x}".format(indent, int(ml['secret'])))
         print("{}idle_time       : {}".format(indent, ml['idle_time']))
         print("{}max_entries     : {}".format(indent, ml['max_entries']))
         print("{}ref_count       : {}".format(indent, ml['ref_cnt']['count']))
@@ -1091,9 +1081,9 @@  class CmdShowFDB(gdb.Command):
         line = "{}{:16.16}  {:-4}  {}  {:-9}".format(
             indent,
             "{}[{}]".format(port_no, port_name),
-            long(mac_entry['vlan']),
+            int(mac_entry['vlan']),
             eth_addr_to_string(mac_entry['mac']),
-            long(mac_entry['expires']))
+            int(mac_entry['expires']))
 
         if dbg:
             line += " [(struct mac_entry *) {}]".format(mac_entry)
@@ -1154,7 +1144,7 @@  class CmdShowFDB(gdb.Command):
                 max_name_len = len(node['up']['name'].string())
 
         if len(arg_list) == 0:
-            for name in sorted(six.iterkeys(all_name)):
+            for name in sorted(all_name.keys()):
                 print("{}: (struct mac_learning *) {}".
                       format(name.ljust(max_name_len),
                              all_name[name]['ml']))
diff --git a/vtep/ovs-vtep.in b/vtep/ovs-vtep.in
index de848d1a0..0ee23b119 100755
--- a/vtep/ovs-vtep.in
+++ b/vtep/ovs-vtep.in
@@ -29,9 +29,6 @@  import ovs.unixctl.server
 import ovs.util
 import ovs.vlog
 
-import six
-from six.moves import range
-
 
 VERSION = "0.99"
 
@@ -123,7 +120,7 @@  class Logical_Switch(object):
         ovs_ofctl("add-flow %s priority=0,action=drop" % self.short_name)
 
     def cleanup_ls(self):
-        for port_no, tun_name, remote_ip in six.itervalues(self.tunnels):
+        for port_no, tun_name, remote_ip in self.tunnels.values():
             del_bfd(remote_ip)
 
     def update_flood(self):
@@ -257,7 +254,7 @@  class Logical_Switch(object):
         column = vtep_ctl("--columns=tunnel_key find logical_switch "
                           "name=%s" % self.name)
         tunnel_key = column.partition(":")[2].strip()
-        if tunnel_key and isinstance(eval(tunnel_key), six.integer_types):
+        if tunnel_key and isinstance(eval(tunnel_key), int):
             vlog.info("update_remote_macs: using tunnel key %s in %s"
                       % (tunnel_key, self.name))
         else:
@@ -293,11 +290,11 @@  class Logical_Switch(object):
         for tunnel in old_tunnels.difference(tunnels):
             self.del_tunnel(tunnel)
 
-        for mac in six.iterkeys(remote_macs):
+        for mac in remote_macs.keys():
             if (self.remote_macs.get(mac) != remote_macs[mac]):
                 self.add_remote_mac(mac, remote_macs[mac])
 
-        for mac in six.iterkeys(self.remote_macs):
+        for mac in self.remote_macs.keys():
             if mac not in remote_macs:
                 self.del_remote_mac(mac)
 
@@ -341,7 +338,7 @@  class Logical_Switch(object):
 
         # Go through all the logical switch's interfaces that end with "-l"
         # and copy the statistics to logical_binding_stats.
-        for interface in six.iterkeys(self.ports):
+        for interface in self.ports.keys():
             if not interface.endswith("-l"):
                 continue
             # Physical ports can have a '-' as part of its name.
@@ -352,7 +349,7 @@  class Logical_Switch(object):
             if not uuid:
                 continue
 
-            for mapfrom, mapto in six.iteritems(stats_map):
+            for mapfrom, mapto in stats_map.items():
                 value = ovs_vsctl("get interface %s statistics:%s"
                                   % (interface, mapfrom)).strip('"')
                 vtep_ctl("set logical_binding_stats %s %s=%s"
@@ -468,7 +465,7 @@  def run_bfd():
                               'bfd_params:check_tnl_key': 'false'}
         bfd_params_values = {}
 
-        for key, default in six.iteritems(bfd_params_default):
+        for key, default in bfd_params_default.items():
             column = vtep_ctl("--if-exists get tunnel %s %s"
                               % (tunnel, key))
             if not column:
@@ -476,7 +473,7 @@  def run_bfd():
             else:
                 bfd_params_values[key] = column
 
-        for key, value in six.iteritems(bfd_params_values):
+        for key, value in bfd_params_values.items():
             new_key = key.replace('_params', '')
             ovs_vsctl("set interface %s %s=%s" % (port, new_key, value))
 
@@ -498,7 +495,7 @@  def run_bfd():
         bfd_lconf_default = {'bfd_config_local:bfd_dst_ip': '169.254.1.0',
                              'bfd_config_local:bfd_dst_mac':
                              '00:23:20:00:00:01'}
-        for key, value in six.iteritems(bfd_lconf_default):
+        for key, value in bfd_lconf_default.items():
             vtep_ctl("set tunnel %s %s=%s" % (tunnel, key, value))
 
         # bfd_config_remote options from VTEP DB should be populated to
@@ -750,7 +747,7 @@  def main():
 
         handle_physical()
 
-        for ls_name, ls in six.iteritems(Lswitches):
+        for ls_name, ls in Lswitches.items():
             ls.run()
 
         run_bfd()
diff --git a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
index ecd6f6d70..cf8960025 100755
--- a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
+++ b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
@@ -35,8 +35,6 @@  import ovs.dirs
 import ovs.unixctl
 import ovs.unixctl.server
 
-import six
-
 vlog = ovs.vlog.Vlog("ovs-xapi-sync")
 session = None
 flush_cache = False
@@ -86,7 +84,7 @@  def get_network_by_bridge(br_name):
     recs = session.xenapi.network.get_all_records_where(
             'field "bridge"="%s"' % br_name)
     if len(recs) > 0:
-        return next(six.itervalues(recs))
+        return next(iter(recs.values()))
 
     return None
 
@@ -296,7 +294,7 @@  def main():
         txn = ovs.db.idl.Transaction(idl)
 
         new_bridges = {}
-        for row in six.itervalues(idl.tables["Bridge"].rows):
+        for row in idl.tables["Bridge"].rows.values():
             bridge_id = bridges.get(row.name)
             if bridge_id is None:
                 # Configure the new bridge.
@@ -321,12 +319,12 @@  def main():
         bridges = new_bridges
 
         iface_by_name = {}
-        for row in six.itervalues(idl.tables["Interface"].rows):
+        for row in idl.tables["Interface"].rows.values():
             iface_by_name[row.name] = row
 
         new_iface_ids = {}
         new_vm_ids = {}
-        for row in six.itervalues(idl.tables["Interface"].rows):
+        for row in idl.tables["Interface"].rows.values():
             # Match up paired vif and tap devices.
             if row.name.startswith("vif"):
                 vif = row