diff --git a/oslo/messaging/_drivers/impl_fake.py b/oslo/messaging/_drivers/impl_fake.py
index 96b4e5b8e..db78d8add 100644
--- a/oslo/messaging/_drivers/impl_fake.py
+++ b/oslo/messaging/_drivers/impl_fake.py
@@ -22,7 +22,7 @@ import time
 
 from oslo import messaging
 from oslo.messaging._drivers import base
-from oslo.messaging import _utils as utils
+from oslo.messaging import _urls as urls
 
 
 class InvalidTarget(base.TransportDriverError, ValueError):
@@ -102,7 +102,7 @@ class FakeDriver(base.BaseDriver):
     def __init__(self, conf, url=None, default_exchange=None):
         super(FakeDriver, self).__init__(conf, url, default_exchange)
 
-        self._default_exchange = utils.exchange_from_url(url, default_exchange)
+        self._default_exchange = urls.exchange_from_url(url, default_exchange)
 
         self._exchanges_lock = threading.Lock()
         self._exchanges = {}
diff --git a/oslo/messaging/_urls.py b/oslo/messaging/_urls.py
new file mode 100644
index 000000000..7b8f6ee77
--- /dev/null
+++ b/oslo/messaging/_urls.py
@@ -0,0 +1,139 @@
+
+# Copyright 2013 Red Hat, Inc.
+#
+#    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.
+
+import urlparse
+
+
+def parse_url(url, default_exchange=None):
+    """Parse an url.
+
+    Assuming a URL takes the form of:
+
+        transport://user:pass@host1:port[,hostN:portN]/exchange[?opt=val]
+
+    then parse the URL and return a dictionary with the following structure:
+
+        {
+            'exchange': 'exchange'
+            'transport': 'transport',
+            'hosts': [{'username': 'username',
+                       'password': 'password'
+                       'host': 'host1:port1'},
+                       ...],
+            'parameters': {'option': 'value'}
+        }
+
+    Netloc is parsed following the sequence bellow:
+
+    * It is first splitted by ',' in order to support multiple hosts
+    * The last parsed username and password will be propagated to the rest
+    of hotsts specified:
+
+      user:passwd@host1:port1,host2:port2
+
+      [
+       {"username": "user", "password": "passwd", "host": "host1:port1"},
+       {"username": "user", "password": "passwd", "host": "host2:port2"}
+      ]
+
+    * In order to avoid the above propagation, it is possible to alter the
+    order in which the hosts are specified or specify a set of fake credentials
+    using ",:@host2:port2"
+
+
+      user:passwd@host1:port1,:@host2:port2
+
+      [
+       {"username": "user", "password": "passwd", "host": "host1:port1"},
+       {"username": "", "password": "", "host": "host2:port2"}
+      ]
+
+    :param url: The URL to parse
+    :type url: str
+    :param default_exchange: what to return if no exchange found in URL
+    :type default_exchange: str
+    :returns: A dictionary with the parsed data
+    """
+
+    # NOTE(flaper87): Not PY3K compliant
+    if not isinstance(url, basestring):
+        raise TypeError("Wrong URL type")
+
+    url = urlparse.urlparse(url)
+
+    parsed = dict(transport=url.scheme)
+
+    # NOTE(flaper87): Set the exchange.
+    # if it is / or None then use the
+    # default one.
+    exchange = default_exchange
+    if url.path and url.path != "/":
+        exchange = url.path[1:].split("/")[0]
+    parsed["exchange"] = exchange
+
+    # NOTE(flaper87): Parse netloc.
+    hosts = []
+    username = password = ''
+    for host in url.netloc.split(","):
+        if not host:
+            continue
+
+        if "@" in host:
+            creds, host = host.split("@")
+            username, password = creds.split(":")
+
+        hosts.append({
+            "host": host,
+            "username": username,
+            "password": password,
+        })
+
+    parsed["hosts"] = hosts
+
+    parameters = {}
+    if url.query:
+        # NOTE(flaper87): This returns a dict with
+        # key -> [value], those values need to be
+        # normalized
+        parameters = urlparse.parse_qs(url.query)
+    parsed['parameters'] = parameters
+
+    return parsed
+
+
+def exchange_from_url(url, default_exchange=None):
+    """Parse an exchange name from a URL.
+
+    Assuming a URL takes the form of:
+
+      transport:///myexchange
+
+    then parse the URL and return the exchange name.
+
+    :param url: the URL to parse
+    :type url: str
+    :param default_exchange: what to return if no exchange found in URL
+    :type default_exchange: str
+    """
+    if not url:
+        return default_exchange
+
+    url = urlparse.urlparse(url)
+    if not url.path.startswith('/'):
+        return default_exchange
+
+    parts = url.path[1:].split('/')
+
+    return parts[0] if parts[0] else default_exchange
diff --git a/oslo/messaging/_utils.py b/oslo/messaging/_utils.py
index d3850b4e2..fcbfd1f1c 100644
--- a/oslo/messaging/_utils.py
+++ b/oslo/messaging/_utils.py
@@ -1,7 +1,4 @@
 
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
 # Copyright 2013 Red Hat, Inc.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -16,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urlparse
