You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2012/03/16 21:21:38 UTC

svn commit: r1301741 - in /libcloud/trunk: libcloud/common/ libcloud/compute/ libcloud/compute/drivers/ libcloud/dns/ libcloud/dns/drivers/ libcloud/loadbalancer/ libcloud/loadbalancer/drivers/ libcloud/storage/ libcloud/storage/drivers/ test/compute/ ...

Author: tomaz
Date: Fri Mar 16 20:21:37 2012
New Revision: 1301741

URL: http://svn.apache.org/viewvc?rev=1301741&view=rev
Log:
Add a new mixin class and make all the OpenStack based drivers inherit from it.
This way all the OpenStack based drivers accept the same extenstion keyword
arguments. This patch has been contributed by Dave King and is part of
LIBCLOUD-167.

Modified:
    libcloud/trunk/libcloud/common/base.py
    libcloud/trunk/libcloud/common/openstack.py
    libcloud/trunk/libcloud/compute/base.py
    libcloud/trunk/libcloud/compute/drivers/openstack.py
    libcloud/trunk/libcloud/dns/base.py
    libcloud/trunk/libcloud/dns/drivers/rackspace.py
    libcloud/trunk/libcloud/loadbalancer/base.py
    libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
    libcloud/trunk/libcloud/storage/base.py
    libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
    libcloud/trunk/test/compute/test_openstack.py
    libcloud/trunk/test/dns/test_rackspace.py
    libcloud/trunk/test/loadbalancer/test_rackspace.py
    libcloud/trunk/test/storage/test_cloudfiles.py

Modified: libcloud/trunk/libcloud/common/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/base.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/base.py (original)
+++ libcloud/trunk/libcloud/common/base.py Fri Mar 16 20:21:37 2012
@@ -769,7 +769,7 @@ class BaseDriver(object):
     connectionCls = ConnectionKey
 
     def __init__(self, key, secret=None, secure=True, host=None, port=None,
-                 api_version=None):
+                 api_version=None, **kwargs):
         """
         @keyword    key:    API key or username to used
         @type       key:    str

Modified: libcloud/trunk/libcloud/common/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/openstack.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/openstack.py (original)
+++ libcloud/trunk/libcloud/common/openstack.py Fri Mar 16 20:21:37 2012
@@ -418,3 +418,24 @@ class OpenStackBaseConnection(Connection
             params['cache-busting'] = cache_busting_number
         else:
             params.append(('cache-busting', cache_busting_number))
+
+
+class OpenStackDriverMixin(object):
+
+    def __init__(self, *args, **kwargs):
+        self._ex_force_base_url = kwargs.get('ex_force_base_url', None)
+        self._ex_force_auth_url = kwargs.get('ex_force_auth_url', None)
+        self._ex_force_auth_version = kwargs.get('ex_force_auth_version', None)
+        self._ex_force_auth_token = kwargs.get('ex_force_auth_token', None)
+
+    def openstack_connection_kwargs(self):
+        rv = {}
+        if self._ex_force_base_url:
+            rv['ex_force_base_url'] = self._ex_force_base_url
+        if self._ex_force_auth_token:
+            rv['ex_force_auth_token'] = self._ex_force_auth_token
+        if self._ex_force_auth_url:
+            rv['ex_force_auth_url'] = self._ex_force_auth_url
+        if self._ex_force_auth_version:
+            rv['ex_force_auth_version'] = self._ex_force_auth_version
+        return rv

Modified: libcloud/trunk/libcloud/compute/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/base.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/base.py (original)
+++ libcloud/trunk/libcloud/compute/base.py Fri Mar 16 20:21:37 2012
@@ -392,10 +392,10 @@ class NodeDriver(BaseDriver):
     NODE_STATE_MAP = {}
 
     def __init__(self, key, secret=None, secure=True, host=None, port=None,
-                 api_version=None):
+                 api_version=None, **kwargs):
         super(NodeDriver, self).__init__(key=key, secret=secret, secure=secure,
                                          host=host, port=port,
-                                         api_version=api_version)
+                                         api_version=api_version, **kwargs)
 
     def create_node(self, **kwargs):
         """Create a new node instance.

Modified: libcloud/trunk/libcloud/compute/drivers/openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/openstack.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/openstack.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/openstack.py Fri Mar 16 20:21:37 2012
@@ -36,7 +36,7 @@ import base64
 
 from xml.etree import ElementTree as ET
 
