libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject [1/3] Refactor OpenStack identity (auth) code and classes, make it more flexible, re-usable and maintainableL
Date Wed, 13 Aug 2014 11:45:58 GMT
Repository: libcloud
Updated Branches:
  refs/heads/trunk 529a9cf59 -> 30bc00944


http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/common/test_openstack_identity.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_openstack_identity.py b/libcloud/test/common/test_openstack_identity.py
new file mode 100644
index 0000000..0353bc1
--- /dev/null
+++ b/libcloud/test/common/test_openstack_identity.py
@@ -0,0 +1,504 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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 sys
+import unittest
+import datetime
+
+try:
+    import simplejson as json
+except ImportError:
+    import json
+
+from mock import Mock
+
+from libcloud.utils.py3 import httplib
+from libcloud.common.openstack import OpenStackBaseConnection
+from libcloud.common.openstack import AUTH_TOKEN_EXPIRES_GRACE_SECONDS
+from libcloud.common.openstack_identity import get_class_for_auth_version
+from libcloud.common.openstack_identity import OpenStackIdentity_2_0_Connection
+from libcloud.common.openstack_identity import OpenStackServiceCatalog
+from libcloud.common.openstack_identity import OpenStackIdentity_3_0_Connection
+from libcloud.compute.drivers.openstack import OpenStack_1_0_NodeDriver
+
+from libcloud.test import MockHttp
+from libcloud.test.secrets import OPENSTACK_PARAMS
+from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.test.compute.test_openstack import OpenStackMockHttp
+from libcloud.test.compute.test_openstack import OpenStack_2_0_MockHttp
+
+
+class OpenStackIdentityConnectionTestCase(unittest.TestCase):
+    def setUp(self):
+        OpenStackBaseConnection.auth_url = None
+        OpenStackBaseConnection.conn_classes = (OpenStackMockHttp,
+                                                OpenStackMockHttp)
+
+    def test_auth_url_is_correctly_assembled(self):
+        tuples = [
+            ('1.0', OpenStackMockHttp),
+            ('1.1', OpenStackMockHttp),
+            ('2.0', OpenStack_2_0_MockHttp),
+            ('2.0_apikey', OpenStack_2_0_MockHttp),
+            ('2.0_password', OpenStack_2_0_MockHttp)
+        ]
+
+        APPEND = 0
+        NOTAPPEND = 1
+
+        auth_urls = [
+            ('https://auth.api.example.com', APPEND, ''),
+            ('https://auth.api.example.com/', NOTAPPEND, '/'),
+            ('https://auth.api.example.com/foo/bar', NOTAPPEND, '/foo/bar'),
+            ('https://auth.api.example.com/foo/bar/', NOTAPPEND, '/foo/bar/')
+        ]
+
+        actions = {
+            '1.0': '/v1.0',
+            '1.1': '/v1.1/auth',
+            '2.0': '/v2.0/tokens',
+            '2.0_apikey': '/v2.0/tokens',
+            '2.0_password': '/v2.0/tokens'
+        }
+
+        user_id = OPENSTACK_PARAMS[0]
+        key = OPENSTACK_PARAMS[1]
+
+        for (auth_version, mock_http_class) in tuples:
+            for (url, should_append_default_path, expected_path) in auth_urls:
+                connection = \
+                    self._get_mock_connection(mock_http_class=mock_http_class,
+                                              auth_url=url)
+
+                auth_url = connection.auth_url
+                cls = get_class_for_auth_version(auth_version=auth_version)
+                osa = cls(auth_url=auth_url,
+                          user_id=user_id,
+                          key=key,
+                          parent_conn=connection)
+
+                try:
+                    osa = osa.authenticate()
+                except:
+                    pass
+
+                if (should_append_default_path == APPEND):
+                    expected_path = actions[auth_version]
+
+                self.assertEqual(osa.action, expected_path)
+
+    def test_basic_authentication(self):
+        tuples = [
+            ('1.0', OpenStackMockHttp),
+            ('1.1', OpenStackMockHttp),
+            ('2.0', OpenStack_2_0_MockHttp),
+            ('2.0_apikey', OpenStack_2_0_MockHttp),
+            ('2.0_password', OpenStack_2_0_MockHttp)
+        ]
+
+        user_id = OPENSTACK_PARAMS[0]
+        key = OPENSTACK_PARAMS[1]
+
+        for (auth_version, mock_http_class) in tuples:
+            connection = \
+                self._get_mock_connection(mock_http_class=mock_http_class)
+            auth_url = connection.auth_url
+
+            cls = get_class_for_auth_version(auth_version=auth_version)
+            osa = cls(auth_url=auth_url, user_id=user_id, key=key,
+                      parent_conn=connection)
+
+            self.assertEqual(osa.urls, {})
+            self.assertEqual(osa.auth_token, None)
+            self.assertEqual(osa.auth_user_info, None)
+            osa = osa.authenticate()
+
+            self.assertTrue(len(osa.urls) >= 1)
+            self.assertTrue(osa.auth_token is not None)
+
+            if auth_version in ['1.1', '2.0', '2.0_apikey', '2.0_password']:
+                self.assertTrue(osa.auth_token_expires is not None)
+
+            if auth_version in ['2.0', '2.0_apikey', '2.0_password']:
+                self.assertTrue(osa.auth_user_info is not None)
+
+    def test_token_expiration_and_force_reauthentication(self):
+        user_id = OPENSTACK_PARAMS[0]
+        key = OPENSTACK_PARAMS[1]
+
+        connection = self._get_mock_connection(OpenStack_2_0_MockHttp)
+        auth_url = connection.auth_url
+
+        yesterday = datetime.datetime.today() - datetime.timedelta(1)
+        tomorrow = datetime.datetime.today() + datetime.timedelta(1)
+
+        osa = OpenStackIdentity_2_0_Connection(auth_url=auth_url,
+                                               user_id=user_id,
+                                               key=key,
+                                               parent_conn=connection)
+
+        mocked_auth_method = Mock(wraps=osa._authenticate_2_0_with_body)
+        osa._authenticate_2_0_with_body = mocked_auth_method
+
+        # Force re-auth, expired token
+        osa.auth_token = None
+        osa.auth_token_expires = yesterday
+        count = 5
+
+        for i in range(0, count):
+            osa.authenticate(force=True)
+
+        self.assertEqual(mocked_auth_method.call_count, count)
+
+        # No force reauth, expired token
+        osa.auth_token = None
+        osa.auth_token_expires = yesterday
+
+        mocked_auth_method.call_count = 0
+        self.assertEqual(mocked_auth_method.call_count, 0)
+
+        for i in range(0, count):
+            osa.authenticate(force=False)
+
+        self.assertEqual(mocked_auth_method.call_count, 1)
+
+        # No force reauth, valid / non-expired token
+        osa.auth_token = None
+
+        mocked_auth_method.call_count = 0
+        self.assertEqual(mocked_auth_method.call_count, 0)
+
+        for i in range(0, count):
+            osa.authenticate(force=False)
+
+            if i == 0:
+                osa.auth_token_expires = tomorrow
+
+        self.assertEqual(mocked_auth_method.call_count, 1)
+
+        # No force reauth, valid / non-expired token which is about to expire in
+        # less than AUTH_TOKEN_EXPIRES_GRACE_SECONDS
+        soon = datetime.datetime.utcnow() + \
+            datetime.timedelta(seconds=AUTH_TOKEN_EXPIRES_GRACE_SECONDS - 1)
+        osa.auth_token = None
+
+        mocked_auth_method.call_count = 0
+        self.assertEqual(mocked_auth_method.call_count, 0)
+
+        for i in range(0, count):
+            if i == 0:
+                osa.auth_token_expires = soon
+
+            osa.authenticate(force=False)
+
+        self.assertEqual(mocked_auth_method.call_count, 1)
+
+    def _get_mock_connection(self, mock_http_class, auth_url=None):
+        OpenStackBaseConnection.conn_classes = (mock_http_class,
+                                                mock_http_class)
+
+        if auth_url is None:
+            auth_url = "https://auth.api.example.com"
+
+        OpenStackBaseConnection.auth_url = auth_url
+        connection = OpenStackBaseConnection(*OPENSTACK_PARAMS)
+
+        connection._ex_force_base_url = "https://www.foo.com"
+        connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS)
+
+        return connection
+
+
+class OpenStackIdentity_3_0_ConnectionTests(unittest.TestCase):
+    def setUp(self):
+        mock_cls = OpenStackIdentity_3_0_MockHttp
+        OpenStackIdentity_3_0_Connection.conn_classes = (mock_cls, mock_cls)
+
+        self.auth_instance = OpenStackIdentity_3_0_Connection(auth_url='http://none',
+                                                              user_id='test',
+                                                              key='test')
+        self.auth_instance.auth_token = 'mock'
+
+    def test_list_domains(self):
+        domains = self.auth_instance.list_domains()
+        self.assertEqual(len(domains), 1)
+        self.assertEqual(domains[0].id, 'default')
+        self.assertEqual(domains[0].name, 'Default')
+        self.assertTrue(domains[0].enabled)
+
+    def test_list_projects(self):
+        projects = self.auth_instance.list_projects()
+        self.assertEqual(len(projects), 4)
+        self.assertEqual(projects[0].id, 'a')
+        self.assertEqual(projects[0].domain_id, 'default')
+        self.assertTrue(projects[0].enabled)
+        self.assertEqual(projects[0].description, 'Test project')
+
+    def test_list_users(self):
+        users = self.auth_instance.list_users()
+        self.assertEqual(len(users), 12)
+        self.assertEqual(users[0].id, 'a')
+        self.assertEqual(users[0].domain_id, 'default')
+        self.assertEqual(users[0].enabled, True)
+        self.assertEqual(users[0].email, 'openstack-test@localhost')
+
+    def test_list_roles(self):
+        roles = self.auth_instance.list_roles()
+        self.assertEqual(len(roles), 2)
+        self.assertEqual(roles[1].id, 'b')
+        self.assertEqual(roles[1].name, 'admin')
+
+    def test_list_user_projects(self):
+        user = self.auth_instance.list_users()[0]
+        projects = self.auth_instance.list_user_projects(user=user)
+        self.assertEqual(len(projects), 0)
+
+    def test_list_user_domain_roles(self):
+        user = self.auth_instance.list_users()[0]
+        domain = self.auth_instance.list_domains()[0]
+        roles = self.auth_instance.list_user_domain_roles(domain=domain,
+                                                          user=user)
+        self.assertEqual(len(roles), 1)
+        self.assertEqual(roles[0].name, 'admin')
+
+    def test_get_domain(self):
+        domain = self.auth_instance.get_domain(domain_id='default')
+        self.assertEqual(domain.name, 'Default')
+
+    def test_create_user(self):
+        user = self.auth_instance.create_user(email='test2@localhost', password='test1',
+                                              name='test2', domain_id='default')
+
+        self.assertEqual(user.id, 'c')
+        self.assertEqual(user.name, 'test2')
+
+    def test_grant_role_to_user(self):
+        domain = self.auth_instance.list_domains()[0]
+        role = self.auth_instance.list_roles()[0]
+        user = self.auth_instance.list_users()[0]
+
+        result = self.auth_instance.grant_role_to_user(domain=domain,
+                                                       role=role,
+                                                       user=user)
+        self.assertTrue(result)
+
+    def test_revoke_role_from_user(self):
+        domain = self.auth_instance.list_domains()[0]
+        role = self.auth_instance.list_roles()[0]
+        user = self.auth_instance.list_users()[0]
+
+        result = self.auth_instance.revoke_role_from_user(domain=domain,
+                                                          role=role,
+                                                          user=user)
+        self.assertTrue(result)
+
+
+class OpenStackServiceCatalogTestCase(unittest.TestCase):
+    fixtures = ComputeFileFixtures('openstack')
+
+    def test_parsing_auth_v1_1(self):
+        data = self.fixtures.load('_v1_1__auth.json')
+        data = json.loads(data)
+        service_catalog = data['auth']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='1.0')
+        entries = catalog.get_entries()
+        self.assertEqual(len(entries), 3)
+
+        entry = [e for e in entries if e.service_type == 'cloudFilesCDN'][0]
+        self.assertEqual(entry.service_type, 'cloudFilesCDN')
+        self.assertEqual(entry.service_name, None)
+        self.assertEqual(len(entry.endpoints), 2)
+        self.assertEqual(entry.endpoints[0].region, 'ORD')
+        self.assertEqual(entry.endpoints[0].url,
+                         'https://cdn2.clouddrive.com/v1/MossoCloudFS')
+        self.assertEqual(entry.endpoints[0].endpoint_type, 'external')
+        self.assertEqual(entry.endpoints[1].region, 'LON')
+        self.assertEqual(entry.endpoints[1].endpoint_type, 'external')
+
+    def test_parsing_auth_v2(self):
+        data = self.fixtures.load('_v2_0__auth.json')
+        data = json.loads(data)
+        service_catalog = data['access']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='2.0')
+        entries = catalog.get_entries()
+        self.assertEqual(len(entries), 6)
+
+        entry = [e for e in entries if e.service_name == 'cloudServers'][0]
+        self.assertEqual(entry.service_type, 'compute')
+        self.assertEqual(entry.service_name, 'cloudServers')
+        self.assertEqual(len(entry.endpoints), 1)
+        self.assertEqual(entry.endpoints[0].region, None)
+        self.assertEqual(entry.endpoints[0].url,
+                         'https://servers.api.rackspacecloud.com/v1.0/1337')
+        self.assertEqual(entry.endpoints[0].endpoint_type, 'external')
+
+    def test_parsing_auth_v3(self):
+        data = self.fixtures.load('_v3__auth.json')
+        data = json.loads(data)
+        service_catalog = data['token']['catalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='3.x')
+        entries = catalog.get_entries()
+        self.assertEqual(len(entries), 6)
+        entry = [e for e in entries if e.service_type == 'volume'][0]
+        self.assertEqual(entry.service_type, 'volume')
+        self.assertEqual(entry.service_name, None)
+        self.assertEqual(len(entry.endpoints), 3)
+        self.assertEqual(entry.endpoints[0].region, 'regionOne')
+        self.assertEqual(entry.endpoints[0].endpoint_type, 'external')
+        self.assertEqual(entry.endpoints[1].region, 'regionOne')
+        self.assertEqual(entry.endpoints[1].endpoint_type, 'admin')
+        self.assertEqual(entry.endpoints[2].region, 'regionOne')
+        self.assertEqual(entry.endpoints[2].endpoint_type, 'internal')
+
+    def test_get_public_urls(self):
+        data = self.fixtures.load('_v2_0__auth.json')
+        data = json.loads(data)
+        service_catalog = data['access']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='2.0')
+
+        public_urls = catalog.get_public_urls(service_type='object-store')
+        expected_urls = ['https://storage101.lon1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111',
+                         'https://storage101.ord1.clouddrive.com/v1/MossoCloudFS_11111-111111111-1111111111-1111111']
+        self.assertEqual(public_urls, expected_urls)
+
+    def test_get_regions(self):
+        data = self.fixtures.load('_v2_0__auth.json')
+        data = json.loads(data)
+        service_catalog = data['access']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='2.0')
+
+        regions = catalog.get_regions(service_type='object-store')
+        self.assertEqual(regions, ['LON', 'ORD'])
+
+        regions = catalog.get_regions(service_type='invalid')
+        self.assertEqual(regions, [])
+
+    def test_get_service_types(self):
+        data = self.fixtures.load('_v2_0__auth.json')
+        data = json.loads(data)
+        service_catalog = data['access']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='2.0')
+        service_types = catalog.get_service_types()
+        self.assertEqual(service_types, ['compute', 'object-store',
+                                         'rax:object-cdn'])
+
+        service_types = catalog.get_service_types(region='ORD')
+        self.assertEqual(service_types, ['rax:object-cdn'])
+
+    def test_get_service_names(self):
+        data = self.fixtures.load('_v2_0__auth.json')
+        data = json.loads(data)
+        service_catalog = data['access']['serviceCatalog']
+
+        catalog = OpenStackServiceCatalog(service_catalog=service_catalog,
+                                          auth_version='2.0')
+
+        service_names = catalog.get_service_names()
+        self.assertEqual(service_names, ['cloudFiles', 'cloudFilesCDN',
+                                         'cloudServers',
+                                         'cloudServersOpenStack',
+                                         'cloudServersPreprod',
+                                         'nova'])
+
+        service_names = catalog.get_service_names(service_type='compute')
+        self.assertEqual(service_names, ['cloudServers',
+                                         'cloudServersOpenStack',
+                                         'cloudServersPreprod',
+                                         'nova'])
+
+
+class OpenStackIdentity_3_0_MockHttp(MockHttp):
+    fixtures = ComputeFileFixtures('openstack_identity')
+    json_content_headers = {'content-type': 'application/json; charset=UTF-8'}
+
+    def _v3_domains(self, method, url, body, headers):
+        if method == 'GET':
+            body = self.fixtures.load('v3_domains.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+    def _v3_projects(self, method, url, body, headers):
+        if method == 'GET':
+            body = self.fixtures.load('v3_projects.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+    def _v3_users(self, method, url, body, headers):
+        if method == 'GET':
+            # list users
+            body = self.fixtures.load('v3_users.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        elif method == 'POST':
+            # create user
+            body = self.fixtures.load('v3_create_user.json')
+            return (httplib.CREATED, body, self.json_content_headers,
+                    httplib.responses[httplib.CREATED])
+        raise NotImplementedError()
+
+    def _v3_roles(self, method, url, body, headers):
+        if method == 'GET':
+            body = self.fixtures.load('v3_roles.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+    def _v3_domains_default_users_a_roles_a(self, method, url, body, headers):
+        if method == 'PUT':
+            # grant role
+            body = ''
+            return (httplib.NO_CONTENT, body, self.json_content_headers,
+                    httplib.responses[httplib.NO_CONTENT])
+        elif method == 'DELETE':
+            # revoke role
+            body = ''
+            return (httplib.NO_CONTENT, body, self.json_content_headers,
+                    httplib.responses[httplib.NO_CONTENT])
+        raise NotImplementedError()
+
+    def _v3_domains_default(self, method, url, body, headers):
+        if method == 'GET':
+            # get domain
+            body = self.fixtures.load('v3_domains_default.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+    def _v3_users_a_projects(self, method, url, body, headers):
+        if method == 'GET':
+            # get user projects
+            body = self.fixtures.load('v3_users_a_projects.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+    def _v3_domains_default_users_a_roles(self, method, url, body, headers):
+        if method == 'GET':
+            # get user domain roles
+            body = self.fixtures.load('v3_domains_default_users_a_roles.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+        raise NotImplementedError()
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack/_v3__auth.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack/_v3__auth.json b/libcloud/test/compute/fixtures/openstack/_v3__auth.json
new file mode 100644
index 0000000..de78703
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack/_v3__auth.json
@@ -0,0 +1,182 @@
+{
+    "token": {
+        "methods": [
+            "password"
+        ],
+        "roles": [
+            {
+                "id": "9fe2ff9ee4384b1894a90878d3e92bab",
+                "name": "_member_"
+            },
+            {
+                "id": "b258b68172db4403892320f784c4d503",
+                "name": "admin"
+            }
+        ],
+        "expires_at": "2014-08-10T19:15:57.096078Z",
+        "project": {
+            "domain": {
+                "id": "default",
+                "name": "Default"
+            },
+            "id": "9c4693dce56b493b9b83197d900f7fba",
+            "name": "admin"
+        },
+        "catalog": [
+            {
+                "endpoints": [
+                    {
+                        "url": "http://controller:8774/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "b3bfb29033ff4add9c97e523e1022794"
+                    },
+                    {
+                        "url": "http://192.168.18.100:8774/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "b52ee215ded7473f94a46512cb94dbf1"
+                    },
+                    {
+                        "url": "http://192.168.18.100:8774/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "ca8a6e39b9334300bf036c0c4226a173"
+                    }
+                ],
+                "type": "compute",
+                "id": "03f123b2253e4852a86b994f86489c0a"
+            },
+            {
+                "endpoints": [
+                    {
+                        "url": "http://192.168.18.100:8776/v1/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "20bf617f334c4bcf82746820f5006599"
+                    },
+                    {
+                        "url": "http://192.168.18.100:8776/v1/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "2da639c26463424fa9775e0bf4e9f29e"
+                    },
+                    {
+                        "url": "http://controller:8776/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "d568ed6f8c5a4649a6e68b7bcb86694b"
+                    }
+                ],
+                "type": "volume",
+                "id": "47f77ba8f3864a03b66024e910ad7247"
+            },
+            {
+                "endpoints": [
+                    {
+                        "url": "http://192.168.18.100:9696",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "720303f92f81404aa80caa32cd9c7d23"
+                    },
+                    {
+                        "url": "http://192.168.18.100:9696",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "8823b9edba354bb6bdc944a6b3bb5404"
+                    },
+                    {
+                        "url": "http://controller:9696",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "c2a522538037492dbec2173f271ecb32"
+                    }
+                ],
+                "type": "network",
+                "id": "9bd61e09d372427f81eca9328f33c510"
+            },
+            {
+                "endpoints": [
+                    {
+                        "url": "http://controller:5000/v2.0",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "802622da0a874cac8fe2ec7a02d87c44"
+                    },
+                    {
+                        "url": "http://192.168.18.100:35357/v2.0",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "8a4eed85ddc748b18cc2b92e64291eb5"
+                    },
+                    {
+                        "url": "http://192.168.18.100:5000/v2.0",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "9ef69c1600a944b9904f34efb6dc67eb"
+                    }
+                ],
+                "type": "identity",
+                "id": "aef833a14f4240d0bbb699f0154add8e"
+            },
+            {
+                "endpoints": [
+                    {
+                        "url": "http://192.168.18.100:9292",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "1aa84aebd3e2467e898e3c18428e3feb"
+                    },
+                    {
+                        "url": "http://192.168.18.100:9292",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "3f6aa4ffd0ec47d2862eee1648993bef"
+                    },
+                    {
+                        "url": "http://192.168.200.1:9292",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "9f66f90af36949479a6365680afabe12"
+                    }
+                ],
+                "type": "image",
+                "id": "c0be10ea61e240f99567f328b9adf3d6"
+            },
+            {
+                "endpoints": [
+                    {
+                        "url": "http://192.168.18.100:8776/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "public",
+                        "id": "6c6b0990ccf84f1890e404fddad7b6e5"
+                    },
+                    {
+                        "url": "http://192.168.18.100:8776/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "admin",
+                        "id": "ab0f0bd770494d4399036867935c52ea"
+                    },
+                    {
+                        "url": "http://controller:8776/v2/9c4693dce56b493b9b83197d900f7fba",
+                        "region": "regionOne",
+                        "interface": "internal",
+                        "id": "fc7c82deda034e52a544da7d00cd28de"
+                    }
+                ],
+                "type": "volumev2",
+                "id": "e097b64d701e4ce29f2a69eed4e69856"
+            }
+        ],
+        "extras": {},
+        "user": {
+            "domain": {
+                "id": "default",
+                "name": "Default"
+            },
+            "id": "55fba80f022b4855acfc700ae13b2b24",
+            "name": "admin"
+        },
+        "issued_at": "2014-08-10T18:15:57.096107Z"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_create_user.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_create_user.json b/libcloud/test/compute/fixtures/openstack_identity/v3_create_user.json
new file mode 100644
index 0000000..82445dc
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_create_user.json
@@ -0,0 +1,12 @@
+{
+    "user": {
+        "name": "test2",
+        "links": {
+            "self": "http://192.168.18.100:5000/v3/users/c"
+        },
+        "domain_id": "default",
+        "enabled": true,
+        "email": "test2@localhost",
+        "id": "c"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_domains.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_domains.json b/libcloud/test/compute/fixtures/openstack_identity/v3_domains.json
new file mode 100644
index 0000000..7813acf
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_domains.json
@@ -0,0 +1,18 @@
+{
+    "domains": [
+        {
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/domains/default"
+            },
+            "enabled": true,
+            "description": "Owns users and tenants (i.e. projects) available on Identity API v2.",
+            "name": "Default",
+            "id": "default"
+        }
+    ],
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/domains",
+        "previous": null,
+        "next": null
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default.json b/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default.json
new file mode 100644
index 0000000..f00230f
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default.json
@@ -0,0 +1,11 @@
+{
+    "domain": {
+        "links": {
+            "self": "http://192.168.18.100:5000/v3/domains/default"
+        },
+        "enabled": true,
+        "description": "Owns users and tenants (i.e. projects) available on Identity API v2.",
+        "name": "Default",
+        "id": "default"
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default_users_a_roles.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default_users_a_roles.json b/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default_users_a_roles.json
new file mode 100644
index 0000000..0312072
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_domains_default_users_a_roles.json
@@ -0,0 +1,16 @@
+{
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/domains/default/users/a/roles",
+        "previous": null,
+        "next": null
+    },
+    "roles": [
+        {
+            "id": "d",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/roles/d"
+            },
+            "name": "admin"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_projects.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_projects.json b/libcloud/test/compute/fixtures/openstack_identity/v3_projects.json
new file mode 100644
index 0000000..16acbce
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_projects.json
@@ -0,0 +1,49 @@
+{
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/projects",
+        "previous": null,
+        "next": null
+    },
+    "projects": [
+        {
+            "description": "Test project",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/projects/a"
+            },
+            "enabled": true,
+            "id": "a",
+            "domain_id": "default",
+            "name": "divvy"
+        },
+        {
+            "description": "Admin Tenant",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/projects/b"
+            },
+            "enabled": true,
+            "id": "b",
+            "domain_id": "default",
+            "name": "admin"
+        },
+        {
+            "description": "Initial tenant",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/projects/c"
+            },
+            "enabled": true,
+            "id": "c",
+            "domain_id": "default",
+            "name": "first-tenant"
+        },
+        {
+            "description": "Service Tenant",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/projects/d"
+            },
+            "enabled": true,
+            "id": "d",
+            "domain_id": "default",
+            "name": "service"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_roles.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_roles.json b/libcloud/test/compute/fixtures/openstack_identity/v3_roles.json
new file mode 100644
index 0000000..5785484
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_roles.json
@@ -0,0 +1,25 @@
+{
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/roles",
+        "previous": null,
+        "next": null
+    },
+    "roles": [
+        {
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/roles/a"
+            },
+            "enabled": "True",
+            "description": "Default role for project membership",
+            "name": "_member_",
+            "id": "a"
+        },
+        {
+            "id": "b",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/roles/b"
+            },
+            "name": "admin"
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_users.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_users.json b/libcloud/test/compute/fixtures/openstack_identity/v3_users.json
new file mode 100644
index 0000000..d4763ea
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_users.json
@@ -0,0 +1,131 @@
+{
+    "users": [
+        {
+            "name": "cloud",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/a"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "openstack-test@localhost",
+            "id": "a"
+        },
+        {
+            "name": "trove",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/1ec8cface8614a2786c99c87c7116f09"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "trove@localhost",
+            "id": "1ec8cface8614a2786c99c87c7116f09"
+        },
+        {
+            "domain_id": "default",
+            "name": "tomaz",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/458f20357227462e8a17355628984515"
+            },
+            "id": "458f20357227462e8a17355628984515",
+            "enabled": true,
+            "email": "tomaz@tomaz.me",
+            "default_project_id": "3130562cafe147f289bbb3b557f2e7ed"
+        },
+        {
+            "name": "admin",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/55fba80f022b4855acfc700ae13b2b24"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "openstack-test@localhost",
+            "id": "55fba80f022b4855acfc700ae13b2b24"
+        },
+        {
+            "name": "nova",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/679c69c6cfd049ebb3ad85734dfea61a"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "nova@localhost",
+            "id": "679c69c6cfd049ebb3ad85734dfea61a"
+        },
+        {
+            "name": "glance",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/6f10443170ad4daf81bff251944da9d7"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "glance@localhost",
+            "id": "6f10443170ad4daf81bff251944da9d7"
+        },
+        {
+            "name": "ceilometer",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/747cf6a2bf75453f847f307823e8eac9"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "ceilometer@localhost",
+            "id": "747cf6a2bf75453f847f307823e8eac9"
+        },
+        {
+            "name": "swift",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/a0081ee2f9674458bcd7731b6dcbf5f9"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "swift@localhost",
+            "id": "a0081ee2f9674458bcd7731b6dcbf5f9"
+        },
+        {
+            "domain_id": "default",
+            "name": "amann",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/aafb942e4c3d4fe1ba33088f3e7c5996"
+            },
+            "id": "aafb942e4c3d4fe1ba33088f3e7c5996",
+            "enabled": true,
+            "email": "andrew@divvycloud.com",
+            "default_project_id": "3130562cafe147f289bbb3b557f2e7ed"
+        },
+        {
+            "name": "heat",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/d16cad10e4f648e0bd9ab5a0359f6736"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "heat@localhost",
+            "id": "d16cad10e4f648e0bd9ab5a0359f6736"
+        },
+        {
+            "name": "cinder",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/f3a4590b0d66497894ee9a3d73c09a95"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "cinder@localhost",
+            "id": "f3a4590b0d66497894ee9a3d73c09a95"
+        },
+        {
+            "name": "neutron",
+            "links": {
+                "self": "http://192.168.18.100:5000/v3/users/fa9a7fedeb2844ff89e37d70a2519441"
+            },
+            "domain_id": "default",
+            "enabled": true,
+            "email": "neutron@localhost",
+            "id": "fa9a7fedeb2844ff89e37d70a2519441"
+        }
+    ],
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/users",
+        "previous": null,
+        "next": null
+    }
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/fixtures/openstack_identity/v3_users_a_projects.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_identity/v3_users_a_projects.json b/libcloud/test/compute/fixtures/openstack_identity/v3_users_a_projects.json
new file mode 100644
index 0000000..e117a8b
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_identity/v3_users_a_projects.json
@@ -0,0 +1,8 @@
+{
+    "links": {
+        "self": "http://192.168.18.100:5000/v3/users/a/projects",
+        "previous": null,
+        "next": null
+    },
+    "projects": []
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index 77a38e9..642b7a8 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -25,7 +25,7 @@ try:
 except ImportError:
     import json
 
-from mock import Mock
+from mock import Mock, patch
 
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import method_type
@@ -33,9 +33,6 @@ from libcloud.utils.py3 import u
 
 from libcloud.common.types import InvalidCredsError, MalformedResponseError, \
     LibcloudError
-from libcloud.common.openstack import OpenStackBaseConnection
-from libcloud.common.openstack import OpenStackAuthConnection
-from libcloud.common.openstack import AUTH_TOKEN_EXPIRES_GRACE_SECONDS
 from libcloud.compute.types import Provider, KeyPairDoesNotExistError
 from libcloud.compute.providers import get_driver
 from libcloud.compute.drivers.openstack import (
@@ -85,243 +82,6 @@ class OpenStack_1_0_ResponseTestCase(unittest.TestCase):
             body, RESPONSE_BODY, "Non-XML body should be returned as is")
 
 
-class OpenStackServiceCatalogTests(unittest.TestCase):
-    # TODO refactor and move into libcloud/test/common
-
-    def setUp(self):
-        OpenStackBaseConnection.conn_classes = (OpenStackMockHttp,
-                                                OpenStackMockHttp)
-
-        connection = OpenStackBaseConnection(*OPENSTACK_PARAMS)
-        connection.auth_url = "https://auth.api.example.com"
-        connection._ex_force_base_url = "https://www.foo.com"
-        connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS)
-
-        self.service_catalog = connection.get_service_catalog()
-        self.catalog = self.service_catalog.get_catalog()
-
-    def test_connection_get_service_catalog(self):
-        endpoints = self.service_catalog.get_endpoints('cloudFilesCDN', 'cloudFilesCDN')
-        public_urls = self.service_catalog.get_public_urls('cloudFilesCDN', 'cloudFilesCDN')
-
-        expected_urls = [
-            'https://cdn2.clouddrive.com/v1/MossoCloudFS',
-            'https://cdn2.clouddrive.com/v1/MossoCloudFS'
-        ]
-
-        self.assertTrue('cloudFilesCDN' in self.catalog)
-        self.assertEqual(len(endpoints), 2)
-        self.assertEqual(public_urls, expected_urls)
-
-    def test_get_regions(self):
-        regions = self.service_catalog.get_regions()
-        self.assertEqual(sorted(regions), ['LON', 'ORD'])
-
-    def test_get_service_types(self):
-        service_types = self.service_catalog.get_service_types()
-        self.assertEqual(sorted(service_types), ['compute', 'object-store',
-                                                 'rax:object-cdn'])
-
-        service_types = self.service_catalog.get_service_types(region='invalid')
-        self.assertEqual(sorted(service_types), [])
-
-    def test_get_service_names(self):
-        OpenStackBaseConnection.conn_classes = (OpenStack_2_0_MockHttp,
-                                                OpenStack_2_0_MockHttp)
-        OpenStackBaseConnection._auth_version = '2.0'
-
-        connection = OpenStackBaseConnection(*OPENSTACK_PARAMS)
-        connection.auth_url = "https://auth.api.example.com"
-        connection._ex_force_base_url = "https://www.foo.com"
-        connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS)
-
-        service_catalog = connection.get_service_catalog()
-
-        service_names = service_catalog.get_service_names(service_type='object-store')
-        self.assertEqual(service_names, ['cloudFiles'])
-
-
-class OpenStackAuthConnectionTests(unittest.TestCase):
-    # TODO refactor and move into libcloud/test/common
-
-    def setUp(self):
-        OpenStackBaseConnection.auth_url = None
-        OpenStackBaseConnection.conn_classes = (OpenStackMockHttp,
-                                                OpenStackMockHttp)
-
-    def test_auth_url_is_correctly_assembled(self):
-        tuples = [
-            ('1.0', OpenStackMockHttp),
-            ('1.1', OpenStackMockHttp),
-            ('2.0', OpenStack_2_0_MockHttp),
-            ('2.0_apikey', OpenStack_2_0_MockHttp),
-            ('2.0_password', OpenStack_2_0_MockHttp)
-        ]
-
-        APPEND = 0
-        NOTAPPEND = 1
-
-        auth_urls = [
-            ('https://auth.api.example.com', APPEND, ''),
-            ('https://auth.api.example.com/', NOTAPPEND, '/'),
-            ('https://auth.api.example.com/foo/bar', NOTAPPEND, '/foo/bar'),
-            ('https://auth.api.example.com/foo/bar/', NOTAPPEND, '/foo/bar/')
-        ]
-
-        actions = {
-            '1.0': '/v1.0',
-            '1.1': '/v1.1/auth',
-            '2.0': '/v2.0/tokens',
-            '2.0_apikey': '/v2.0/tokens',
-            '2.0_password': '/v2.0/tokens'
-        }
-
-        user_id = OPENSTACK_PARAMS[0]
-        key = OPENSTACK_PARAMS[1]
-
-        for (auth_version, mock_http_class) in tuples:
-            for (url, should_append_default_path, expected_path) in auth_urls:
-                connection = \
-                    self._get_mock_connection(mock_http_class=mock_http_class,
-                                              auth_url=url)
-
-                auth_url = connection.auth_url
-
-                osa = OpenStackAuthConnection(connection,
-                                              auth_url,
-                                              auth_version,
-                                              user_id, key)
-
-                try:
-                    osa = osa.authenticate()
-                except:
-                    pass
-
-                if (should_append_default_path == APPEND):
-                    expected_path = actions[auth_version]
-
-                self.assertEqual(osa.action, expected_path)
-
-    def test_basic_authentication(self):
-        tuples = [
-            ('1.0', OpenStackMockHttp),
-            ('1.1', OpenStackMockHttp),
-            ('2.0', OpenStack_2_0_MockHttp),
-            ('2.0_apikey', OpenStack_2_0_MockHttp),
-            ('2.0_password', OpenStack_2_0_MockHttp)
-        ]
-
-        user_id = OPENSTACK_PARAMS[0]
-        key = OPENSTACK_PARAMS[1]
-
-        for (auth_version, mock_http_class) in tuples:
-            connection = \
-                self._get_mock_connection(mock_http_class=mock_http_class)
-            auth_url = connection.auth_url
-
-            osa = OpenStackAuthConnection(connection, auth_url, auth_version,
-                                          user_id, key)
-
-            self.assertEqual(osa.urls, {})
-            self.assertEqual(osa.auth_token, None)
-            self.assertEqual(osa.auth_user_info, None)
-            osa = osa.authenticate()
-
-            self.assertTrue(len(osa.urls) >= 1)
-            self.assertTrue(osa.auth_token is not None)
-
-            if auth_version in ['1.1', '2.0', '2.0_apikey', '2.0_password']:
-                self.assertTrue(osa.auth_token_expires is not None)
-
-            if auth_version in ['2.0', '2.0_apikey', '2.0_password']:
-                self.assertTrue(osa.auth_user_info is not None)
-
-    def test_token_expiration_and_force_reauthentication(self):
-        user_id = OPENSTACK_PARAMS[0]
-        key = OPENSTACK_PARAMS[1]
-
-        connection = self._get_mock_connection(OpenStack_2_0_MockHttp)
-        auth_url = connection.auth_url
-        auth_version = '2.0'
-
-        yesterday = datetime.datetime.today() - datetime.timedelta(1)
-        tomorrow = datetime.datetime.today() + datetime.timedelta(1)
-
-        osa = OpenStackAuthConnection(connection, auth_url, auth_version,
-                                      user_id, key)
-
-        mocked_auth_method = Mock(wraps=osa.authenticate_2_0_with_body)
-        osa.authenticate_2_0_with_body = mocked_auth_method
-
-        # Force re-auth, expired token
-        osa.auth_token = None
-        osa.auth_token_expires = yesterday
-        count = 5
-
-        for i in range(0, count):
-            osa.authenticate(force=True)
-
-        self.assertEqual(mocked_auth_method.call_count, count)
-
-        # No force reauth, expired token
-        osa.auth_token = None
-        osa.auth_token_expires = yesterday
-
-        mocked_auth_method.call_count = 0
-        self.assertEqual(mocked_auth_method.call_count, 0)
-
-        for i in range(0, count):
-            osa.authenticate(force=False)
-
-        self.assertEqual(mocked_auth_method.call_count, 1)
-
-        # No force reauth, valid / non-expired token
-        osa.auth_token = None
-
-        mocked_auth_method.call_count = 0
-        self.assertEqual(mocked_auth_method.call_count, 0)
-
-        for i in range(0, count):
-            osa.authenticate(force=False)
-
-            if i == 0:
-                osa.auth_token_expires = tomorrow
-
-        self.assertEqual(mocked_auth_method.call_count, 1)
-
-        # No force reauth, valid / non-expired token which is about to expire in
-        # less than AUTH_TOKEN_EXPIRES_GRACE_SECONDS
-        soon = datetime.datetime.utcnow() + \
-            datetime.timedelta(seconds=AUTH_TOKEN_EXPIRES_GRACE_SECONDS - 1)
-        osa.auth_token = None
-
-        mocked_auth_method.call_count = 0
-        self.assertEqual(mocked_auth_method.call_count, 0)
-
-        for i in range(0, count):
-            if i == 0:
-                osa.auth_token_expires = soon
-
-            osa.authenticate(force=False)
-
-        self.assertEqual(mocked_auth_method.call_count, 1)
-
-    def _get_mock_connection(self, mock_http_class, auth_url=None):
-        OpenStackBaseConnection.conn_classes = (mock_http_class,
-                                                mock_http_class)
-
-        if auth_url is None:
-            auth_url = "https://auth.api.example.com"
-
-        OpenStackBaseConnection.auth_url = auth_url
-        connection = OpenStackBaseConnection(*OPENSTACK_PARAMS)
-
-        connection._ex_force_base_url = "https://www.foo.com"
-        connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS)
-
-        return connection
-
-
 class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin):
     should_list_locations = False
     should_list_volumes = False
@@ -356,7 +116,8 @@ class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin):
         self.driver.connection._populate_hosts_and_request_paths()
         clear_pricing_data()
 
-    def test_populate_hosts_and_requests_path(self):
+    @patch('libcloud.common.openstack.OpenStackServiceCatalog')
+    def test_populate_hosts_and_requests_path(self, _):
         tomorrow = datetime.datetime.today() + datetime.timedelta(1)
         cls = self.driver_klass.connectionCls
 
@@ -364,7 +125,7 @@ class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin):
 
         # Test authentication and token re-use
         con = cls('username', 'key')
-        osa = con._osa
+        osa = con.get_auth_class()
 
         mocked_auth_method = Mock()
         osa.authenticate = mocked_auth_method
@@ -385,7 +146,7 @@ class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin):
         # ex_force_auth_token provided, authenticate should never be called
         con = cls('username', 'key', ex_force_base_url='http://ponies',
                   ex_force_auth_token='1234')
-        osa = con._osa
+        osa = con.get_auth_class()
 
         mocked_auth_method = Mock()
         osa.authenticate = mocked_auth_method

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cd167194/libcloud/test/storage/test_cloudfiles.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_cloudfiles.py b/libcloud/test/storage/test_cloudfiles.py
index 84ec615..70e52c8 100644
--- a/libcloud/test/storage/test_cloudfiles.py
+++ b/libcloud/test/storage/test_cloudfiles.py
@@ -138,16 +138,6 @@ class CloudFilesTests(unittest.TestCase):
             self.driver.connection.get_endpoint())
         self.driver.connection.cdn_request = False
 
-    def test_endpoint_pointer(self):
-        kwargs = {'use_internal_url': False}
-        driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs)
-        self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.PUBLIC_ENDPOINT_KEY)
-        kwargs = {'use_internal_url': True}
-        driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs)
-        self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.INTERNAL_ENDPOINT_KEY)
-        driver.connection.cdn_request = True
-        self.assertEquals(driver.connection._get_endpoint_key(), libcloud.storage.drivers.cloudfiles.PUBLIC_ENDPOINT_KEY)
-
     def test_list_containers(self):
         CloudFilesMockHttp.type = 'EMPTY'
         containers = self.driver.list_containers()


Mime
View raw message