Updated Branches: refs/heads/trunk b4aa97231 -> 64b55706a
Allow user to specify a full URL with a path for the "auth_url" argument in the OpenStack driver, add storage driver for KT Ucloud. (LIBCLOUD-431) Signed-off-by: Tomaz Muraus <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/7afee031 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/7afee031 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/7afee031 Branch: refs/heads/trunk Commit: 7afee0317a58829245864b50917f39ef83f4dca9 Parents: b4aa972 Author: charsyam <[email protected]> Authored: Sat Nov 2 01:02:04 2013 +0900 Committer: Tomaz Muraus <[email protected]> Committed: Mon Nov 4 21:08:56 2013 +0000 ---------------------------------------------------------------------- libcloud/common/openstack.py | 34 ++++++++++++- libcloud/common/rackspace.py | 2 +- libcloud/storage/drivers/ktucloud.py | 52 ++++++++++++++++++++ libcloud/storage/providers.py | 2 + libcloud/storage/types.py | 1 + libcloud/test/compute/test_openstack.py | 71 +++++++++++++++++++++++++--- libcloud/test/compute/test_rackspace.py | 4 +- 7 files changed, 155 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/common/openstack.py ---------------------------------------------------------------------- diff --git a/libcloud/common/openstack.py b/libcloud/common/openstack.py index b9a6f2e..085b364 100644 --- a/libcloud/common/openstack.py +++ b/libcloud/common/openstack.py @@ -120,7 +120,37 @@ class OpenStackAuthConnection(ConnectionUserAndKey): self.auth_user_info = None def morph_action_hook(self, action): - return action + (host, port, secure, request_path) = \ + self._tuple_from_url(self.auth_url) + + # for example auth_url is + # + # http://192.168.0.100 - assume path is not provided, + # depending on the auth_version, + # correct path should be appended + # to the final url + # if auth_version is 1.0 + # final is http://192.168.0.100/v1.0 + # if auth_version is 1.1 + # final is http://192.168.0.100/v1.1/auth + # if auth_version is 2.0 + # final is http://192.168.0.100/v2.0/tokens + # + # http://192.168.0.100/ - assume path(foo/bar) is already + # provided, nothing should be + # apppended to the final url + # + # http://192.168.0.100/foo/bar - assume path(foo/bar) is already + # provided, nothing should be + # apppended to the final url + # + # http://192.168.0.100/foo/bar/ - assume path(foo/bar) is already + # provided, nothing should be + # appended to the final url + if request_path is "": + return action + + return request_path def add_default_headers(self, headers): headers['Accept'] = 'application/json' @@ -162,7 +192,7 @@ class OpenStackAuthConnection(ConnectionUserAndKey): if resp.status == httplib.UNAUTHORIZED: # HTTP UNAUTHORIZED (401): auth failed raise InvalidCredsError() - elif resp.status != httplib.NO_CONTENT: + elif resp.status not in [httplib.NO_CONTENT, httplib.OK]: body = 'code: %s body:%s headers:%s' % (resp.status, resp.body, resp.headers) http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/common/rackspace.py ---------------------------------------------------------------------- diff --git a/libcloud/common/rackspace.py b/libcloud/common/rackspace.py index eea4ead..3826ba6 100644 --- a/libcloud/common/rackspace.py +++ b/libcloud/common/rackspace.py @@ -21,4 +21,4 @@ __all__ = [ 'AUTH_URL' ] -AUTH_URL = 'https://auth.api.rackspacecloud.com/v2.0/' +AUTH_URL = 'https://auth.api.rackspacecloud.com' http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/storage/drivers/ktucloud.py ---------------------------------------------------------------------- diff --git a/libcloud/storage/drivers/ktucloud.py b/libcloud/storage/drivers/ktucloud.py new file mode 100644 index 0000000..9708a9b --- /dev/null +++ b/libcloud/storage/drivers/ktucloud.py @@ -0,0 +1,52 @@ +# 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. + +from libcloud.common.types import LibcloudError +from libcloud.storage.providers import Provider + +from libcloud.storage.drivers.cloudfiles import CloudFilesConnection +from libcloud.storage.drivers.cloudfiles import CloudFilesStorageDriver + +KTUCLOUDSTORAGE_AUTH_URL = "https://ssproxy.ucloudbiz.olleh.com/auth/v1.0" +KTUCLOUDSTORAGE_API_VERSION = "1.0" + + +class KTUCloudStorageConnection(CloudFilesConnection): + """ + Connection class for the KT UCloud Storage endpoint. + """ + + auth_url = KTUCLOUDSTORAGE_AUTH_URL + _auth_version = KTUCLOUDSTORAGE_API_VERSION + + def get_endpoint(self): + eps = self.service_catalog.get_endpoints(name='cloudFiles') + if len(eps) == 0: + raise LibcloudError('Could not find specified endpoint') + ep = eps[0] + if 'publicURL' in ep: + return ep['publicURL'] + else: + raise LibcloudError('Could not find specified endpoint') + + +class KTUCloudStorageDriver(CloudFilesStorageDriver): + """ + Cloudfiles storage driver for the UK endpoint. + """ + + type = Provider.KTUCLOUD + name = 'KTUCloud Storage' + connectionCls = KTUCloudStorageConnection http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/storage/providers.py ---------------------------------------------------------------------- diff --git a/libcloud/storage/providers.py b/libcloud/storage/providers.py index 4148d28..f704254 100644 --- a/libcloud/storage/providers.py +++ b/libcloud/storage/providers.py @@ -46,6 +46,8 @@ DRIVERS = { ('libcloud.storage.drivers.local', 'LocalStorageDriver'), Provider.AZURE_BLOBS: ('libcloud.storage.drivers.azure_blobs', 'AzureBlobsStorageDriver'), + Provider.KTUCLOUD: + ('libcloud.storage.drivers.ktucloud', 'KTUCloudStorageDriver'), # Deprecated Provider.CLOUDFILES_US: http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/storage/types.py ---------------------------------------------------------------------- diff --git a/libcloud/storage/types.py b/libcloud/storage/types.py index 6a0c82f..ae48430 100644 --- a/libcloud/storage/types.py +++ b/libcloud/storage/types.py @@ -57,6 +57,7 @@ class Provider(object): LOCAL = 'local' CLOUDFILES = 'cloudfiles' AZURE_BLOBS = 'azure_blobs' + KTUCLOUD = 'ktucloud' # Deperecated CLOUDFILES_US = 'cloudfiles_us' http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/test/compute/test_openstack.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py index b73ccb4..16ffeeb 100644 --- a/libcloud/test/compute/test_openstack.py +++ b/libcloud/test/compute/test_openstack.py @@ -94,7 +94,7 @@ class OpenStackServiceCatalogTests(unittest.TestCase): def test_connection_get_service_catalog(self): connection = OpenStackBaseConnection(*OPENSTACK_PARAMS) - connection.auth_url = "https://auth.api.example.com/v1.1/" + 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) @@ -120,6 +120,61 @@ class OpenStackAuthConnectionTests(unittest.TestCase): 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 _auth_url, \ + should_append_default_path, \ + expected_path in auth_urls: + + connection = \ + self._get_mock_connection(mock_http_class=mock_http_class, + auth_url=_auth_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), @@ -224,12 +279,16 @@ class OpenStackAuthConnectionTests(unittest.TestCase): self.assertEqual(mocked_auth_method.call_count, 5) - def _get_mock_connection(self, mock_http_class): + def _get_mock_connection(self, mock_http_class, auth_url=None): OpenStackBaseConnection.conn_classes = (mock_http_class, mock_http_class) connection = OpenStackBaseConnection(*OPENSTACK_PARAMS) - connection.auth_url = "https://auth.api.example.com/v1.1/" + if auth_url is None: + connection.auth_url = "https://auth.api.example.com" + else: + connection.auth_url = auth_url + connection._ex_force_base_url = "https://www.foo.com" connection.driver = OpenStack_1_0_NodeDriver(*OPENSTACK_PARAMS) @@ -260,7 +319,7 @@ class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin): self.driver_klass.connectionCls.conn_classes = ( OpenStackMockHttp, OpenStackMockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com/v1.1/" + self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None self.driver = self.create_driver() # normally authentication happens lazily, but we force it here @@ -749,7 +808,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin): def setUp(self): self.driver_klass.connectionCls.conn_classes = ( OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com/v2.0/" + self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None OpenStack_1_1_MockHttp.type = None OpenStack_2_0_MockHttp.type = None @@ -1681,7 +1740,7 @@ class OpenStack_1_1_Auth_2_0_Tests(OpenStack_1_1_Tests): def setUp(self): self.driver_klass.connectionCls.conn_classes = \ (OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp) - self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com/v2.0/" + self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com" OpenStackMockHttp.type = None OpenStack_1_1_MockHttp.type = None OpenStack_2_0_MockHttp.type = None http://git-wip-us.apache.org/repos/asf/libcloud/blob/7afee031/libcloud/test/compute/test_rackspace.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_rackspace.py b/libcloud/test/compute/test_rackspace.py index c222130..d42e668 100644 --- a/libcloud/test/compute/test_rackspace.py +++ b/libcloud/test/compute/test_rackspace.py @@ -119,7 +119,7 @@ class RackspaceNovaLonMockHttp(RackspaceNovaMockHttp): class BaseRackspaceNovaTestCase(object): conn_classes = (RackspaceNovaMockHttp, RackspaceNovaMockHttp) - auth_url = 'https://auth.api.example.com/v2.0/' + auth_url = 'https://auth.api.example.com' def create_driver(self): return self.driver_type(*self.driver_args, **self.driver_kwargs) @@ -185,7 +185,7 @@ class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests): driver_kwargs = {'region': 'lon'} conn_classes = (RackspaceNovaLonMockHttp, RackspaceNovaLonMockHttp) - auth_url = 'https://lon.auth.api.example.com/v2.0/' + auth_url = 'https://lon.auth.api.example.com' expected_endpoint = 'https://lon.servers.api.rackspacecloud.com/v2/1337'