-from libcloud.common.openstack import OpenStackBaseConnection
+from libcloud.common.openstack import OpenStackBaseConnection, OpenStackDriverMixin
 from libcloud.common.types import MalformedResponseError, LibcloudError
 from libcloud.compute.types import NodeState, Provider
 from libcloud.compute.base import NodeSize, NodeImage
@@ -156,7 +156,7 @@ class OpenStackComputeConnection(OpenSta
             method=method, headers=headers)
 
 
-class OpenStackNodeDriver(NodeDriver):
+class OpenStackNodeDriver(NodeDriver, OpenStackDriverMixin):
     """
     Base OpenStack node driver. Should not be used directly.
     """
@@ -193,6 +193,10 @@ class OpenStackNodeDriver(NodeDriver):
                     (api_version))
         return super(OpenStackNodeDriver, cls).__new__(cls)
 
+    def __init__(self, *args, **kwargs):
+        OpenStackDriverMixin.__init__(self, **kwargs)
+        super(OpenStackNodeDriver, self).__init__(*args, **kwargs)
+
     def destroy_node(self, node):
         uri = '/servers/%s' % (node.id)
         resp = self.connection.request(uri, method='DELETE')
@@ -222,14 +226,7 @@ class OpenStackNodeDriver(NodeDriver):
         return [NodeLocation(0, '', '', self)]
 
     def _ex_connection_class_kwargs(self):
-        rv = {}
-        if self._ex_force_base_url:
-            rv['ex_force_base_url'] = self._ex_force_base_url
-        if self._ex_force_auth_url:
-            rv['ex_force_auth_url'] = self._ex_force_auth_url
-        if self._ex_force_auth_version:
-            rv['ex_force_auth_version'] = self._ex_force_auth_version
-        return rv
+        return self.openstack_connection_kwargs()
 
     def ex_get_node_details(self, node_id):
         # @TODO: Remove this if in 0.6
@@ -284,9 +281,6 @@ class OpenStack_1_0_NodeDriver(OpenStack
     features = {"create_node": ["generates_password"]}
 
     def __init__(self, *args, **kwargs):
-        self._ex_force_base_url = kwargs.pop('ex_force_base_url', None)
-        self._ex_force_auth_url = kwargs.pop('ex_force_auth_url', None)
-        self._ex_force_auth_version = kwargs.pop('ex_force_auth_version', None)
         self._ex_force_api_version = str(kwargs.pop('ex_force_api_version',
                                                     None))
         self.XML_NAMESPACE = self.connectionCls.XML_NAMESPACE
@@ -802,10 +796,6 @@ class OpenStack_1_1_NodeDriver(OpenStack
     features = {"create_node": ["generates_password"]}
 
     def __init__(self, *args, **kwargs):
-        self._ex_force_base_url = kwargs.pop('ex_force_base_url', None)
-        self._ex_force_auth_url = kwargs.pop('ex_force_auth_url', None)
-        self._ex_force_auth_version = kwargs.pop('ex_force_auth_version',
-                                                 None)
         self._ex_force_api_version = str(kwargs.pop('ex_force_api_version',
                                                     None))
         super(OpenStack_1_1_NodeDriver, self).__init__(*args, **kwargs)

Modified: libcloud/trunk/libcloud/dns/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/base.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/base.py (original)
+++ libcloud/trunk/libcloud/dns/base.py Fri Mar 16 20:21:37 2012
@@ -132,9 +132,9 @@ class DNSDriver(BaseDriver):
     connectionCls = ConnectionUserAndKey
     name = None
 
-    def __init__(self, key, secret=None, secure=True, host=None, port=None):
+    def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs):
         super(DNSDriver, self).__init__(key=key, secret=secret, secure=secure,
-                                        host=host, port=port)
+                                        host=host, port=port, **kwargs)
 
     def list_record_types(self):
         """

Modified: libcloud/trunk/libcloud/dns/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/rackspace.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/rackspace.py Fri Mar 16 20:21:37 2012
@@ -12,6 +12,7 @@
 # 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.openstack import OpenStackDriverMixin
 
 __all__ = [
     'RackspaceUSDNSDriver',
@@ -118,7 +119,14 @@ class RackspaceUKDNSConnection(Rackspace
     auth_url = AUTH_URL_UK
 
 
-class RackspaceDNSDriver(DNSDriver):
+class RackspaceDNSDriver(DNSDriver, OpenStackDriverMixin):
+
+    def __init__(self, *args, **kwargs):
+        OpenStackDriverMixin.__init__(self, *args, **kwargs)
+        super(RackspaceDNSDriver, self).__init__(*args, **kwargs)
+
+    def _ex_connection_class_kwargs(self):
+        return self.openstack_connection_kwargs()
 
     RECORD_TYPE_MAP = {
         RecordType.A: 'A',

Modified: libcloud/trunk/libcloud/loadbalancer/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/base.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/base.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/base.py Fri Mar 16 20:21:37 2012
@@ -96,9 +96,9 @@ class Driver(BaseDriver):
     _ALGORITHM_TO_VALUE_MAP = {}
     _VALUE_TO_ALGORITHM_MAP = {}
 
-    def __init__(self, key, secret=None, secure=True, host=None, port=None):
+    def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs):
         super(Driver, self).__init__(key=key, secret=secret, secure=secure,
-                                     host=host, port=port)
+                                     host=host, port=port, **kwargs)
 
     def list_protocols(self):
         """

