diff --git a/openstack-common.conf b/openstack-common.conf
index a9223df45..f22613441 100644
--- a/openstack-common.conf
+++ b/openstack-common.conf
@@ -7,6 +7,7 @@ module=gettextutils
 module=importutils
 module=jsonutils
 module=network_utils
+module=py3kcompat
 module=sslutils
 module=timeutils
 
diff --git a/oslo/messaging/openstack/common/py3kcompat/__init__.py b/oslo/messaging/openstack/common/py3kcompat/__init__.py
new file mode 100644
index 000000000..97ae4e34a
--- /dev/null
+++ b/oslo/messaging/openstack/common/py3kcompat/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright 2013 Canonical Ltd.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
diff --git a/oslo/messaging/openstack/common/py3kcompat/urlutils.py b/oslo/messaging/openstack/common/py3kcompat/urlutils.py
new file mode 100644
index 000000000..6200271f3
--- /dev/null
+++ b/oslo/messaging/openstack/common/py3kcompat/urlutils.py
@@ -0,0 +1,65 @@
+#
+# Copyright 2013 Canonical Ltd.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+"""
+Python2/Python3 compatibility layer for OpenStack
+"""
+
+import six
+
+if six.PY3:
+    # python3
+    import urllib.error
+    import urllib.parse
+    import urllib.request
+
+    urlencode = urllib.parse.urlencode
+    urljoin = urllib.parse.urljoin
+    quote = urllib.parse.quote
+    parse_qsl = urllib.parse.parse_qsl
+    unquote = urllib.parse.unquote
+    unquote_plus = urllib.parse.unquote_plus
+    urlparse = urllib.parse.urlparse
+    urlsplit = urllib.parse.urlsplit
+    urlunsplit = urllib.parse.urlunsplit
+    SplitResult = urllib.parse.SplitResult
+
+    urlopen = urllib.request.urlopen
+    URLError = urllib.error.URLError
+    pathname2url = urllib.request.pathname2url
+else:
+    # python2
+    import urllib
+    import urllib2
+    import urlparse
+
+    urlencode = urllib.urlencode
+    quote = urllib.quote
+    unquote = urllib.unquote
+    unquote_plus = urllib.unquote_plus
+
+    parse = urlparse
+    parse_qsl = parse.parse_qsl
+    urljoin = parse.urljoin
+    urlparse = parse.urlparse
+    urlsplit = parse.urlsplit
+    urlunsplit = parse.urlunsplit
+    SplitResult = parse.SplitResult
+
+    urlopen = urllib2.urlopen
+    URLError = urllib2.URLError
+    pathname2url = urllib.pathname2url
diff --git a/oslo/messaging/transport.py b/oslo/messaging/transport.py
index e61c9c260..4ffefc91e 100644
--- a/oslo/messaging/transport.py
+++ b/oslo/messaging/transport.py
@@ -27,13 +27,11 @@ __all__ = [
     'set_transport_defaults',
 ]
 
-import urllib
-import urlparse
-
 from oslo.config import cfg
 from stevedore import driver
 
 from oslo.messaging import exceptions
+from oslo.messaging.openstack.common.py3kcompat import urlutils
 
 
 _transport_opts = [
@@ -285,9 +283,9 @@ class TransportURL(object):
             # Build the username and password portion of the transport URL
             if username is not None or password is not None:
                 if username is not None:
-                    netloc += urllib.quote(username, '')
+                    netloc += urlutils.quote(username, '')
                 if password is not None:
-                    netloc += ':%s' % urllib.quote(password, '')
+                    netloc += ':%s' % urlutils.quote(password, '')
                 netloc += '@'
 
             # Build the network location portion of the transport URL
@@ -305,7 +303,7 @@ class TransportURL(object):
         url = '%s://%s/' % (self.transport, ','.join(netlocs))
 
         if self.virtual_host:
-            url += urllib.quote(self.virtual_host)
+            url += urlutils.quote(self.virtual_host)
 
         return url
 
@@ -358,7 +356,7 @@ class TransportURL(object):
         if not isinstance(url, basestring):
             raise InvalidTransportURL(url, 'Wrong URL type')
 
-        url = urlparse.urlparse(url)
+        url = urlutils.urlparse(url)
 
         # Make sure there's not a query string; that could identify
         # requirements we can't comply with (e.g., ssl), so reject it if
diff --git a/tests/test_transport.py b/tests/test_transport.py
index f16f36faf..095319468 100644
--- a/tests/test_transport.py
+++ b/tests/test_transport.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import itertools
-
 import fixtures
 import mox
 from oslo.config import cfg
@@ -231,7 +229,7 @@ class _SetDefaultsFixture(fixtures.Fixture):
         def first(seq, default=None, key=None):
             if key is None:
                 key = bool
-            return next(itertools.ifilter(key, seq), default)
+            return next(six.moves.filter(key, seq), default)
 
         def default(opts, name):
             return first(opts, key=lambda o: o.name == name).default