-
 
 def version_is_compatible(imp_version, version):
     """Determine whether versions are compatible.
@@ -32,126 +27,3 @@ def version_is_compatible(imp_version, version):
     if int(version_parts[1]) > int(imp_version_parts[1]):  # Minor
         return False
     return True
-
-
-def parse_url(url, default_exchange=None):
-    """Parse an url.
-
-    Assuming a URL takes the form of:
-
-        transport://user:pass@host1:port[,hostN:portN]/exchange[?opt=val]
-
-    then parse the URL and return a dictionary with the following structure:
-
-        {
-            'exchange': 'exchange'
-            'transport': 'transport',
-            'hosts': [{'username': 'username',
-                       'password': 'password'
-                       'host': 'host1:port1'},
-                       ...],
-            'parameters': {'option': 'value'}
-        }
-
-    Netloc is parsed following the sequence bellow:
-
-    * It is first splitted by ',' in order to support multiple hosts
-    * The last parsed username and password will be propagated to the rest
-    of hotsts specified:
-
-      user:passwd@host1:port1,host2:port2
-
-      [
-       {"username": "user", "password": "passwd", "host": "host1:port1"},
-       {"username": "user", "password": "passwd", "host": "host2:port2"}
-      ]
-
-    * In order to avoid the above propagation, it is possible to alter the
-    order in which the hosts are specified or specify a set of fake credentials
-    using ",:@host2:port2"
-
-
-      user:passwd@host1:port1,:@host2:port2
-
-      [
-       {"username": "user", "password": "passwd", "host": "host1:port1"},
-       {"username": "", "password": "", "host": "host2:port2"}
-      ]
-
-    :param url: The URL to parse
-    :type url: str
-    :param default_exchange: what to return if no exchange found in URL
-    :type default_exchange: str
-    :returns: A dictionary with the parsed data
-    """
-
-    # NOTE(flaper87): Not PY3K compliant
-    if not isinstance(url, basestring):
-        raise TypeError("Wrong URL type")
-
-    url = urlparse.urlparse(url)
-
-    parsed = dict(transport=url.scheme)
-
-    # NOTE(flaper87): Set the exchange.
-    # if it is / or None then use the
-    # default one.
-    exchange = default_exchange
-    if url.path and url.path != "/":
-        exchange = url.path[1:].split("/")[0]
-    parsed["exchange"] = exchange
-
-    # NOTE(flaper87): Parse netloc.
-    hosts = []
-    username = password = ''
-    for host in url.netloc.split(","):
-        if not host:
-            continue
-
-        if "@" in host:
-            creds, host = host.split("@")
-            username, password = creds.split(":")
-
-        hosts.append({
-            "host": host,
-            "username": username,
-            "password": password,
-        })
-
-    parsed["hosts"] = hosts
-
-    parameters = {}
-    if url.query:
-        # NOTE(flaper87): This returns a dict with
-        # key -> [value], those values need to be
-        # normalized
-        parameters = urlparse.parse_qs(url.query)
-    parsed['parameters'] = parameters
-
-    return parsed
-
-
-def exchange_from_url(url, default_exchange=None):
-    """Parse an exchange name from a URL.
-
-    Assuming a URL takes the form of:
-
-      transport:///myexchange
-
-    then parse the URL and return the exchange name.
-
-    :param url: the URL to parse
-    :type url: str
-    :param default_exchange: what to return if no exchange found in URL
-    :type default_exchange: str
-    """
-    if not url:
-        return default_exchange
-
-    url = urlparse.urlparse(url)
-    if not url.path.startswith('/'):
-        return default_exchange
-
-    parts = url.path[1:].split('/')
-
-    return parts[0] if parts[0] else default_exchange