Modified: libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py (original)
+++ libcloud/trunk/libcloud/loadbalancer/drivers/rackspace.py Fri Mar 16 20:21:37 2012
@@ -29,7 +29,7 @@ from libcloud.loadbalancer.base import D
 from libcloud.common.types import LibcloudError
 from libcloud.common.base import JsonResponse, PollingConnection
 from libcloud.loadbalancer.types import State, MemberCondition
-from libcloud.common.openstack import OpenStackBaseConnection
+from libcloud.common.openstack import OpenStackBaseConnection, OpenStackDriverMixin
 from libcloud.common.rackspace import (
         AUTH_URL_US, AUTH_URL_UK)
 
@@ -286,7 +286,7 @@ class RackspaceUKConnection(RackspaceCon
     auth_url = AUTH_URL_UK
 
 
-class RackspaceLBDriver(Driver):
+class RackspaceLBDriver(Driver, OpenStackDriverMixin):
     connectionCls = RackspaceConnection
     api_name = 'rackspace_lb'
     name = 'Rackspace LB'
@@ -318,6 +318,13 @@ class RackspaceLBDriver(Driver):
 
     _ALGORITHM_TO_VALUE_MAP = reverse_dict(_VALUE_TO_ALGORITHM_MAP)
 
+    def __init__(self, *args, **kwargs):
+        OpenStackDriverMixin.__init__(self, *args, **kwargs)
+        super(RackspaceLBDriver, self).__init__(*args, **kwargs)
+
+    def _ex_connection_class_kwargs(self):
+        return self.openstack_connection_kwargs()
+
     def list_protocols(self):
         return self._to_protocols(
                    self.connection.request('/loadbalancers/protocols').object)

Modified: libcloud/trunk/libcloud/storage/base.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/base.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/base.py (original)
+++ libcloud/trunk/libcloud/storage/base.py Fri Mar 16 20:21:37 2012
@@ -164,9 +164,9 @@ class StorageDriver(BaseDriver):
     hash_type = 'md5'
     supports_chunked_encoding = False
 
-    def __init__(self, key, secret=None, secure=True, host=None, port=None):
+    def __init__(self, key, secret=None, secure=True, host=None, port=None, **kwargs):
       super(StorageDriver, self).__init__(key=key, secret=secret, secure=secure,
-                                          host=host, port=port)
+                                          host=host, port=port, **kwargs)
 
     def list_containters(self):
         """

Modified: libcloud/trunk/libcloud/storage/drivers/cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/storage/drivers/cloudfiles.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/libcloud/storage/drivers/cloudfiles.py (original)
+++ libcloud/trunk/libcloud/storage/drivers/cloudfiles.py Fri Mar 16 20:21:37 2012
@@ -40,7 +40,7 @@ from libcloud.storage.types import Objec
 from libcloud.storage.types import ObjectHashMismatchError
 from libcloud.storage.types import InvalidContainerNameError
 from libcloud.common.types import LazyList
-from libcloud.common.openstack import OpenStackBaseConnection
+from libcloud.common.openstack import OpenStackBaseConnection, OpenStackDriverMixin
 
 from libcloud.common.rackspace import (
     AUTH_URL_US, AUTH_URL_UK)
@@ -139,12 +139,14 @@ class CloudFilesConnection(OpenStackBase
             params = {}
 
         # FIXME: Massive hack.
-        # This driver dynamically changes the url in it's connection, based on arguments
+        # This driver dynamically changes the url in its connection, based on arguments
         # passed to request(). As such, we have to manually check and reset connection
         # params each request
         self._populate_hosts_and_request_paths()
-        ep = self.get_endpoint(cdn_request)
-        (self.host, self.port, self.secure, self.request_path) = self._ex_force_base_url or self._tuple_from_url(ep)
+        if not self._ex_force_base_url:
+            self._reset_connection_params(self.get_endpoint(cdn_request))
+        else:
+            self._reset_connection_params(self._ex_force_base_url)
 
         params['format'] = 'json'
 
@@ -157,6 +159,9 @@ class CloudFilesConnection(OpenStackBase
             method=method, headers=headers,
             raw=raw)
 
+    def _reset_connection_params(self, endpoint_url):
+        (self.host, self.port, self.secure, self.request_path) = self._tuple_from_url(endpoint_url)
+
 
 class CloudFilesUSConnection(CloudFilesConnection):
     """
@@ -174,7 +179,7 @@ class CloudFilesUKConnection(CloudFilesC
     auth_url = AUTH_URL_UK
 
 
-class CloudFilesStorageDriver(StorageDriver):
+class CloudFilesStorageDriver(StorageDriver, OpenStackDriverMixin):
     """
     Base CloudFiles driver.
 
@@ -187,6 +192,10 @@ class CloudFilesStorageDriver(StorageDri
     hash_type = 'md5'
     supports_chunked_encoding = True
 
+    def __init__(self, *args, **kwargs):
+        OpenStackDriverMixin.__init__(self, *args, **kwargs)
+        super(CloudFilesStorageDriver, self).__init__(*args, **kwargs)
+
     def list_containers(self):
         response = self.connection.request('')
 
@@ -539,6 +548,9 @@ class CloudFilesStorageDriver(StorageDri
                      meta_data=meta_data, container=container, driver=self)
         return obj
 
+    def _ex_connection_class_kwargs(self):
+        return self.openstack_connection_kwargs()
+
 class CloudFilesUSStorageDriver(CloudFilesStorageDriver):
     """
     Cloudfiles storage driver for the US endpoint.

Modified: libcloud/trunk/test/compute/test_openstack.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_openstack.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/test/compute/test_openstack.py (original)
+++ libcloud/trunk/test/compute/test_openstack.py Fri Mar 16 20:21:37 2012
@@ -24,7 +24,8 @@ from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import method_type
 from libcloud.utils.py3 import u
 
-from libcloud.common.types import InvalidCredsError, MalformedResponseError
+from libcloud.common.types import InvalidCredsError, MalformedResponseError, \
+                                  LibcloudError
 from libcloud.compute.types import Provider
 from libcloud.compute.providers import get_driver
 from libcloud.compute.drivers.openstack import (
@@ -574,6 +575,36 @@ class OpenStack_1_1_Tests(unittest.TestC
         self.assertEqual(self.driver.connection.port, '1222')
         self.assertEqual(self.driver.connection.request_path, '/some-service')
 
+    def test_auth_token_without_base_url_raises_exception(self):
+        kwargs = {
+            'ex_force_auth_version': '2.0',
+            'ex_force_auth_token': 'preset-auth-token'
+        }
+        try:
+            self.driver_type(*self.driver_args, **kwargs)
+            self.fail('Expected failure setting auth token without base url')
+        except LibcloudError as e:
+            pass
+        else:
+            self.fail('Expected failure setting auth token without base url')
+
+    def test_ex_force_auth_token_passed_to_connection(self):
+        base_url = 'https://servers.api.rackspacecloud.com/v1.1/slug'
+        kwargs = {
+            'ex_force_auth_version': '2.0',
+            'ex_force_auth_token': 'preset-auth-token',
+            'ex_force_base_url': base_url
+        }
+        driver = self.driver_type(*self.driver_args, **kwargs)
+        driver.list_nodes()
+
+        self.assertEquals(kwargs['ex_force_auth_token'],
+                          driver.connection.auth_token)
+        self.assertEquals('servers.api.rackspacecloud.com',
+                          driver.connection.host)
+        self.assertEquals('/v1.1/slug', driver.connection.request_path)
+        self.assertEquals(443, driver.connection.port)
+
     def test_list_nodes(self):
         nodes = self.driver.list_nodes()
         self.assertEqual(len(nodes), 2)

Modified: libcloud/trunk/test/dns/test_rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/dns/test_rackspace.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/test/dns/test_rackspace.py (original)
+++ libcloud/trunk/test/dns/test_rackspace.py Fri Mar 16 20:21:37 2012
@@ -40,6 +40,31 @@ class RackspaceUSTests(unittest.TestCase
         # normally authentication happens lazily, but we force it here
         self.driver.connection._populate_hosts_and_request_paths()
 
+    def test_force_auth_token_kwargs(self):
+        kwargs = {
+            'ex_force_auth_token': 'some-auth-token',
+            'ex_force_base_url': 'https://dns.api.rackspacecloud.com/v1.0/11111'
+        }
+        driver = self.klass(*DNS_PARAMS_RACKSPACE, **kwargs)
+        driver.list_zones()
+
+        self.assertEquals(kwargs['ex_force_auth_token'],
+            driver.connection.auth_token)
+        self.assertEquals('/v1.0/11111',
+            driver.connection.request_path)
+
+    def test_force_auth_url_kwargs(self):
+        kwargs = {
+            'ex_force_auth_version': '2.0',
+            'ex_force_auth_url': 'https://identity.api.rackspace.com'
+        }
+        driver = self.klass(*DNS_PARAMS_RACKSPACE, **kwargs)
+
+        self.assertEquals(kwargs['ex_force_auth_url'],
+            driver.connection._ex_force_auth_url)
+        self.assertEquals(kwargs['ex_force_auth_version'],
+            driver.connection._auth_version)
+
     def test_list_record_types(self):
         record_types = self.driver.list_record_types()
         self.assertEqual(len(record_types), 7)

Modified: libcloud/trunk/test/loadbalancer/test_rackspace.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/loadbalancer/test_rackspace.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/test/loadbalancer/test_rackspace.py (original)
+++ libcloud/trunk/test/loadbalancer/test_rackspace.py Fri Mar 16 20:21:37 2012
@@ -47,6 +47,32 @@ class RackspaceLBTests(unittest.TestCase
         # normally authentication happens lazily, but we force it here
         self.driver.connection._populate_hosts_and_request_paths()
 
+    def test_force_auth_token_kwargs(self):
+        base_url = 'https://ord.loadbalancer.api.rackspacecloud.com/v1.0/slug'
+        kwargs = {
+            'ex_force_auth_token': 'some-auth-token',
+            'ex_force_base_url': base_url
+        }
+        driver = RackspaceLBDriver('user', 'key', **kwargs)
+        driver.list_balancers()
+
+        self.assertEquals(kwargs['ex_force_auth_token'],
+            driver.connection.auth_token)
+        self.assertEquals('/v1.0/slug',
+            driver.connection.request_path)
+
+    def test_force_auth_url_kwargs(self):
+        kwargs = {
+            'ex_force_auth_version': '2.0',
+            'ex_force_auth_url': 'https://identity.api.rackspace.com'
+        }
+        driver = RackspaceLBDriver('user', 'key', **kwargs)
+
+        self.assertEquals(kwargs['ex_force_auth_url'],
+            driver.connection._ex_force_auth_url)
+        self.assertEquals(kwargs['ex_force_auth_version'],
+            driver.connection._auth_version)
+
     def test_list_protocols(self):
         protocols = self.driver.list_protocols()
 

Modified: libcloud/trunk/test/storage/test_cloudfiles.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/storage/test_cloudfiles.py?rev=1301741&r1=1301740&r2=1301741&view=diff
==============================================================================
--- libcloud/trunk/test/storage/test_cloudfiles.py (original)
+++ libcloud/trunk/test/storage/test_cloudfiles.py Fri Mar 16 20:21:37 2012
@@ -60,6 +60,34 @@ class CloudFilesTests(unittest.TestCase)
     def tearDown(self):
         self._remove_test_file()
 
+    def test_force_auth_token_kwargs(self):
+        base_url = 'https://cdn2.clouddrive.com/v1/MossoCloudFS'
+        kwargs = {
+            'ex_force_auth_token': 'some-auth-token',
+            'ex_force_base_url': base_url
+        }
+        driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs)
+        driver.list_containers()
+
+        self.assertEquals(kwargs['ex_force_auth_token'],
+            driver.connection.auth_token)
+        self.assertEquals('cdn2.clouddrive.com',
+            driver.connection.host)
+        self.assertEquals('/v1/MossoCloudFS',
+            driver.connection.request_path)
+
+    def test_force_auth_url_kwargs(self):
+        kwargs = {
+            'ex_force_auth_version': '2.0',
+            'ex_force_auth_url': 'https://identity.api.rackspace.com'
+        }
+        driver = CloudFilesStorageDriver('driver', 'dummy', **kwargs)
+
+        self.assertEquals(kwargs['ex_force_auth_url'],
+            driver.connection._ex_force_auth_url)
+        self.assertEquals(kwargs['ex_force_auth_version'],
+            driver.connection._auth_version)
+
     def test_invalid_json_throws_exception(self):
         CloudFilesMockHttp.type = 'MALFORMED_JSON'
         try: