You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/04/05 13:16:52 UTC

[01/33] libcloud git commit: Move logging connection classes to another module -why don't people just use a logging proxy instead? so much easier!

Repository: libcloud
Updated Branches:
  refs/heads/requests [created] 2519c34d7


Move logging connection classes to another module -why don't people just use a logging proxy instead? so much easier!


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/cb0f4995
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/cb0f4995
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/cb0f4995

Branch: refs/heads/requests
Commit: cb0f499590c783382b8b5261439e9415fb869278
Parents: fec8af6
Author: anthony-shaw <an...@gmail.com>
Authored: Sat Mar 26 20:38:48 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sat Mar 26 20:38:48 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py             | 190 --------------------------
 libcloud/utils/loggingconnection.py | 220 +++++++++++++++++++++++++++++++
 2 files changed, 220 insertions(+), 190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/cb0f4995/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 1f353ab..6f62e0d 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -21,14 +21,11 @@ import copy
 import binascii
 import time
 
-import xml.dom.minidom
-
 try:
     from lxml import etree as ET
 except ImportError:
     from xml.etree import ElementTree as ET
 
-from pipes import quote as pquote
 
 try:
     import simplejson as json
@@ -41,8 +38,6 @@ from libcloud.utils.py3 import PY3, PY25
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import urlencode
-from libcloud.utils.py3 import StringIO
-from libcloud.utils.py3 import u
 from libcloud.utils.py3 import b
 
 from libcloud.utils.misc import lowercase_keys, retry
@@ -63,8 +58,6 @@ __all__ = [
     'ConnectionKey',
     'ConnectionUserAndKey',
     'CertificateConnection',
-    'LoggingHTTPConnection',
-    'LoggingHTTPSConnection',
 
     'Response',
     'HTTPResponse',
@@ -322,189 +315,6 @@ class RawResponse(Response):
         return self._reason
 
 
-# TODO: Move this to a better location/package
-class LoggingConnection():
-    """
-    Debug class to log all HTTP(s) requests as they could be made
-    with the curl command.
-
-    :cvar log: file-like object that logs entries are written to.
-    """
-
-    log = None
-    http_proxy_used = False
-
-    def _log_response(self, r):
-        rv = "# -------- begin %d:%d response ----------\n" % (id(self), id(r))
-        ht = ""
-        v = r.version
-        if r.version == 10:
-            v = "HTTP/1.0"
-        if r.version == 11:
-            v = "HTTP/1.1"
-        ht += "%s %s %s\r\n" % (v, r.status, r.reason)
-        body = r.read()
-        for h in r.getheaders():
-            ht += "%s: %s\r\n" % (h[0].title(), h[1])
-        ht += "\r\n"
-
-        # this is evil. laugh with me. ha arharhrhahahaha
-        class fakesock(object):
-            def __init__(self, s):
-                self.s = s
-
-            def makefile(self, *args, **kwargs):
-                if PY3:
-                    from io import BytesIO
-                    cls = BytesIO
-                else:
-                    cls = StringIO
-
-                return cls(b(self.s))
-        rr = r
-        headers = lowercase_keys(dict(r.getheaders()))
-
-        encoding = headers.get('content-encoding', None)
-        content_type = headers.get('content-type', None)
-
-        if encoding in ['zlib', 'deflate']:
-            body = decompress_data('zlib', body)
-        elif encoding in ['gzip', 'x-gzip']:
-            body = decompress_data('gzip', body)
-
-        pretty_print = os.environ.get('LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE',
-                                      False)
-
-        if r.chunked:
-            ht += "%x\r\n" % (len(body))
-            ht += body.decode('utf-8')
-            ht += "\r\n0\r\n"
-        else:
-            if pretty_print and content_type == 'application/json':
-                try:
-                    body = json.loads(body.decode('utf-8'))
-                    body = json.dumps(body, sort_keys=True, indent=4)
-                except:
-                    # Invalid JSON or server is lying about content-type
-                    pass
-            elif pretty_print and content_type == 'text/xml':
-                try:
-                    elem = xml.dom.minidom.parseString(body.decode('utf-8'))
-                    body = elem.toprettyxml()
-                except Exception:
-                    # Invalid XML
-                    pass
-
-            ht += u(body)
-
-        if sys.version_info >= (2, 6) and sys.version_info < (2, 7):
-            cls = HTTPResponse
-        else:
-            cls = httplib.HTTPResponse
-
-        rr = cls(sock=fakesock(ht), method=r._method,
-                 debuglevel=r.debuglevel)
-        rr.begin()
-        rv += ht
-        rv += ("\n# -------- end %d:%d response ----------\n"
-               % (id(self), id(r)))
-
-        rr._original_data = body
-        return (rr, rv)
-
-    def _log_curl(self, method, url, body, headers):
-        cmd = ["curl"]
-
-        if self.http_proxy_used:
-            if self.proxy_username and self.proxy_password:
-                proxy_url = 'http://%s:%s@%s:%s' % (self.proxy_username,
-                                                    self.proxy_password,
-                                                    self.proxy_host,
-                                                    self.proxy_port)
-            else:
-                proxy_url = 'http://%s:%s' % (self.proxy_host,
-                                              self.proxy_port)
-            proxy_url = pquote(proxy_url)
-            cmd.extend(['--proxy', proxy_url])
-
-        cmd.extend(['-i'])
-
-        if method.lower() == 'head':
-            # HEAD method need special handling
-            cmd.extend(["--head"])
-        else:
-            cmd.extend(["-X", pquote(method)])
-
-        for h in headers:
-            cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))])
-
-        cert_file = getattr(self, 'cert_file', None)
-
-        if cert_file:
-            cmd.extend(["--cert", pquote(cert_file)])
-
-        # TODO: in python 2.6, body can be a file-like object.
-        if body is not None and len(body) > 0:
-            cmd.extend(["--data-binary", pquote(body)])
-
-        cmd.extend(["--compress"])
-        cmd.extend([pquote("%s://%s:%d%s" % (self.protocol, self.host,
-                                             self.port, url))])
-        return " ".join(cmd)
-
-
-class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection):
-    """
-    Utility Class for logging HTTPS connections
-    """
-
-    protocol = 'https'
-
-    def getresponse(self):
-        r = LibcloudHTTPSConnection.getresponse(self)
-        if self.log is not None:
-            r, rv = self._log_response(r)
-            self.log.write(rv + "\n")
-            self.log.flush()
-        return r
-
-    def request(self, method, url, body=None, headers=None):
-        headers.update({'X-LC-Request-ID': str(id(self))})
-        if self.log is not None:
-            pre = "# -------- begin %d request ----------\n" % id(self)
-            self.log.write(pre +
-                           self._log_curl(method, url, body, headers) + "\n")
-            self.log.flush()
-        return LibcloudHTTPSConnection.request(self, method, url, body,
-                                               headers)
-
-
-class LoggingHTTPConnection(LoggingConnection, LibcloudHTTPConnection):
-    """
-    Utility Class for logging HTTP connections
-    """
-
-    protocol = 'http'
-
-    def getresponse(self):
-        r = LibcloudHTTPConnection.getresponse(self)
-        if self.log is not None:
-            r, rv = self._log_response(r)
-            self.log.write(rv + "\n")
-            self.log.flush()
-        return r
-
-    def request(self, method, url, body=None, headers=None):
-        headers.update({'X-LC-Request-ID': str(id(self))})
-        if self.log is not None:
-            pre = '# -------- begin %d request ----------\n' % id(self)
-            self.log.write(pre +
-                           self._log_curl(method, url, body, headers) + "\n")
-            self.log.flush()
-        return LibcloudHTTPConnection.request(self, method, url,
-                                              body, headers)
-
-
 class Connection(object):
     """
     A Base Connection class to derive from.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/cb0f4995/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
new file mode 100644
index 0000000..b7a1996
--- /dev/null
+++ b/libcloud/utils/loggingconnection.py
@@ -0,0 +1,220 @@
+# 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.
+
+try:
+    import simplejson as json
+except:
+    import json
+
+from pipes import quote as pquote
+import xml.dom.minidom
+
+import sys
+import os
+import httplib
+
+from libcloud.common.base import LibcloudHTTPConnection, \
+                                 LibcloudHTTPSConnection, \
+                                 HTTPResponse
+from libcloud.utils.py3 import PY3
+from libcloud.utils.py3 import StringIO
+from libcloud.utils.py3 import u
+from libcloud.utils.py3 import b
+
+
+from libcloud.utils.misc import lowercase_keys
+from libcloud.utils.compression import decompress_data
+
+
+class LoggingConnection():
+    """
+    Debug class to log all HTTP(s) requests as they could be made
+    with the curl command.
+
+    :cvar log: file-like object that logs entries are written to.
+    """
+
+    log = None
+    http_proxy_used = False
+
+    def _log_response(self, r):
+        rv = "# -------- begin %d:%d response ----------\n" % (id(self), id(r))
+        ht = ""
+        v = r.version
+        if r.version == 10:
+            v = "HTTP/1.0"
+        if r.version == 11:
+            v = "HTTP/1.1"
+        ht += "%s %s %s\r\n" % (v, r.status, r.reason)
+        body = r.read()
+        for h in r.getheaders():
+            ht += "%s: %s\r\n" % (h[0].title(), h[1])
+        ht += "\r\n"
+
+        # this is evil. laugh with me. ha arharhrhahahaha
+        class fakesock(object):
+            def __init__(self, s):
+                self.s = s
+
+            def makefile(self, *args, **kwargs):
+                if PY3:
+                    from io import BytesIO
+                    cls = BytesIO
+                else:
+                    cls = StringIO
+
+                return cls(b(self.s))
+        rr = r
+        headers = lowercase_keys(dict(r.getheaders()))
+
+        encoding = headers.get('content-encoding', None)
+        content_type = headers.get('content-type', None)
+
+        if encoding in ['zlib', 'deflate']:
+            body = decompress_data('zlib', body)
+        elif encoding in ['gzip', 'x-gzip']:
+            body = decompress_data('gzip', body)
+
+        pretty_print = os.environ.get('LIBCLOUD_DEBUG_PRETTY_PRINT_RESPONSE',
+                                      False)
+
+        if r.chunked:
+            ht += "%x\r\n" % (len(body))
+            ht += body.decode('utf-8')
+            ht += "\r\n0\r\n"
+        else:
+            if pretty_print and content_type == 'application/json':
+                try:
+                    body = json.loads(body.decode('utf-8'))
+                    body = json.dumps(body, sort_keys=True, indent=4)
+                except:
+                    # Invalid JSON or server is lying about content-type
+                    pass
+            elif pretty_print and content_type == 'text/xml':
+                try:
+                    elem = xml.dom.minidom.parseString(body.decode('utf-8'))
+                    body = elem.toprettyxml()
+                except Exception:
+                    # Invalid XML
+                    pass
+
+            ht += u(body)
+
+        if sys.version_info >= (2, 6) and sys.version_info < (2, 7):
+            cls = HTTPResponse
+        else:
+            cls = httplib.HTTPResponse
+
+        rr = cls(sock=fakesock(ht), method=r._method,
+                 debuglevel=r.debuglevel)
+        rr.begin()
+        rv += ht
+        rv += ("\n# -------- end %d:%d response ----------\n"
+               % (id(self), id(r)))
+
+        rr._original_data = body
+        return (rr, rv)
+
+    def _log_curl(self, method, url, body, headers):
+        cmd = ["curl"]
+
+        if self.http_proxy_used:
+            if self.proxy_username and self.proxy_password:
+                proxy_url = 'http://%s:%s@%s:%s' % (self.proxy_username,
+                                                    self.proxy_password,
+                                                    self.proxy_host,
+                                                    self.proxy_port)
+            else:
+                proxy_url = 'http://%s:%s' % (self.proxy_host,
+                                              self.proxy_port)
+            proxy_url = pquote(proxy_url)
+            cmd.extend(['--proxy', proxy_url])
+
+        cmd.extend(['-i'])
+
+        if method.lower() == 'head':
+            # HEAD method need special handling
+            cmd.extend(["--head"])
+        else:
+            cmd.extend(["-X", pquote(method)])
+
+        for h in headers:
+            cmd.extend(["-H", pquote("%s: %s" % (h, headers[h]))])
+
+        cert_file = getattr(self, 'cert_file', None)
+
+        if cert_file:
+            cmd.extend(["--cert", pquote(cert_file)])
+
+        # TODO: in python 2.6, body can be a file-like object.
+        if body is not None and len(body) > 0:
+            cmd.extend(["--data-binary", pquote(body)])
+
+        cmd.extend(["--compress"])
+        cmd.extend([pquote("%s://%s:%d%s" % (self.protocol, self.host,
+                                             self.port, url))])
+        return " ".join(cmd)
+
+
+class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection):
+    """
+    Utility Class for logging HTTPS connections
+    """
+
+    protocol = 'https'
+
+    def getresponse(self):
+        r = LibcloudHTTPSConnection.getresponse(self)
+        if self.log is not None:
+            r, rv = self._log_response(r)
+            self.log.write(rv + "\n")
+            self.log.flush()
+        return r
+
+    def request(self, method, url, body=None, headers=None):
+        headers.update({'X-LC-Request-ID': str(id(self))})
+        if self.log is not None:
+            pre = "# -------- begin %d request ----------\n" % id(self)
+            self.log.write(pre +
+                           self._log_curl(method, url, body, headers) + "\n")
+            self.log.flush()
+        return LibcloudHTTPSConnection.request(self, method, url, body,
+                                               headers)
+
+
+class LoggingHTTPConnection(LoggingConnection, LibcloudHTTPConnection):
+    """
+    Utility Class for logging HTTP connections
+    """
+
+    protocol = 'http'
+
+    def getresponse(self):
+        r = LibcloudHTTPConnection.getresponse(self)
+        if self.log is not None:
+            r, rv = self._log_response(r)
+            self.log.write(rv + "\n")
+            self.log.flush()
+        return r
+
+    def request(self, method, url, body=None, headers=None):
+        headers.update({'X-LC-Request-ID': str(id(self))})
+        if self.log is not None:
+            pre = '# -------- begin %d request ----------\n' % id(self)
+            self.log.write(pre +
+                           self._log_curl(method, url, body, headers) + "\n")
+            self.log.flush()
+        return LibcloudHTTPConnection.request(self, method, url,
+                                              body, headers)


[07/33] libcloud git commit: Fix test initialization and remove unused modules from httplib_ssl

Posted by an...@apache.org.
Fix test initialization and remove unused modules from httplib_ssl


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/10cea10f
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/10cea10f
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/10cea10f

Branch: refs/heads/requests
Commit: 10cea10fe58f5f620ae56769233097079591f9a3
Parents: 4191900
Author: anthony-shaw <an...@gmail.com>
Authored: Sun Mar 27 11:56:28 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sun Mar 27 11:56:28 2016 +1100

----------------------------------------------------------------------
 libcloud/httplib_ssl.py    | 4 ----
 libcloud/test/test_init.py | 4 ++--
 2 files changed, 2 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/10cea10f/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index 6e89a14..ce384d5 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -18,16 +18,12 @@ verification, depending on libcloud.security settings.
 """
 import os
 import socket
-import base64
 import warnings
 
 import requests
 
 import libcloud.security
-from libcloud.utils.py3 import b
-from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
-from libcloud.utils.py3 import urlunquote
 
 
 __all__ = [

http://git-wip-us.apache.org/repos/asf/libcloud/blob/10cea10f/libcloud/test/test_init.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_init.py b/libcloud/test/test_init.py
index ad709d7..bd428ef 100644
--- a/libcloud/test/test_init.py
+++ b/libcloud/test/test_init.py
@@ -25,8 +25,8 @@ except ImportError:
     have_paramiko = False
 
 from libcloud import _init_once
-from libcloud.common.base import LoggingHTTPConnection
-from libcloud.common.base import LoggingHTTPSConnection
+from libcloud.utils.loggingconnection import LoggingHTTPConnection
+from libcloud.utils.loggingconnection import LoggingHTTPSConnection
 
 from libcloud.test import unittest
 


[24/33] libcloud git commit: Fix brightbox tests

Posted by an...@apache.org.
Fix brightbox tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/2195434b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/2195434b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/2195434b

Branch: refs/heads/requests
Commit: 2195434b94df4c221003a7ca98df4ffbf679aecb
Parents: b164cfc
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 15:53:42 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 15:53:42 2016 +1100

----------------------------------------------------------------------
 libcloud/test/loadbalancer/test_brightbox.py | 26 ++++++++++++-----------
 1 file changed, 14 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/2195434b/libcloud/test/loadbalancer/test_brightbox.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_brightbox.py b/libcloud/test/loadbalancer/test_brightbox.py
index ba95c64..7c1008d 100644
--- a/libcloud/test/loadbalancer/test_brightbox.py
+++ b/libcloud/test/loadbalancer/test_brightbox.py
@@ -97,36 +97,38 @@ class BrightboxLBMockHttp(MockHttpTestCase):
 
     def _token(self, method, url, body, headers):
         if method == 'POST':
-            return self.response(httplib.OK, self.fixtures.load('token.json'))
+            return (httplib.OK, self.fixtures.load('token.json'), {'content-type': 'application/json'},
+                    httplib.responses[httplib.OK])
 
     def _1_0_load_balancers(self, method, url, body, headers):
         if method == 'GET':
-            return self.response(httplib.OK,
-                                 self.fixtures.load('load_balancers.json'))
+            return (httplib.OK, self.fixtures.load('load_balancers.json'), {'content-type': 'application/json'},
+                    httplib.responses[httplib.OK])
         elif method == 'POST':
             body = self.fixtures.load('load_balancers_post.json')
-            return self.response(httplib.ACCEPTED, body)
+            return (httplib.ACCEPTED, body, {'content-type': 'application/json'},
+                    httplib.responses[httplib.ACCEPTED])
 
     def _1_0_load_balancers_lba_1235f(self, method, url, body, headers):
         if method == 'GET':
             body = self.fixtures.load('load_balancers_lba_1235f.json')
-            return self.response(httplib.OK, body)
+            return (httplib.OK, body, {'content-type': 'application/json'},
+                    httplib.responses[httplib.OK])
         elif method == 'DELETE':
-            return self.response(httplib.ACCEPTED, '')
+            return (httplib.ACCEPTED, '', {'content-type': 'application/json'},
+                    httplib.responses[httplib.ACCEPTED])
 
     def _1_0_load_balancers_lba_1235f_add_nodes(self, method, url, body,
                                                 headers):
         if method == 'POST':
-            return self.response(httplib.ACCEPTED, '')
+            return (httplib.ACCEPTED, '', {'content-type': 'application/json'},
+                    httplib.responses[httplib.ACCEPTED])
 
     def _1_0_load_balancers_lba_1235f_remove_nodes(self, method, url, body,
                                                    headers):
         if method == 'POST':
-            return self.response(httplib.ACCEPTED, '')
-
-    def response(self, status, body):
-        return (status, body, {'content-type': 'application/json'},
-                httplib.responses[status])
+            return (httplib.ACCEPTED, '', {'content-type': 'application/json'},
+                    httplib.responses[httplib.ACCEPTED])
 
 
 if __name__ == "__main__":


[18/33] libcloud git commit: Fix digital ocean tests

Posted by an...@apache.org.
Fix digital ocean tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/dc1290f0
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/dc1290f0
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/dc1290f0

Branch: refs/heads/requests
Commit: dc1290f0213652eb5466cadda5cae291586f4bf1
Parents: 9be69cc
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 14:44:36 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 14:44:36 2016 +1100

----------------------------------------------------------------------
 libcloud/test/common/test_digitalocean_v2.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/dc1290f0/libcloud/test/common/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v2.py b/libcloud/test/common/test_digitalocean_v2.py
index e1582ea..21d855e 100644
--- a/libcloud/test/common/test_digitalocean_v2.py
+++ b/libcloud/test/common/test_digitalocean_v2.py
@@ -96,8 +96,8 @@ class DigitalOceanMockHttp(MockHttpTestCase):
 
     def _v2_actions_page_1(self, method, url, body, headers):
         body = self.fixtures.load('_v2_actions_page_1.json')
-        return (self.response[None], body, {},
-                httplib.responses[self.response[None]])
+        return (httplib.OK, body, {},
+                httplib.responses[httplib.OK])
 
 
 if __name__ == '__main__':


[27/33] libcloud git commit: Setup CA cert verification for compatibility with previous libcloud (but requests bundles CA now), fixed route53 tests, fixed httplib_ssl tests

Posted by an...@apache.org.
Setup CA cert verification for compatibility with previous libcloud (but requests bundles CA now), fixed route53 tests, fixed httplib_ssl tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/3a492b8a
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/3a492b8a
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/3a492b8a

Branch: refs/heads/requests
Commit: 3a492b8abca690093513a24433b899dd3bf1de4b
Parents: d0f6d22
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 16:30:10 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 16:30:10 2016 +1000

----------------------------------------------------------------------
 libcloud/httplib_ssl.py                         | 17 ++++-
 libcloud/test/dns/fixtures/route53/get_zone.xml |  1 -
 .../fixtures/route53/record_does_not_exist.xml  | 17 -----
 libcloud/test/test_httplib_ssl.py               | 66 --------------------
 libcloud/test/test_response_classes.py          | 14 ++---
 5 files changed, 23 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index b8d9286..1207243 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -21,6 +21,7 @@ import socket
 
 import requests
 
+import libcloud.security
 from libcloud.utils.py3 import urlparse
 
 
@@ -68,8 +69,12 @@ class LibcloudBaseConnection(object):
 
     http_proxy_used = False
 
+    ca_cert = None
+
     def __init__(self):
         self.session = requests.Session()
+        self.verify = True
+        self.ca_cert = None
 
     def set_http_proxy(self, proxy_url):
         """
@@ -137,6 +142,15 @@ class LibcloudBaseConnection(object):
         return (proxy_scheme, proxy_host, proxy_port, proxy_username,
                 proxy_password)
 
+    def _setup_verify(self):
+        self.verify = libcloud.security.VERIFY_SSL_CERT
+
+    def _setup_ca_cert(self):
+        if self.verify is False:
+            pass
+        else:
+            self.ca_cert = libcloud.security.CA_CERTS_PATH
+
 
 class LibcloudConnection(LibcloudBaseConnection):
     timeout = None
@@ -165,7 +179,8 @@ class LibcloudConnection(LibcloudBaseConnection):
             data=body,
             headers=headers,
             allow_redirects=1,
-            stream=raw
+            stream=raw,
+            verify=self.ca_cert if self.ca_cert is not None else self.verify
         )
 
     def getresponse(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/dns/fixtures/route53/get_zone.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/route53/get_zone.xml b/libcloud/test/dns/fixtures/route53/get_zone.xml
index 3a1ffbe..c7e5be8 100644
--- a/libcloud/test/dns/fixtures/route53/get_zone.xml
+++ b/libcloud/test/dns/fixtures/route53/get_zone.xml
@@ -1,4 +1,3 @@
-
 <?xml version="1.0" encoding="UTF-8"?>
 <GetHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
    <HostedZone>

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml b/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
deleted file mode 100644
index 6a767d1..0000000
--- a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
-   <ResourceRecordSets>
-
-      <ResourceRecordSet>
-         <Name>definitely.not.what.you.askedfor.t.com</Name>
-         <Type>CNAME</Type>
-         <TTL>86400</TTL>
-         <ResourceRecords>
-            <ResourceRecord>
-               <Value>t.com</Value>
-            </ResourceRecord>
-         </ResourceRecords>
-      </ResourceRecordSet>
-
-  </ResourceRecordSets>
-</ListResourceRecordSetsResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/test_httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_httplib_ssl.py b/libcloud/test/test_httplib_ssl.py
index 55d1b23..9c96df4 100644
--- a/libcloud/test/test_httplib_ssl.py
+++ b/libcloud/test/test_httplib_ssl.py
@@ -70,20 +70,6 @@ class TestHttpLibSSLTests(unittest.TestCase):
         self.assertEqual(libcloud.security.CA_CERTS_PATH, [file_path])
 
     @patch('warnings.warn')
-    def test_setup_verify(self, _):
-        libcloud.security.CA_CERTS_PATH = []
-
-        # Should throw a runtime error
-        libcloud.security.VERIFY_SSL_CERT = True
-
-        expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG
-        self.assertRaisesRegexp(RuntimeError, expected_msg,
-                                self.httplib_object._setup_verify)
-
-        libcloud.security.VERIFY_SSL_CERT = False
-        self.httplib_object._setup_verify()
-
-    @patch('warnings.warn')
     def test_setup_ca_cert(self, _):
         # verify = False, _setup_ca_cert should be a no-op
         self.httplib_object.verify = False
@@ -100,58 +86,6 @@ class TestHttpLibSSLTests(unittest.TestCase):
 
         self.assertTrue(self.httplib_object.ca_cert is not None)
 
-        # verify = True, no CA certs are available, exception should be thrown
-        libcloud.security.CA_CERTS_PATH = []
-
-        expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG
-        self.assertRaisesRegexp(RuntimeError, expected_msg,
-                                self.httplib_object._setup_ca_cert)
-
-    @mock.patch('socket.create_connection', mock.MagicMock())
-    @mock.patch('socket.socket', mock.MagicMock())
-    @mock.patch('ssl.wrap_socket')
-    def test_connect_throws_friendly_error_message_on_ssl_wrap_connection_reset_by_peer(self, mock_wrap_socket):
-        # Test that we re-throw a more friendly error message in case
-        # "connection reset by peer" error occurs when trying to establish a
-        # SSL connection
-        libcloud.security.VERIFY_SSL_CERT = True
-        self.httplib_object.verify = True
-        self.httplib_object.http_proxy_used = False
-
-        # No connection reset by peer, original exception should be thrown
-        mock_wrap_socket.side_effect = Exception('foo bar fail')
-
-        expected_msg = 'foo bar fail'
-        self.assertRaisesRegexp(Exception, expected_msg,
-                                self.httplib_object.connect)
-
-        # Connection reset by peer, wrapped exception with friendly error
-        # message should be thrown
-        mock_wrap_socket.side_effect = socket.error('Connection reset by peer')
-
-        expected_msg = 'Failed to establish SSL / TLS connection'
-        self.assertRaisesRegexp(socket.error, expected_msg,
-                                self.httplib_object.connect)
-
-        # Same error but including errno
-        with self.assertRaises(socket.error) as cm:
-            mock_wrap_socket.side_effect = socket.error(104, 'Connection reset by peer')
-            self.httplib_object.connect()
-
-        e = cm.exception
-        self.assertEqual(e.errno, 104)
-        self.assertTrue(expected_msg in str(e))
-
-        # Test original exception is propagated correctly on non reset by peer
-        # error
-        with self.assertRaises(socket.error) as cm:
-            mock_wrap_socket.side_effect = socket.error(105, 'Some random error')
-            self.httplib_object.connect()
-
-        e = cm.exception
-        self.assertEqual(e.errno, 105)
-        self.assertTrue('Some random error' in str(e))
-
 
 if __name__ == '__main__':
     sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/test_response_classes.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_response_classes.py b/libcloud/test/test_response_classes.py
index ceeab4c..0bdd06a 100644
--- a/libcloud/test/test_response_classes.py
+++ b/libcloud/test/test_response_classes.py
@@ -34,7 +34,7 @@ class ResponseClassesTests(unittest.TestCase):
         self._mock_connection = Mock()
 
     def test_XmlResponse_class(self):
-        self._mock_response.read.return_value = '<foo>bar</foo>'
+        self._mock_response.text = '<foo>bar</foo>'
         response = XmlResponse(response=self._mock_response,
                                connection=self._mock_connection)
 
@@ -43,7 +43,7 @@ class ResponseClassesTests(unittest.TestCase):
         self.assertEqual(parsed.text, 'bar')
 
     def test_XmlResponse_class_malformed_response(self):
-        self._mock_response.read.return_value = '<foo>'
+        self._mock_response.text = '<foo>'
 
         try:
             XmlResponse(response=self._mock_response,
@@ -54,7 +54,7 @@ class ResponseClassesTests(unittest.TestCase):
             self.fail('Exception was not thrown')
 
     def test_XmlResponse_class_zero_length_body_strip(self):
-        self._mock_response.read.return_value = ' '
+        self._mock_response.text = ' '
 
         response = XmlResponse(response=self._mock_response,
                                connection=self._mock_connection)
@@ -71,7 +71,7 @@ class ResponseClassesTests(unittest.TestCase):
         self.assertEqual(parsed, {'foo': 'bar'})
 
     def test_JsonResponse_class_malformed_response(self):
-        self._mock_response.read.return_value = '{"foo": "bar'
+        self._mock_response.text = '{"foo": "bar'
 
         try:
             JsonResponse(response=self._mock_response,
@@ -82,7 +82,7 @@ class ResponseClassesTests(unittest.TestCase):
             self.fail('Exception was not thrown')
 
     def test_JsonResponse_class_zero_length_body_strip(self):
-        self._mock_response.read.return_value = ' '
+        self._mock_response.text = ' '
 
         response = JsonResponse(response=self._mock_response,
                                 connection=self._mock_connection)
@@ -94,7 +94,7 @@ class ResponseClassesTests(unittest.TestCase):
         original_data = 'foo bar ponies, wooo zlib'
         compressed_data = zlib.compress(b(original_data))
 
-        self._mock_response.read.return_value = compressed_data
+        self._mock_response.text = compressed_data
         self._mock_response.getheaders.return_value = \
             {'Content-Encoding': 'deflate'}
 
@@ -127,7 +127,7 @@ class ResponseClassesTests(unittest.TestCase):
         stream.close()
         compressed_data = string_io.getvalue()
 
-        self._mock_response.read.return_value = compressed_data
+        self._mock_response.text = compressed_data
         self._mock_response.getheaders.return_value = \
             {'Content-Encoding': 'gzip'}
 


[09/33] libcloud git commit: Use PEP0328 to fix import errors now that I moved logging connection to a more logical module

Posted by an...@apache.org.
Use PEP0328 to fix import errors now that I moved logging connection to a more logical module


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6cc6e3c5
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6cc6e3c5
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6cc6e3c5

Branch: refs/heads/requests
Commit: 6cc6e3c5c6d57a98c455d8d41ec1e83e9a7d28e4
Parents: 30d27bb
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 15:48:20 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 15:48:20 2016 +1100

----------------------------------------------------------------------
 libcloud/utils/loggingconnection.py | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6cc6e3c5/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index f6926e8..02a2a41 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -13,6 +13,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from __future__ import absolute_import
+
 try:
     import simplejson as json
 except:


[32/33] libcloud git commit: Fix linting errors

Posted by an...@apache.org.
Fix linting errors


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/04d4655b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/04d4655b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/04d4655b

Branch: refs/heads/requests
Commit: 04d4655b29a25677324557c4a8caad19944e4966
Parents: 6c2d57c
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 18:04:02 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 18:04:02 2016 +1000

----------------------------------------------------------------------
 libcloud/common/base.py           | 2 +-
 libcloud/test/compute/test_gce.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/04d4655b/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index fa1f0ba..b1ec3d9 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -151,7 +151,7 @@ class Response(object):
         self.headers = lowercase_keys(dict(response.headers))
         self.error = response.reason
         self.status = response.status_code
-        
+
         if isinstance(response.text, basestring):
             self.body = response.text.strip() \
                 if response.text is not None else ''

http://git-wip-us.apache.org/repos/asf/libcloud/blob/04d4655b/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py
index e315e2d..90699ef 100644
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@ -30,7 +30,7 @@ from libcloud.compute.drivers.gce import (GCENodeDriver, API_VERSION,
                                           GCEZone)
 from libcloud.common.google import (GoogleBaseAuthConnection,
                                     ResourceNotFoundError, ResourceExistsError,
-                                    InvalidRequestError, GoogleBaseError)
+                                    GoogleBaseError)
 from libcloud.test.common.test_google import GoogleAuthMockHttp, GoogleTestCase
 from libcloud.compute.base import Node, StorageVolume
 


[14/33] libcloud git commit: Update package import for logging connection

Posted by an...@apache.org.
Update package import for logging connection


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0f9f53ea
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0f9f53ea
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0f9f53ea

Branch: refs/heads/requests
Commit: 0f9f53ea3f51a54b0d85d2a378ac2e3ff9f86a3d
Parents: 6fd28b6
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 21:05:22 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 21:05:22 2016 +1100

----------------------------------------------------------------------
 libcloud/__init__.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0f9f53ea/libcloud/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/__init__.py b/libcloud/__init__.py
index bc68d73..256c39c 100644
--- a/libcloud/__init__.py
+++ b/libcloud/__init__.py
@@ -39,9 +39,9 @@ def enable_debug(fo):
     :param fo: Where to append debugging information
     :type fo: File like object, only write operations are used.
     """
-    from libcloud.common.base import (Connection,
-                                      LoggingConnection)
-    LoggingConnection.log = fo
+    from libcloud.common.base import Connection
+    from libcloud.utils.loggingconnection import LoggingConnection
+
     LoggingConnection.log = fo
     Connection.conn_class = LoggingConnection
 


[04/33] libcloud git commit: Add requests as a required installed package

Posted by an...@apache.org.
Add requests as a required installed package


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/c3fab310
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c3fab310
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c3fab310

Branch: refs/heads/requests
Commit: c3fab3104bb393c8e9de1fadb68b42b8a08aef7b
Parents: b2f5b22
Author: anthony-shaw <an...@gmail.com>
Authored: Sat Mar 26 21:02:42 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sat Mar 26 21:02:42 2016 +1100

----------------------------------------------------------------------
 setup.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c3fab310/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index e8cc1bf..19926ef 100644
--- a/setup.py
+++ b/setup.py
@@ -253,7 +253,7 @@ class CoverageCommand(Command):
 
 forbid_publish()
 
-install_requires = []
+install_requires = ['requests']
 if PY2_pre_26:
     install_requires.extend(['ssl', 'simplejson'])
 


[15/33] libcloud git commit: Fix rackspace tests

Posted by an...@apache.org.
Fix rackspace tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0d1fdcec
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0d1fdcec
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0d1fdcec

Branch: refs/heads/requests
Commit: 0d1fdcec8864dda5e70259191bac3231e84b4df6
Parents: 0f9f53e
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 21:11:57 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 21:11:57 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_rackspace.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0d1fdcec/libcloud/test/compute/test_rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_rackspace.py b/libcloud/test/compute/test_rackspace.py
index 3c31316..43920e8 100644
--- a/libcloud/test/compute/test_rackspace.py
+++ b/libcloud/test/compute/test_rackspace.py
@@ -184,7 +184,7 @@ class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
     driver_args = RACKSPACE_NOVA_PARAMS
     driver_kwargs = {'region': 'lon'}
 
-    conn_classes = (RackspaceNovaLonMockHttp, RackspaceNovaLonMockHttp)
+    conn_classes = RackspaceNovaLonMockHttp
     auth_url = 'https://lon.auth.api.example.com'
 
     expected_endpoint = 'https://lon.servers.api.rackspacecloud.com/v2/1337'


[02/33] libcloud git commit: Remove the double connect hack

Posted by an...@apache.org.
Remove the double connect hack


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/649c70e7
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/649c70e7
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/649c70e7

Branch: refs/heads/requests
Commit: 649c70e7029118d82128f2f6e35a22ca8f85be74
Parents: cb0f499
Author: anthony-shaw <an...@gmail.com>
Authored: Sat Mar 26 20:42:04 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sat Mar 26 20:42:04 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/649c70e7/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 6f62e0d..ab642f3 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -602,9 +602,6 @@ class Connection(object):
         else:
             url = action
 
-        # Removed terrible hack...this a less-bad hack that doesn't execute a
-        # request twice, but it's still a hack.
-        self.connect()
         try:
             # @TODO: Should we just pass File object as body to request method
             # instead of dealing with splitting and sending the file ourselves?


[31/33] libcloud git commit: Remove broken test, fix lua and NSFN tests

Posted by an...@apache.org.
Remove broken test, fix lua and NSFN tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6c2d57c0
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6c2d57c0
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6c2d57c0

Branch: refs/heads/requests
Commit: 6c2d57c09dfc5285706d26e0d4860cc870d4af2d
Parents: e1765b9
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 18:02:11 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 18:02:11 2016 +1000

----------------------------------------------------------------------
 libcloud/common/base.py           | 10 +++++++---
 libcloud/test/compute/test_gce.py |  7 -------
 libcloud/test/dns/test_luadns.py  |  3 +--
 libcloud/test/dns/test_nfsn.py    |  2 +-
 4 files changed, 9 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6c2d57c0/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 60cfb04..fa1f0ba 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -36,7 +36,7 @@ import requests
 
 import libcloud
 
-from libcloud.utils.py3 import PY25
+from libcloud.utils.py3 import PY25, basestring
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import urlencode
@@ -151,8 +151,12 @@ class Response(object):
         self.headers = lowercase_keys(dict(response.headers))
         self.error = response.reason
         self.status = response.status_code
-
-        self.body = response.text.strip() if response.text is not None else ''
+        
+        if isinstance(response.text, basestring):
+            self.body = response.text.strip() \
+                if response.text is not None else ''
+        else:
+            self.body = ''
 
         if not self.success():
             raise exception_from_message(code=self.status,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6c2d57c0/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py
index 2e386aa..e315e2d 100644
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@ -485,13 +485,6 @@ class GCENodeDriverTest(GoogleTestCase, TestCaseMixin):
         self.assertRaises(GoogleBaseError, self.driver.ex_set_machine_type,
                           node, 'custom-4-61440')
 
-    def test_ex_set_machine_type_invalid(self):
-        # get stopped node, change machine type
-        zone = 'us-central1-a'
-        node = self.driver.ex_get_node('custom-node', zone)
-        self.assertRaises(InvalidRequestError, self.driver.ex_set_machine_type,
-                          node, 'custom-1-61440')
-
     def test_ex_set_machine_type(self):
         # get stopped node, change machine type
         zone = 'us-central1-a'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6c2d57c0/libcloud/test/dns/test_luadns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_luadns.py b/libcloud/test/dns/test_luadns.py
index 1bacf98..03ee898 100644
--- a/libcloud/test/dns/test_luadns.py
+++ b/libcloud/test/dns/test_luadns.py
@@ -16,8 +16,7 @@ class LuadnsTests(unittest.TestCase):
 
     def setUp(self):
         LuadnsMockHttp.type = None
-        LuadnsDNSDriver.connectionCls.conn_classes = (
-            None, LuadnsMockHttp)
+        LuadnsDNSDriver.connectionCls.conn_class = LuadnsMockHttp
         self.driver = LuadnsDNSDriver(*DNS_PARAMS_LUADNS)
         self.test_zone = Zone(id='11', type='master', ttl=None,
                               domain='example.com', extra={},

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6c2d57c0/libcloud/test/dns/test_nfsn.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_nfsn.py b/libcloud/test/dns/test_nfsn.py
index 0a07c2a..b6bfb3a 100644
--- a/libcloud/test/dns/test_nfsn.py
+++ b/libcloud/test/dns/test_nfsn.py
@@ -29,7 +29,7 @@ from libcloud.test.file_fixtures import DNSFileFixtures
 class NFSNTestCase(LibcloudTestCase):
 
     def setUp(self):
-        NFSNDNSDriver.connectionCls.conn_classes = (None, NFSNMockHttp)
+        NFSNDNSDriver.connectionCls.conn_class = NFSNMockHttp
         NFSNMockHttp.type = None
         self.driver = NFSNDNSDriver('testid', 'testsecret')
 


[20/33] libcloud git commit: Fix rackspace tests

Posted by an...@apache.org.
Fix rackspace tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/14b68f59
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/14b68f59
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/14b68f59

Branch: refs/heads/requests
Commit: 14b68f59e7c3180846e41fe726d43bdaffdb5327
Parents: d95474e
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 15:16:45 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 15:16:45 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_rackspace.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/14b68f59/libcloud/test/compute/test_rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_rackspace.py b/libcloud/test/compute/test_rackspace.py
index 43920e8..5d418fe 100644
--- a/libcloud/test/compute/test_rackspace.py
+++ b/libcloud/test/compute/test_rackspace.py
@@ -184,7 +184,7 @@ class RackspaceNovaLonTests(BaseRackspaceNovaTestCase, OpenStack_1_1_Tests):
     driver_args = RACKSPACE_NOVA_PARAMS
     driver_kwargs = {'region': 'lon'}
 
-    conn_classes = RackspaceNovaLonMockHttp
+    conn_class = RackspaceNovaLonMockHttp
     auth_url = 'https://lon.auth.api.example.com'
 
     expected_endpoint = 'https://lon.servers.api.rackspacecloud.com/v2/1337'


[28/33] libcloud git commit: Fix response class tests, fix route53 missing file. Added requests_mock as a testing dependency.

Posted by an...@apache.org.
Fix response class tests, fix route53 missing file. Added requests_mock as a testing dependency.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6b9f90c5
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6b9f90c5
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6b9f90c5

Branch: refs/heads/requests
Commit: 6b9f90c59faae02cfcd92d41c412291377a9331e
Parents: 3a492b8
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 17:45:01 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 17:45:01 2016 +1000

----------------------------------------------------------------------
 libcloud/common/base.py                         |   7 +-
 .../fixtures/route53/record_does_not_exist.xml  |  17 +++
 libcloud/test/test_response_classes.py          | 144 ++++++-------------
 requirements-tests.txt                          |   3 +-
 setup.py                                        |   3 +-
 5 files changed, 70 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6b9f90c5/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 67d66b1..60cfb04 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -148,11 +148,11 @@ class Response(object):
 
         # http.client In Python 3 doesn't automatically lowercase the header
         # names
-        self.headers = lowercase_keys(dict(response.getheaders()))
+        self.headers = lowercase_keys(dict(response.headers))
         self.error = response.reason
         self.status = response.status_code
 
-        self.body = response.text if response.text is not None else ''
+        self.body = response.text.strip() if response.text is not None else ''
 
         if not self.success():
             raise exception_from_message(code=self.status,
@@ -226,8 +226,7 @@ class JsonResponse(Response):
     """
 
     def parse_body(self):
-        if self.body is not None and \
-        len(self.body) == 0 and not self.parse_zero_length_body:
+        if len(self.body) == 0 and not self.parse_zero_length_body:
             return self.body
 
         try:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6b9f90c5/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml b/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
new file mode 100644
index 0000000..6a767d1
--- /dev/null
+++ b/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/">
+   <ResourceRecordSets>
+
+      <ResourceRecordSet>
+         <Name>definitely.not.what.you.askedfor.t.com</Name>
+         <Type>CNAME</Type>
+         <TTL>86400</TTL>
+         <ResourceRecords>
+            <ResourceRecord>
+               <Value>t.com</Value>
+            </ResourceRecord>
+         </ResourceRecords>
+      </ResourceRecordSet>
+
+  </ResourceRecordSets>
+</ListResourceRecordSetsResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6b9f90c5/libcloud/test/test_response_classes.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_response_classes.py b/libcloud/test/test_response_classes.py
index 0bdd06a..37d2386 100644
--- a/libcloud/test/test_response_classes.py
+++ b/libcloud/test/test_response_classes.py
@@ -15,137 +15,85 @@
 
 import sys
 import unittest
-import zlib
-import gzip
 
-from mock import Mock
+import requests
+import requests_mock
 
-from libcloud.utils.py3 import httplib, b, StringIO, PY3
-from libcloud.common.base import Response, XmlResponse, JsonResponse
+from libcloud.common.base import XmlResponse, JsonResponse
 from libcloud.common.types import MalformedResponseError
+from libcloud.httplib_ssl import LibcloudConnection
 
 
 class ResponseClassesTests(unittest.TestCase):
     def setUp(self):
-        self._mock_response = Mock()
-        self._mock_response.getheaders.return_value = []
-        self._mock_response.status = httplib.OK
-        self._mock_response._original_data = None
-        self._mock_connection = Mock()
+        self.mock_connection = LibcloudConnection(host='mock.com', port=80)
+        self.mock_connection.driver = None
 
     def test_XmlResponse_class(self):
-        self._mock_response.text = '<foo>bar</foo>'
-        response = XmlResponse(response=self._mock_response,
-                               connection=self._mock_connection)
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/2', text='<foo>bar</foo>')
+            response_obj = requests.get('mock://test.com/2')
+            response = XmlResponse(response=response_obj,
+                                   connection=self.mock_connection)
 
         parsed = response.parse_body()
         self.assertEqual(parsed.tag, 'foo')
         self.assertEqual(parsed.text, 'bar')
 
     def test_XmlResponse_class_malformed_response(self):
-        self._mock_response.text = '<foo>'
-
-        try:
-            XmlResponse(response=self._mock_response,
-                        connection=self._mock_connection)
-        except MalformedResponseError:
-            pass
-        else:
-            self.fail('Exception was not thrown')
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/', text='<foo>')
+            response_obj = requests.get('mock://test.com/')
+            try:
+                XmlResponse(response=response_obj,
+                            connection=self.mock_connection)
+            except MalformedResponseError:
+                pass
+            else:
+                self.fail('Exception was not thrown')
 
     def test_XmlResponse_class_zero_length_body_strip(self):
-        self._mock_response.text = ' '
-
-        response = XmlResponse(response=self._mock_response,
-                               connection=self._mock_connection)
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/', text=' ')
+            response_obj = requests.get('mock://test.com/')
+            response = XmlResponse(response=response_obj,
+                                   connection=self.mock_connection)
 
         parsed = response.parse_body()
         self.assertEqual(parsed, '')
 
     def test_JsonResponse_class_success(self):
-        self._mock_response.read.return_value = '{"foo": "bar"}'
-        response = JsonResponse(response=self._mock_response,
-                                connection=self._mock_connection)
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/', text='{"foo": "bar"}')
+            response_obj = requests.get('mock://test.com/')
+            response = JsonResponse(response=response_obj,
+                                    connection=self.mock_connection)
 
         parsed = response.parse_body()
         self.assertEqual(parsed, {'foo': 'bar'})
 
     def test_JsonResponse_class_malformed_response(self):
-        self._mock_response.text = '{"foo": "bar'
-
-        try:
-            JsonResponse(response=self._mock_response,
-                         connection=self._mock_connection)
-        except MalformedResponseError:
-            pass
-        else:
-            self.fail('Exception was not thrown')
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/', text='{"foo": "bar"')
+            response_obj = requests.get('mock://test.com/')
+            try:
+                JsonResponse(response=response_obj,
+                             connection=self.mock_connection)
+            except MalformedResponseError:
+                pass
+            else:
+                self.fail('Exception was not thrown')
 
     def test_JsonResponse_class_zero_length_body_strip(self):
-        self._mock_response.text = ' '
-
-        response = JsonResponse(response=self._mock_response,
-                                connection=self._mock_connection)
+        with requests_mock.mock() as m:
+            m.register_uri('GET', 'mock://test.com/', text=' ')
+            response_obj = requests.get('mock://test.com/')
+            response = JsonResponse(response=response_obj,
+                                    connection=self.mock_connection)
 
         parsed = response.parse_body()
         self.assertEqual(parsed, '')
 
-    def test_deflate_encoding(self):
-        original_data = 'foo bar ponies, wooo zlib'
-        compressed_data = zlib.compress(b(original_data))
-
-        self._mock_response.text = compressed_data
-        self._mock_response.getheaders.return_value = \
-            {'Content-Encoding': 'deflate'}
-
-        response = Response(response=self._mock_response,
-                            connection=self._mock_connection)
-
-        body = response.parse_body()
-        self.assertEqual(body, original_data)
-
-        self._mock_response.getheaders.return_value = \
-            {'Content-Encoding': 'zlib'}
-
-        response = Response(response=self._mock_response,
-                            connection=self._mock_connection)
-
-        body = response.parse_body()
-        self.assertEqual(body, original_data)
-
-    def test_gzip_encoding(self):
-        original_data = 'foo bar ponies, wooo gzip'
-
-        if PY3:
-            from io import BytesIO
-            string_io = BytesIO()
-        else:
-            string_io = StringIO()
-
-        stream = gzip.GzipFile(fileobj=string_io, mode='w')
-        stream.write(b(original_data))
-        stream.close()
-        compressed_data = string_io.getvalue()
-
-        self._mock_response.text = compressed_data
-        self._mock_response.getheaders.return_value = \
-            {'Content-Encoding': 'gzip'}
-
-        response = Response(response=self._mock_response,
-                            connection=self._mock_connection)
-
-        body = response.parse_body()
-        self.assertEqual(body, original_data)
-
-        self._mock_response.getheaders.return_value = \
-            {'Content-Encoding': 'x-gzip'}
-
-        response = Response(response=self._mock_response,
-                            connection=self._mock_connection)
-
-        body = response.parse_body()
-        self.assertEqual(body, original_data)
-
 
 if __name__ == '__main__':
     sys.exit(unittest.main())

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6b9f90c5/requirements-tests.txt
----------------------------------------------------------------------
diff --git a/requirements-tests.txt b/requirements-tests.txt
index 3a40ef0..22317b2 100644
--- a/requirements-tests.txt
+++ b/requirements-tests.txt
@@ -1,4 +1,5 @@
 pep8>=1.7.0,<1.8
 flake8>=2.5.1,<2.6
 mock>=1.0.1,<1.1
-requests
\ No newline at end of file
+requests
+requests_mock
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6b9f90c5/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index dc1589f..351fcb9 100644
--- a/setup.py
+++ b/setup.py
@@ -60,7 +60,8 @@ SUPPORTED_VERSIONS = ['2.5', '2.6', '2.7', 'PyPy', '3.x']
 
 TEST_REQUIREMENTS = [
     'mock',
-    'requests'
+    'requests',
+    'requests-mock'
 ]
 
 if PY2_pre_279 or PY3_pre_32:


[12/33] libcloud git commit: Refactor all the unit tests to only have 1 mock connection class and use Connection.conn_class instead of Connection.conn_classes (tuple)

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_backblaze_b2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_backblaze_b2.py b/libcloud/test/storage/test_backblaze_b2.py
index eea9f11..728f348 100644
--- a/libcloud/test/storage/test_backblaze_b2.py
+++ b/libcloud/test/storage/test_backblaze_b2.py
@@ -38,8 +38,7 @@ class BackblazeB2StorageDriverTestCase(unittest.TestCase):
 
     def setUp(self):
         self.driver_klass.connectionCls.authCls = MockAuthConn()
-        self.driver_klass.connectionCls.conn_classes = (
-            None, BackblazeB2MockHttp)
+        self.driver_klass.connectionCls.conn_class = BackblazeB2MockHttp
         self.driver_klass.connectionCls.rawResponseCls = \
             BackblazeB2MockRawResponse
         BackblazeB2MockHttp.type = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_base.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_base.py b/libcloud/test/storage/test_base.py
index 5c234b8..91bbe2f 100644
--- a/libcloud/test/storage/test_base.py
+++ b/libcloud/test/storage/test_base.py
@@ -36,7 +36,7 @@ class BaseStorageTests(unittest.TestCase):
 
     def setUp(self):
         self.send_called = 0
-        StorageDriver.connectionCls.conn_classes = (None, StorageMockHttp)
+        StorageDriver.connectionCls.conn_class = StorageMockHttp
 
         self.driver1 = StorageDriver('username', 'key', host='localhost')
         self.driver1.supports_chunked_encoding = True

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_cloudfiles.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_cloudfiles.py b/libcloud/test/storage/test_cloudfiles.py
index 3e911da..dad51b3 100644
--- a/libcloud/test/storage/test_cloudfiles.py
+++ b/libcloud/test/storage/test_cloudfiles.py
@@ -55,8 +55,7 @@ class CloudFilesTests(unittest.TestCase):
     region = 'ord'
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = (
-            None, CloudFilesMockHttp)
+        self.driver_klass.connectionCls.conn_class = CloudFilesMockHttp
         self.driver_klass.connectionCls.rawResponseCls = \
             CloudFilesMockRawResponse
         CloudFilesMockHttp.type = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_oss.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_oss.py b/libcloud/test/storage/test_oss.py
index e5eb24f..32a5aca 100644
--- a/libcloud/test/storage/test_oss.py
+++ b/libcloud/test/storage/test_oss.py
@@ -418,8 +418,7 @@ class OSSStorageDriverTestCase(unittest.TestCase):
         return self.driver_type(*self.driver_args)
 
     def setUp(self):
-        self.driver_type.connectionCls.conn_classes = (
-            None, self.mock_response_klass)
+        self.driver_type.connectionCls.conn_class = self.mock_response_klass
         self.driver_type.connectionCls.rawResponseCls = \
             self.mock_raw_response_klass
         self.mock_response_klass.type = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_s3.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_s3.py b/libcloud/test/storage/test_s3.py
index 2a6e873..95f83de 100644
--- a/libcloud/test/storage/test_s3.py
+++ b/libcloud/test/storage/test_s3.py
@@ -431,8 +431,7 @@ class S3Tests(unittest.TestCase):
         return self.driver_type(*self.driver_args)
 
     def setUp(self):
-        self.driver_type.connectionCls.conn_classes = (None,
-                                                       self.mock_response_klass)
+        self.driver_type.connectionCls.conn_class = self.mock_response_klass
         self.driver_type.connectionCls.rawResponseCls = \
             self.mock_raw_response_klass
         self.mock_response_klass.type = None


[16/33] libcloud git commit: Fix linting errors

Posted by an...@apache.org.
Fix linting errors


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6326f982
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6326f982
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6326f982

Branch: refs/heads/requests
Commit: 6326f9820eb785ce521c7d376825a4d3e36c8f95
Parents: 0d1fdce
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 21:14:58 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 21:14:58 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py | 2 +-
 libcloud/httplib_ssl.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6326f982/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index acf9a7f..badce2c 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -600,7 +600,7 @@ class Connection(object):
                 url = '?'.join((action, urlencode(params, doseq=True)))
         else:
             url = action
-            
+
         # IF connection has not yet been established
         if self.connection is None:
             self.connect()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6326f982/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index aea5eb6..b8d9286 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -143,7 +143,7 @@ class LibcloudConnection(LibcloudBaseConnection):
     host = None
     response = None
 
-    def __init__(self,  host, port, **kwargs):
+    def __init__(self, host, port, **kwargs):
         self.host = '{}://{}'.format(
             'https' if port == 443 else 'http',
             host


[25/33] libcloud git commit: Fix iter methods for storage tests

Posted by an...@apache.org.
Fix iter methods for storage tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/52778e53
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/52778e53
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/52778e53

Branch: refs/heads/requests
Commit: 52778e53b8a92f41132fe8595853835bd4ae56e0
Parents: 2195434
Author: anthony-shaw <an...@gmail.com>
Authored: Fri Apr 1 09:27:47 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Fri Apr 1 09:27:47 2016 +1100

----------------------------------------------------------------------
 libcloud/test/__init__.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/52778e53/libcloud/test/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/test/__init__.py b/libcloud/test/__init__.py
index 17e1f2f..068de27 100644
--- a/libcloud/test/__init__.py
+++ b/libcloud/test/__init__.py
@@ -89,15 +89,16 @@ class MockResponse(object):
         self.body = body
         self.headers = headers or self.headers
         self.reason = reason or self.reason
+        self.body_iter = iter(self.body) if self.body is not None else None
 
     def read(self, *args, **kwargs):
         return self.body
 
     def next(self):
         if sys.version_info >= (2, 5) and sys.version_info <= (2, 6):
-            return self.body.next()
+            return self.body_iter.next()
         else:
-            return next(self.body)
+            return next(self.body_iter)
 
     def __next__(self):
         return self.next()


[17/33] libcloud git commit: Setup the error handling for the underlying requests library

Posted by an...@apache.org.
Setup the error handling for the underlying requests library


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/9be69cc0
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/9be69cc0
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/9be69cc0

Branch: refs/heads/requests
Commit: 9be69cc0fa3b2563b315281a9dfa688fa9e16b36
Parents: 6326f98
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 14:44:21 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 14:44:21 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py           | 24 +++++++-----------------
 libcloud/common/exceptions.py     |  1 -
 libcloud/test/__init__.py         | 21 +++++++++++++++++++--
 libcloud/test/test_connection.py  |  4 ++--
 libcloud/test/test_httplib_ssl.py |  2 +-
 5 files changed, 29 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/9be69cc0/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index badce2c..40d9c39 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -32,6 +32,8 @@ try:
 except:
     import json
 
+import requests
+
 import libcloud
 
 from libcloud.utils.py3 import PY3, PY25
@@ -149,26 +151,13 @@ class Response(object):
         # names
         self.headers = lowercase_keys(dict(response.getheaders()))
         self.error = response.reason
-        self.status = response.status
-
-        # This attribute is set when using LoggingConnection.
-        original_data = getattr(response, '_original_data', None)
-
-        if original_data:
-            # LoggingConnection already decompresses data so it can log it
-            # which means we don't need to decompress it here.
-            self.body = response._original_data
-        else:
-            self.body = self._decompress_response(body=response.read(),
-                                                  headers=self.headers)
+        self.status = response.status_code
 
-        if PY3:
-            self.body = b(self.body).decode('utf-8')
+        self.body = response.text
 
         if not self.success():
             raise exception_from_message(code=self.status,
-                                         message=self.parse_error(),
-                                         headers=self.headers)
+                                         message=self.parse_error())
 
         self.object = self.parse_body()
 
@@ -204,7 +193,8 @@ class Response(object):
         :rtype: ``bool``
         :return: ``True`` or ``False``
         """
-        return self.status in [httplib.OK, httplib.CREATED]
+        return self.status in [requests.codes.ok, requests.codes.created,
+                               httplib.OK, httplib.CREATED]
 
     def _decompress_response(self, body, headers):
         """

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9be69cc0/libcloud/common/exceptions.py
----------------------------------------------------------------------
diff --git a/libcloud/common/exceptions.py b/libcloud/common/exceptions.py
index 14dcea8..a286ccd 100644
--- a/libcloud/common/exceptions.py
+++ b/libcloud/common/exceptions.py
@@ -70,6 +70,5 @@ def exception_from_message(code, message, headers=None):
 
     if headers and 'retry_after' in headers:
         kwargs['retry_after'] = headers['retry_after']
-
     cls = _code_map.get(code, BaseHTTPError)
     return cls(**kwargs)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9be69cc0/libcloud/test/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/test/__init__.py b/libcloud/test/__init__.py
index 747b02c..cfd076c 100644
--- a/libcloud/test/__init__.py
+++ b/libcloud/test/__init__.py
@@ -15,6 +15,7 @@
 
 import sys
 import random
+import requests
 
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import StringIO
@@ -78,14 +79,14 @@ class MockResponse(object):
     A mock HTTPResponse
     """
     headers = {}
-    body = StringIO()
+    body = None
     status = 0
     reason = ''
     version = 11
 
     def __init__(self, status, body=None, headers=None, reason=None):
         self.status = status
-        self.body = StringIO(u(body)) if body else StringIO()
+        self.body = body
         self.headers = headers or self.headers
         self.reason = reason or self.reason
 
@@ -110,6 +111,17 @@ class MockResponse(object):
     def msg(self):
         raise NotImplemented
 
+    @property
+    def status_code(self):
+        return self.status
+
+    def raise_for_status(self):
+        raise requests.exceptions.HTTPError(self.status)
+
+    @property
+    def text(self):
+        return self.body
+
 
 class BaseMockHttpObject(object):
     def _get_method_name(self, type, use_param, qs, path):
@@ -327,6 +339,11 @@ class MockRawResponse(BaseMockHttpObject):
         return self._status
 
     @property
+    def status_code(self):
+        self._get_response_if_not_availale()
+        return self._status
+
+    @property
     def headers(self):
         self._get_response_if_not_availale()
         return self._headers

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9be69cc0/libcloud/test/test_connection.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_connection.py b/libcloud/test/test_connection.py
index 5a97b45..53cd979 100644
--- a/libcloud/test/test_connection.py
+++ b/libcloud/test/test_connection.py
@@ -86,7 +86,7 @@ class BaseConnectionClassTestCase(unittest.TestCase):
 
         proxy_url = 'http://127.0.0.4:3128'
         conn = LibcloudConnection(host='localhost', port=80,
-                                      proxy_url=proxy_url)
+                                  proxy_url=proxy_url)
         self.assertEqual(conn.proxy_scheme, 'http')
         self.assertEqual(conn.proxy_host, '127.0.0.4')
         self.assertEqual(conn.proxy_port, 3128)
@@ -94,7 +94,7 @@ class BaseConnectionClassTestCase(unittest.TestCase):
         os.environ['http_proxy'] = proxy_url
         proxy_url = 'http://127.0.0.5:3128'
         conn = LibcloudConnection(host='localhost', port=80,
-                                      proxy_url=proxy_url)
+                                  proxy_url=proxy_url)
         self.assertEqual(conn.proxy_scheme, 'http')
         self.assertEqual(conn.proxy_host, '127.0.0.5')
         self.assertEqual(conn.proxy_port, 3128)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/9be69cc0/libcloud/test/test_httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_httplib_ssl.py b/libcloud/test/test_httplib_ssl.py
index 8f5885d..55d1b23 100644
--- a/libcloud/test/test_httplib_ssl.py
+++ b/libcloud/test/test_httplib_ssl.py
@@ -36,7 +36,7 @@ class TestHttpLibSSLTests(unittest.TestCase):
     def setUp(self):
         libcloud.security.VERIFY_SSL_CERT = False
         libcloud.security.CA_CERTS_PATH = ORIGINAL_CA_CERS_PATH
-        self.httplib_object = LibcloudConnection('foo.bar')
+        self.httplib_object = LibcloudConnection('foo.bar', port=80)
 
     def test_custom_ca_path_using_env_var_doesnt_exist(self):
         os.environ['SSL_CERT_FILE'] = '/foo/doesnt/exist'


[08/33] libcloud git commit: Consolidate LibcloudHTTPConnection and LibcloudHTTPSConnection into a single class. Create a session based wrapper for requests. Implement the SSL verification overridding.

Posted by an...@apache.org.
Consolidate LibcloudHTTPConnection and LibcloudHTTPSConnection into a single class. Create a session based wrapper for requests. Implement the SSL verification overridding.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/30d27bbc
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/30d27bbc
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/30d27bbc

Branch: refs/heads/requests
Commit: 30d27bbc198098daedaf6d57742ad2e0bad5118e
Parents: 10cea10
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 15:38:23 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 15:38:23 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py             |  11 ++-
 libcloud/httplib_ssl.py             | 140 +++++++++++--------------------
 libcloud/test/test_connection.py    |  29 +------
 libcloud/test/test_httplib_ssl.py   |   4 +-
 libcloud/utils/loggingconnection.py |   4 +-
 requirements-tests.txt              |   1 +
 setup.py                            |   3 +-
 7 files changed, 65 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index ab642f3..22852b4 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -45,8 +45,7 @@ from libcloud.utils.compression import decompress_data
 
 from libcloud.common.exceptions import exception_from_message
 from libcloud.common.types import LibcloudError, MalformedResponseError
-from libcloud.httplib_ssl import LibcloudHTTPConnection
-from libcloud.httplib_ssl import LibcloudHTTPSConnection
+from libcloud.httplib_ssl import LibcloudConnection
 
 __all__ = [
     'RETRY_FAILED_HTTP_REQUESTS',
@@ -319,8 +318,8 @@ class Connection(object):
     """
     A Base Connection class to derive from.
     """
-    # conn_classes = (LoggingHTTPSConnection)
-    conn_classes = (LibcloudHTTPConnection, LibcloudHTTPSConnection)
+    # conn_class = LoggingHTTPSConnection
+    conn_class = LibcloudConnection
 
     responseCls = Response
     rawResponseCls = RawResponse
@@ -470,12 +469,12 @@ class Connection(object):
         if self.proxy_url:
             kwargs.update({'proxy_url': self.proxy_url})
 
-        connection = self.conn_classes[secure](**kwargs)
+        connection = self.conn_class(**kwargs)
         # You can uncoment this line, if you setup a reverse proxy server
         # which proxies to your endpoint, and lets you easily capture
         # connections in cleartext when you setup the proxy to do SSL
         # for you
-        # connection = self.conn_classes[False]("127.0.0.1", 8080)
+        # connection = self.conn_class("127.0.0.1", 8080)
 
         self.connection = connection
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index ce384d5..aea5eb6 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -18,18 +18,15 @@ verification, depending on libcloud.security settings.
 """
 import os
 import socket
-import warnings
 
 import requests
 
-import libcloud.security
 from libcloud.utils.py3 import urlparse
 
 
 __all__ = [
     'LibcloudBaseConnection',
-    'LibcloudHTTPConnection',
-    'LibcloudHTTPSConnection'
+    'LibcloudConnection'
 ]
 
 HTTP_PROXY_ENV_VARIABLE_NAME = 'http_proxy'
@@ -141,103 +138,64 @@ class LibcloudBaseConnection(object):
                 proxy_password)
 
 
-class LibcloudHTTPConnection(LibcloudBaseConnection):
-    def __init__(self, *args, **kwargs):
-        # Support for HTTP proxy
-        proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
-        proxy_url = kwargs.pop('proxy_url', proxy_url_env)
-
-        super(LibcloudHTTPConnection, self).__init__()
-
-        if proxy_url:
-            self.set_http_proxy(proxy_url=proxy_url)
-
-    def connect():
-        pass
-
-    def request(self, method, url, body=None, headers=None):
-        method = method.lower()
-        if method == 'get':
-            response = self.session.get(url, headers=headers)
-        elif method == 'post':
-            response = self.session.post(url, data=body, headers=headers)
-        elif method == 'head':
-            response = self.session.head(url, headers=headers)
-        return response
-
-
-class LibcloudHTTPSConnection(LibcloudBaseConnection):
-    """
-    LibcloudHTTPSConnection
-
-    Subclass of HTTPSConnection which verifies certificate names
-    if and only if CA certificates are available.
-    """
-    verify = True         # verify by default
-    ca_cert = None        # no default CA Certificate
+class LibcloudConnection(LibcloudBaseConnection):
+    timeout = None
+    host = None
+    response = None
 
-    def __init__(self, *args, **kwargs):
-        """
-        Constructor
-        """
-        self._setup_verify()
+    def __init__(self,  host, port, **kwargs):
+        self.host = '{}://{}'.format(
+            'https' if port == 443 else 'http',
+            host
+        )
         # Support for HTTP proxy
         proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
         proxy_url = kwargs.pop('proxy_url', proxy_url_env)
 
-        super(LibcloudHTTPSConnection, self).__init__()
+        super(LibcloudConnection, self).__init__()
 
         if proxy_url:
             self.set_http_proxy(proxy_url=proxy_url)
-
-    def _setup_verify(self):
-        """
-        Setup Verify SSL or not
-
-        Reads security module's VERIFY_SSL_CERT and toggles whether
-        the class overrides the connect() class method or runs the
-        inherited httplib.HTTPSConnection connect()
-        """
-        self.verify = libcloud.security.VERIFY_SSL_CERT
-
-        if self.verify:
-            self._setup_ca_cert()
-        else:
-            warnings.warn(libcloud.security.VERIFY_SSL_DISABLED_MSG)
-
-    def _setup_ca_cert(self):
-        """
-        Setup CA Certs
-
-        Search in CA_CERTS_PATH for valid candidates and
-        return first match.  Otherwise, complain about certs
-        not being available.
-        """
-        if not self.verify:
-            return
-
-        ca_certs_available = [cert
-                              for cert in libcloud.security.CA_CERTS_PATH
-                              if os.path.exists(cert) and os.path.isfile(cert)]
-        if ca_certs_available:
-            # use first available certificate
-            self.ca_cert = ca_certs_available[0]
-        else:
-            raise RuntimeError(
-                libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG)
-
-    def connect(self):
+        self.session.timeout = kwargs.get('timeout', 60)
+
+    def request(self, method, url, body=None, headers=None, raw=False):
+        self.response = self.session.request(
+            method=method.lower(),
+            url=''.join([self.host, url]),
+            data=body,
+            headers=headers,
+            allow_redirects=1,
+            stream=raw
+        )
+
+    def getresponse(self):
+        return self
+
+    def getheaders(self):
+        # urlib decoded response body, libcloud has a bug
+        # and will not check if content is gzipped, so let's
+        # remove headers indicating compressed content.
+        if 'content-encoding' in self.response.headers:
+            del self.response.headers['content-encoding']
+        return self.response.headers
+
+    @property
+    def status(self):
+        return self.response.status_code
+
+    @property
+    def reason(self):
+        return None if self.response.status_code > 400 else self.response.text
+
+    def connect(self):  # pragma: no cover
         pass
 
-    def request(self, method, url, body=None, headers=None):
-            method = method.lower()
-            if method == 'get':
-                response = requests.get(url, headers=headers)
-            elif method == 'post':
-                response = requests.post(url, data=body, headers=headers)
-            elif method == 'head':
-                response = requests.head(url, headers=headers)
-            return response
+    def read(self):
+        return self.response.content
+
+    def close(self):  # pragma: no cover
+        # return connection back to pool
+        self.response.close()
 
 
 def get_socket_error_exception(ssl_version, exc):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/libcloud/test/test_connection.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_connection.py b/libcloud/test/test_connection.py
index a588ca6..5a97b45 100644
--- a/libcloud/test/test_connection.py
+++ b/libcloud/test/test_connection.py
@@ -23,9 +23,8 @@ from mock import Mock, call, patch
 
 from libcloud.test import unittest
 from libcloud.common.base import Connection
-from libcloud.utils.loggingconnection import LoggingConnection
 from libcloud.httplib_ssl import LibcloudBaseConnection
-from libcloud.httplib_ssl import LibcloudHTTPConnection
+from libcloud.httplib_ssl import LibcloudConnection
 from libcloud.utils.misc import retry
 
 
@@ -74,7 +73,7 @@ class BaseConnectionClassTestCase(unittest.TestCase):
                                 proxy_url=proxy_url)
 
     def test_constructor(self):
-        conn = LibcloudHTTPConnection(host='localhost', port=80)
+        conn = LibcloudConnection(host='localhost', port=80)
         self.assertEqual(conn.proxy_scheme, None)
         self.assertEqual(conn.proxy_host, None)
         self.assertEqual(conn.proxy_port, None)
@@ -86,7 +85,7 @@ class BaseConnectionClassTestCase(unittest.TestCase):
         self.assertEqual(conn.proxy_port, 3128)
 
         proxy_url = 'http://127.0.0.4:3128'
-        conn = LibcloudHTTPConnection(host='localhost', port=80,
+        conn = LibcloudConnection(host='localhost', port=80,
                                       proxy_url=proxy_url)
         self.assertEqual(conn.proxy_scheme, 'http')
         self.assertEqual(conn.proxy_host, '127.0.0.4')
@@ -94,7 +93,7 @@ class BaseConnectionClassTestCase(unittest.TestCase):
 
         os.environ['http_proxy'] = proxy_url
         proxy_url = 'http://127.0.0.5:3128'
-        conn = LibcloudHTTPConnection(host='localhost', port=80,
+        conn = LibcloudConnection(host='localhost', port=80,
                                       proxy_url=proxy_url)
         self.assertEqual(conn.proxy_scheme, 'http')
         self.assertEqual(conn.proxy_host, '127.0.0.5')
@@ -259,26 +258,6 @@ class ConnectionClassTestCase(unittest.TestCase):
 
         self.assertEqual(con.context, {})
 
-    def test_log_curl(self):
-        url = '/test/path'
-        body = None
-        headers = {}
-
-        con = LoggingConnection()
-        con.protocol = 'http'
-        con.host = 'example.com'
-        con.port = 80
-
-        for method in ['GET', 'POST', 'PUT', 'DELETE']:
-            cmd = con._log_curl(method=method, url=url, body=body,
-                                headers=headers)
-            self.assertEqual(cmd, 'curl -i -X %s --compress http://example.com:80/test/path' %
-                             (method))
-
-        # Should use --head for head requests
-        cmd = con._log_curl(method='HEAD', url=url, body=body, headers=headers)
-        self.assertEqual(cmd, 'curl -i --head --compress http://example.com:80/test/path')
-
     def _raise_socket_error(self):
         raise socket.gaierror('')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/libcloud/test/test_httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_httplib_ssl.py b/libcloud/test/test_httplib_ssl.py
index 996498f..8f5885d 100644
--- a/libcloud/test/test_httplib_ssl.py
+++ b/libcloud/test/test_httplib_ssl.py
@@ -24,7 +24,7 @@ from mock import patch
 import libcloud.security
 
 from libcloud.utils.py3 import reload
-from libcloud.httplib_ssl import LibcloudHTTPSConnection
+from libcloud.httplib_ssl import LibcloudConnection
 
 from libcloud.test import unittest
 
@@ -36,7 +36,7 @@ class TestHttpLibSSLTests(unittest.TestCase):
     def setUp(self):
         libcloud.security.VERIFY_SSL_CERT = False
         libcloud.security.CA_CERTS_PATH = ORIGINAL_CA_CERS_PATH
-        self.httplib_object = LibcloudHTTPSConnection('foo.bar')
+        self.httplib_object = LibcloudConnection('foo.bar')
 
     def test_custom_ca_path_using_env_var_doesnt_exist(self):
         os.environ['SSL_CERT_FILE'] = '/foo/doesnt/exist'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index 2b6550d..f6926e8 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -19,7 +19,7 @@ except:
     import json
 
 from pipes import quote as pquote
-import xml.dom.minidom
+from xml.dom.minidom import parseString
 
 import sys
 import os
@@ -104,7 +104,7 @@ class LoggingConnection():
                     pass
             elif pretty_print and content_type == 'text/xml':
                 try:
-                    elem = xml.dom.minidom.parseString(body.decode('utf-8'))
+                    elem = parseString(body.decode('utf-8'))
                     body = elem.toprettyxml()
                 except Exception:
                     # Invalid XML

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/requirements-tests.txt
----------------------------------------------------------------------
diff --git a/requirements-tests.txt b/requirements-tests.txt
index 791dfb5..3a40ef0 100644
--- a/requirements-tests.txt
+++ b/requirements-tests.txt
@@ -1,3 +1,4 @@
 pep8>=1.7.0,<1.8
 flake8>=2.5.1,<2.6
 mock>=1.0.1,<1.1
+requests
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/30d27bbc/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index 19926ef..dc1589f 100644
--- a/setup.py
+++ b/setup.py
@@ -59,7 +59,8 @@ DOC_TEST_MODULES = ['libcloud.compute.drivers.dummy',
 SUPPORTED_VERSIONS = ['2.5', '2.6', '2.7', 'PyPy', '3.x']
 
 TEST_REQUIREMENTS = [
-    'mock'
+    'mock',
+    'requests'
 ]
 
 if PY2_pre_279 or PY3_pre_32:


[05/33] libcloud git commit: Fix module ref for logging connection, fix indenting on logging connection imports

Posted by an...@apache.org.
Fix module ref for logging connection, fix indenting on logging connection imports


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/96f69cfa
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/96f69cfa
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/96f69cfa

Branch: refs/heads/requests
Commit: 96f69cfaac6e8aa255a88eaa8978d11d20470726
Parents: c3fab31
Author: anthony-shaw <an...@gmail.com>
Authored: Sat Mar 26 21:29:07 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sat Mar 26 21:29:07 2016 +1100

----------------------------------------------------------------------
 libcloud/test/test_connection.py    | 2 +-
 libcloud/utils/loggingconnection.py | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/96f69cfa/libcloud/test/test_connection.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_connection.py b/libcloud/test/test_connection.py
index 96e86ce..783ed6a 100644
--- a/libcloud/test/test_connection.py
+++ b/libcloud/test/test_connection.py
@@ -23,7 +23,7 @@ from mock import Mock, call, patch
 
 from libcloud.test import unittest
 from libcloud.common.base import Connection
-from libcloud.common.base import LoggingConnection
+from libcloud.common.utils.loggingconnection import LoggingConnection
 from libcloud.httplib_ssl import LibcloudBaseConnection
 from libcloud.httplib_ssl import LibcloudHTTPConnection
 from libcloud.utils.misc import retry

http://git-wip-us.apache.org/repos/asf/libcloud/blob/96f69cfa/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index b7a1996..bffd8f9 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -25,9 +25,9 @@ import sys
 import os
 import httplib
 
-from libcloud.common.base import LibcloudHTTPConnection, \
-                                 LibcloudHTTPSConnection, \
-                                 HTTPResponse
+from libcloud.common.base import (LibcloudHTTPConnection,
+                                  LibcloudHTTPSConnection,
+                                  HTTPResponse)
 from libcloud.utils.py3 import PY3
 from libcloud.utils.py3 import StringIO
 from libcloud.utils.py3 import u


[10/33] libcloud git commit: Consolidate the logging connection into a single class now that the connection classes are no longer a tuple

Posted by an...@apache.org.
Consolidate the logging connection into a single class now that the connection classes are no longer a tuple


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d52e8eff
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d52e8eff
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d52e8eff

Branch: refs/heads/requests
Commit: d52e8eff25edbdfc5b2f67ec55aad94d67d2c15f
Parents: 6cc6e3c
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 19:29:07 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 19:29:07 2016 +1100

----------------------------------------------------------------------
 libcloud/__init__.py                | 10 ++++----
 libcloud/test/test_init.py          |  9 +++-----
 libcloud/utils/loggingconnection.py | 39 +++++---------------------------
 3 files changed, 13 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d52e8eff/libcloud/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/__init__.py b/libcloud/__init__.py
index 3ed520d..bc68d73 100644
--- a/libcloud/__init__.py
+++ b/libcloud/__init__.py
@@ -40,12 +40,10 @@ def enable_debug(fo):
     :type fo: File like object, only write operations are used.
     """
     from libcloud.common.base import (Connection,
-                                      LoggingHTTPConnection,
-                                      LoggingHTTPSConnection)
-    LoggingHTTPSConnection.log = fo
-    LoggingHTTPConnection.log = fo
-    Connection.conn_classes = (LoggingHTTPConnection,
-                               LoggingHTTPSConnection)
+                                      LoggingConnection)
+    LoggingConnection.log = fo
+    LoggingConnection.log = fo
+    Connection.conn_class = LoggingConnection
 
 
 def _init_once():

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d52e8eff/libcloud/test/test_init.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_init.py b/libcloud/test/test_init.py
index bd428ef..d7069c3 100644
--- a/libcloud/test/test_init.py
+++ b/libcloud/test/test_init.py
@@ -25,8 +25,7 @@ except ImportError:
     have_paramiko = False
 
 from libcloud import _init_once
-from libcloud.utils.loggingconnection import LoggingHTTPConnection
-from libcloud.utils.loggingconnection import LoggingHTTPSConnection
+from libcloud.utils.loggingconnection import LoggingConnection
 
 from libcloud.test import unittest
 
@@ -36,8 +35,7 @@ class TestUtils(unittest.TestCase):
         # Debug mode is disabled
         _init_once()
 
-        self.assertEqual(LoggingHTTPConnection.log, None)
-        self.assertEqual(LoggingHTTPSConnection.log, None)
+        self.assertEqual(LoggingConnection.log, None)
 
         if have_paramiko:
             logger = paramiko.util.logging.getLogger()
@@ -48,8 +46,7 @@ class TestUtils(unittest.TestCase):
         os.environ['LIBCLOUD_DEBUG'] = '/dev/null'
         _init_once()
 
-        self.assertTrue(LoggingHTTPConnection.log is not None)
-        self.assertTrue(LoggingHTTPSConnection.log is not None)
+        self.assertTrue(LoggingConnection.log is not None)
 
         if have_paramiko:
             logger = paramiko.util.logging.getLogger()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d52e8eff/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index 02a2a41..966023a 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -26,8 +26,7 @@ from xml.dom.minidom import parseString
 import sys
 import os
 
-from libcloud.common.base import (LibcloudHTTPConnection,
-                                  LibcloudHTTPSConnection,
+from libcloud.common.base import (LibcloudConnection,
                                   HTTPResponse)
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import PY3
@@ -40,7 +39,7 @@ from libcloud.utils.misc import lowercase_keys
 from libcloud.utils.compression import decompress_data
 
 
-class LoggingConnection():
+class LoggingBaseConnection():
     """
     Debug class to log all HTTP(s) requests as they could be made
     with the curl command.
@@ -170,7 +169,7 @@ class LoggingConnection():
         return " ".join(cmd)
 
 
-class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection):
+class LoggingConnection(LoggingBaseConnection, LibcloudConnection):
     """
     Utility Class for logging HTTPS connections
     """
@@ -178,7 +177,7 @@ class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection):
     protocol = 'https'
 
     def getresponse(self):
-        r = LibcloudHTTPSConnection.getresponse(self)
+        r = LibcloudConnection.getresponse(self)
         if self.log is not None:
             r, rv = self._log_response(r)
             self.log.write(rv + "\n")
@@ -192,31 +191,5 @@ class LoggingHTTPSConnection(LoggingConnection, LibcloudHTTPSConnection):
             self.log.write(pre +
                            self._log_curl(method, url, body, headers) + "\n")
             self.log.flush()
-        return LibcloudHTTPSConnection.request(self, method, url, body,
-                                               headers)
-
-
-class LoggingHTTPConnection(LoggingConnection, LibcloudHTTPConnection):
-    """
-    Utility Class for logging HTTP connections
-    """
-
-    protocol = 'http'
-
-    def getresponse(self):
-        r = LibcloudHTTPConnection.getresponse(self)
-        if self.log is not None:
-            r, rv = self._log_response(r)
-            self.log.write(rv + "\n")
-            self.log.flush()
-        return r
-
-    def request(self, method, url, body=None, headers=None):
-        headers.update({'X-LC-Request-ID': str(id(self))})
-        if self.log is not None:
-            pre = '# -------- begin %d request ----------\n' % id(self)
-            self.log.write(pre +
-                           self._log_curl(method, url, body, headers) + "\n")
-            self.log.flush()
-        return LibcloudHTTPConnection.request(self, method, url,
-                                              body, headers)
+        return LibcloudConnection.request(self, method, url, body,
+                                          headers)


[11/33] libcloud git commit: Fix remaining direct references to the direct module

Posted by an...@apache.org.
Fix remaining direct references to the direct module


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/de1176e2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/de1176e2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/de1176e2

Branch: refs/heads/requests
Commit: de1176e22ffff0c97f32f7f6c95310188ad66406
Parents: d52e8ef
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 19:41:51 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 19:41:51 2016 +1100

----------------------------------------------------------------------
 libcloud/common/runabove.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/de1176e2/libcloud/common/runabove.py
----------------------------------------------------------------------
diff --git a/libcloud/common/runabove.py b/libcloud/common/runabove.py
index 4d45241..72b93da 100644
--- a/libcloud/common/runabove.py
+++ b/libcloud/common/runabove.py
@@ -26,7 +26,7 @@ from libcloud.utils.py3 import httplib
 from libcloud.utils.connection import get_response_object
 from libcloud.common.types import InvalidCredsError
 from libcloud.common.base import ConnectionUserAndKey, JsonResponse
-from libcloud.httplib_ssl import LibcloudHTTPSConnection
+from libcloud.httplib_ssl import LibcloudConnection
 
 __all__ = [
     'RunAboveResponse',
@@ -100,7 +100,7 @@ class RunAboveConnection(ConnectionUserAndKey):
             'Content-Type': 'application/json',
             'X-Ra-Application': user_id,
         }
-        httpcon = LibcloudHTTPSConnection(self.host)
+        httpcon = LibcloudConnection(self.host)
         httpcon.request(method='POST', url=action, body=data, headers=headers)
         response = httpcon.getresponse()
 


[03/33] libcloud git commit: remove httplib wrapper and start on requests

Posted by an...@apache.org.
remove httplib wrapper and start on requests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b2f5b226
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b2f5b226
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b2f5b226

Branch: refs/heads/requests
Commit: b2f5b22622c6fde7c3085afd2e339bdb2eb69f81
Parents: 649c70e
Author: anthony-shaw <an...@gmail.com>
Authored: Sat Mar 26 21:00:50 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sat Mar 26 21:00:50 2016 +1100

----------------------------------------------------------------------
 libcloud/httplib_ssl.py | 78 ++++++++++++++++----------------------------
 1 file changed, 28 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b2f5b226/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index b3e3101..2cf00fb 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -17,19 +17,17 @@ Subclass for httplib.HTTPSConnection with optional certificate name
 verification, depending on libcloud.security settings.
 """
 import os
-import sys
 import socket
-import ssl
 import base64
 import warnings
 
+import requests
+
 import libcloud.security
 from libcloud.utils.py3 import b
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import urlunquote
-from libcloud.utils.py3 import match_hostname
-from libcloud.utils.py3 import CertificateError
 
 
 __all__ = [
@@ -195,7 +193,7 @@ class LibcloudBaseConnection(object):
         self.port = port
 
 
-class LibcloudHTTPConnection(httplib.HTTPConnection, LibcloudBaseConnection):
+class LibcloudHTTPConnection(LibcloudBaseConnection):
     def __init__(self, *args, **kwargs):
         # Support for HTTP proxy
         proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
@@ -206,8 +204,21 @@ class LibcloudHTTPConnection(httplib.HTTPConnection, LibcloudBaseConnection):
         if proxy_url:
             self.set_http_proxy(proxy_url=proxy_url)
 
+        def connect():
+            pass
+
+        def request(method, url, body=None, headers=None):
+            method = method.lower()
+            if method == 'get':
+                response = requests.get(url, headers=headers)
+            elif method == 'post':
+                response = requests.post(url, data=body, headers=headers)
+            elif method == 'head':
+                response = requests.head(url, headers=headers)
+            return response
+
 
-class LibcloudHTTPSConnection(httplib.HTTPSConnection, LibcloudBaseConnection):
+class LibcloudHTTPSConnection(LibcloudBaseConnection):
     """
     LibcloudHTTPSConnection
 
@@ -268,50 +279,17 @@ class LibcloudHTTPSConnection(httplib.HTTPSConnection, LibcloudBaseConnection):
                 libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG)
 
     def connect(self):
-        """
-        Connect
-
-        Checks if verification is toggled; if not, just call
-        httplib.HTTPSConnection's connect
-        """
-        if not self.verify:
-            return httplib.HTTPSConnection.connect(self)
-
-        # otherwise, create a connection and verify the hostname
-        # use socket.create_connection (in 2.6+) if possible
-        if getattr(socket, 'create_connection', None):
-            sock = socket.create_connection((self.host, self.port),
-                                            self.timeout)
-        else:
-            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            sock.connect((self.host, self.port))
-
-        # Activate the HTTP proxy
-        if self.http_proxy_used:
-            self._activate_http_proxy(sock=sock)
-
-        ssl_version = libcloud.security.SSL_VERSION
-
-        try:
-            self.sock = ssl.wrap_socket(
-                sock,
-                self.key_file,
-                self.cert_file,
-                cert_reqs=ssl.CERT_REQUIRED,
-                ca_certs=self.ca_cert,
-                ssl_version=ssl_version)
-        except socket.error:
-            exc = sys.exc_info()[1]
-            # Re-throw an exception with a more friendly error message
-            exc = get_socket_error_exception(ssl_version=ssl_version, exc=exc)
-            raise exc
-
-        cert = self.sock.getpeercert()
-        try:
-            match_hostname(cert, self.host)
-        except CertificateError:
-            e = sys.exc_info()[1]
-            raise ssl.SSLError('Failed to verify hostname: %s' % (str(e)))
+        pass
+
+    def request(method, url, body=None, headers=None):
+            method = method.lower()
+            if method == 'get':
+                response = requests.get(url, headers=headers)
+            elif method == 'post':
+                response = requests.post(url, data=body, headers=headers)
+            elif method == 'head':
+                response = requests.head(url, headers=headers)
+            return response
 
 
 def get_socket_error_exception(ssl_version, exc):


[30/33] libcloud git commit: Merge remote-tracking branch 'apache/trunk' into requests

Posted by an...@apache.org.
Merge remote-tracking branch 'apache/trunk' into requests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/e1765b93
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/e1765b93
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/e1765b93

Branch: refs/heads/requests
Commit: e1765b93c1702e398051fa450a693997aee3cce0
Parents: e24c859 f56db93
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 17:53:59 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 17:53:59 2016 +1000

----------------------------------------------------------------------
 CHANGES.rst                                     |  25 ++
 .../_supported_methods_block_storage.rst        |   2 +
 .../_supported_methods_image_management.rst     |   2 +
 .../_supported_methods_key_pair_management.rst  |   2 +
 docs/compute/_supported_methods_main.rst        |   2 +
 docs/compute/_supported_providers.rst           |   2 +
 docs/dns/_supported_methods.rst                 |   2 +
 docs/dns/_supported_providers.rst               |   2 +
 docs/dns/drivers/luadns.rst                     |  25 ++
 docs/dns/drivers/nfsn.rst                       |  25 ++
 docs/examples/dns/luadns/instantiate_driver.py  |   5 +
 docs/examples/dns/nfsn/instantiate_driver.py    |   5 +
 docs/loadbalancer/_supported_methods.rst        |   2 +
 docs/loadbalancer/_supported_providers.rst      |   2 +
 docs/storage/_supported_methods_cdn.rst         |   4 +
 docs/storage/_supported_methods_main.rst        |   6 +-
 docs/storage/_supported_providers.rst           |   4 +
 libcloud/common/dimensiondata.py                |  98 ++++++
 libcloud/common/google.py                       |   5 -
 libcloud/common/luadns.py                       |  69 +++++
 libcloud/common/nfsn.py                         | 114 +++++++
 libcloud/compute/drivers/dimensiondata.py       | 196 +++++++++++-
 libcloud/compute/drivers/ec2.py                 |  21 +-
 libcloud/dns/drivers/luadns.py                  | 293 ++++++++++++++++++
 libcloud/dns/drivers/nfsn.py                    | 198 ++++++++++++
 libcloud/dns/providers.py                       |   2 +
 libcloud/dns/types.py                           |   3 +-
 libcloud/storage/drivers/s3.py                  |  31 ++
 libcloud/storage/providers.py                   |   2 +
 libcloud/storage/types.py                       |   2 +
 libcloud/test/common/test_nfsn.py               |  65 ++++
 ...a_9cbc_8dabe5a7d0e4_network_firewallRule.xml |  52 +++-
 ...dabe5a7d0e4_server_antiAffinityRule_list.xml |  42 +++
 ...4_server_antiAffinityRule_list_PAGINATED.xml |  42 +++
 ...cbc_8dabe5a7d0e4_antiAffinityRule_create.xml |  11 +
 ...dabe5a7d0e4_antiAffinityRule_create_FAIL.xml |   7 +
 ...cbc_8dabe5a7d0e4_antiAffinityRule_delete.xml |   7 +
 ...dabe5a7d0e4_antiAffinityRule_delete_FAIL.xml |   7 +
 libcloud/test/compute/test_dimensiondata.py     | 222 +++++++++++++-
 .../fixtures/luadns/create_record_success.json  |  10 +
 .../fixtures/luadns/create_zone_success.json    |  10 +
 .../fixtures/luadns/delete_record_success.json  |   0
 .../fixtures/luadns/delete_zone_success.json    |   0
 .../dns/fixtures/luadns/empty_records_list.json |   1 +
 .../dns/fixtures/luadns/empty_zones_list.json   |   1 +
 .../test/dns/fixtures/luadns/get_record.json    |  10 +
 libcloud/test/dns/fixtures/luadns/get_zone.json |  42 +++
 .../fixtures/luadns/record_does_not_exist.json  |   1 +
 .../test/dns/fixtures/luadns/records_list.json  |  22 ++
 .../fixtures/luadns/zone_already_exists.json    |   4 +
 .../fixtures/luadns/zone_does_not_exist.json    |   1 +
 .../test/dns/fixtures/luadns/zones_list.json    |  22 ++
 .../test/dns/fixtures/nfsn/list_one_record.json |   9 +
 .../test/dns/fixtures/nfsn/list_records.json    |  16 +
 .../dns/fixtures/nfsn/list_records_created.json |  23 ++
 .../dns/fixtures/nfsn/record_not_removed.json   |   4 +
 .../test/dns/fixtures/nfsn/zone_not_found.json  |   4 +
 libcloud/test/dns/test_luadns.py                | 306 +++++++++++++++++++
 libcloud/test/dns/test_nfsn.py                  | 148 +++++++++
 libcloud/test/secrets.py-dist                   |   1 +
 60 files changed, 2215 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/e1765b93/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------


[21/33] libcloud git commit: Fix gridspot driver

Posted by an...@apache.org.
Fix gridspot driver


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0bfe15b2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0bfe15b2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0bfe15b2

Branch: refs/heads/requests
Commit: 0bfe15b2fd03d9067e521c330e2a7cde63de6e2e
Parents: 14b68f5
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 15:18:03 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 15:18:03 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_gridspot.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0bfe15b2/libcloud/test/compute/test_gridspot.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gridspot.py b/libcloud/test/compute/test_gridspot.py
index a2e31f5..a20582c 100644
--- a/libcloud/test/compute/test_gridspot.py
+++ b/libcloud/test/compute/test_gridspot.py
@@ -34,7 +34,7 @@ from libcloud.test.secrets import GRIDSPOT_PARAMS
 class GridspotTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        GridspotNodeDriver.conectionCls.conn_class = GridspotMockHttp
+        GridspotNodeDriver.connectionCls.conn_class = GridspotMockHttp
         GridspotMockHttp.type = None
         self.driver = GridspotNodeDriver(*GRIDSPOT_PARAMS)
 


[22/33] libcloud git commit: Fix cloudsigma tests

Posted by an...@apache.org.
Fix cloudsigma tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/aac34de7
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/aac34de7
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/aac34de7

Branch: refs/heads/requests
Commit: aac34de798ef9462a68ec2e69e2246b498425f92
Parents: 0bfe15b
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 15:20:50 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 15:20:50 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_cloudsigma_v1_0.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/aac34de7/libcloud/test/compute/test_cloudsigma_v1_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v1_0.py b/libcloud/test/compute/test_cloudsigma_v1_0.py
index 197d63e..4c9f2e3 100644
--- a/libcloud/test/compute/test_cloudsigma_v1_0.py
+++ b/libcloud/test/compute/test_cloudsigma_v1_0.py
@@ -35,7 +35,7 @@ class CloudSigmaAPI10BaseTestCase(object):
     def setUp(self):
         self.driver = self.driver_klass(*self.driver_args,
                                         **self.driver_kwargs)
-
+        CloudSigmaHttp.type = None
         self.driver.connectionCls.conn_class = CloudSigmaHttp
 
     def test_list_nodes(self):


[23/33] libcloud git commit: Fix digital ocean tests

Posted by an...@apache.org.
Fix digital ocean tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b164cfc7
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b164cfc7
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b164cfc7

Branch: refs/heads/requests
Commit: b164cfc793f99ed6c0e52f2e681abd9dfe744a50
Parents: aac34de
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 15:46:40 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 15:46:40 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py                | 12 ++---
 libcloud/test/__init__.py              |  2 +-
 libcloud/test/dns/test_digitalocean.py | 70 ++++++++++++++---------------
 3 files changed, 42 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b164cfc7/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 40d9c39..67d66b1 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -36,11 +36,10 @@ import requests
 
 import libcloud
 
-from libcloud.utils.py3 import PY3, PY25
+from libcloud.utils.py3 import PY25
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import urlencode
-from libcloud.utils.py3 import b
 
 from libcloud.utils.misc import lowercase_keys, retry
 from libcloud.utils.compression import decompress_data
@@ -153,7 +152,7 @@ class Response(object):
         self.error = response.reason
         self.status = response.status_code
 
-        self.body = response.text
+        self.body = response.text if response.text is not None else ''
 
         if not self.success():
             raise exception_from_message(code=self.status,
@@ -170,7 +169,7 @@ class Response(object):
         :return: Parsed body.
         :rtype: ``str``
         """
-        return self.body
+        return self.body if self.body is not None else ''
 
     def parse_error(self):
         """
@@ -227,7 +226,8 @@ class JsonResponse(Response):
     """
 
     def parse_body(self):
-        if len(self.body) == 0 and not self.parse_zero_length_body:
+        if self.body is not None and \
+        len(self.body) == 0 and not self.parse_zero_length_body:
             return self.body
 
         try:
@@ -249,7 +249,7 @@ class XmlResponse(Response):
 
     def parse_body(self):
         if len(self.body) == 0 and not self.parse_zero_length_body:
-            return self.body
+            return self.body if self.body is not None else ''
 
         try:
             body = ET.XML(self.body)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b164cfc7/libcloud/test/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/test/__init__.py b/libcloud/test/__init__.py
index af4a3b3..17e1f2f 100644
--- a/libcloud/test/__init__.py
+++ b/libcloud/test/__init__.py
@@ -79,7 +79,7 @@ class MockResponse(object):
     A mock HTTPResponse
     """
     headers = {}
-    body = None
+    body = ''
     status = 0
     reason = ''
     version = 11

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b164cfc7/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index 8046fda..33d0cb9 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -96,7 +96,7 @@ class DigitalOceanDNSTests(LibcloudTestCase):
 class DigitalOceanDNSMockHttp(MockHttpTestCase):
     fixtures = DNSFileFixtures('digitalocean')
 
-    response = {
+    response_map = {
         None: httplib.OK,
         'CREATE': httplib.CREATED,
         'DELETE': httplib.NO_CONTENT,
@@ -108,103 +108,103 @@ class DigitalOceanDNSMockHttp(MockHttpTestCase):
 
     def _v2_domains(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_CREATE(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_CREATE.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_EMPTY(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_EMPTY.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_UNAUTHORIZED(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_UNAUTHORIZED.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_DELETE(self, method, url, body, headers):
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_NOT_FOUND(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_NOT_FOUND.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records(self, method, url, body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_records.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_CREATE(self, method, url,
                                               body, headers):
         body = self.fixtures.load('_v2_domains_testdomain_records_CREATE.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234560(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234560.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234561(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234561.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234562(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234562.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234563(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234563.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234564(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234564.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234564_DELETE(
             self, method, url, body, headers):
         self.type = 'DELETE'
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234564_NOT_FOUND(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234564_NOT_FOUND.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
     def _v2_domains_testdomain_records_1234564_UPDATE(
             self, method, url, body, headers):
         body = self.fixtures.load(
             '_v2_domains_testdomain_records_1234564_UPDATE.json')
-        return (self.response[self.type], body, {},
-                httplib.responses[self.response[self.type]])
+        return (self.response_map[self.type], body, {},
+                httplib.responses[self.response_map[self.type]])
 
 if __name__ == '__main__':
     sys.exit(unittest.main())


[29/33] libcloud git commit: Fix linting errors in test and test deps

Posted by an...@apache.org.
Fix linting errors in test and test deps


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/e24c859c
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/e24c859c
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/e24c859c

Branch: refs/heads/requests
Commit: e24c859cb985efb447483ab54de61f7bf3df2693
Parents: 6b9f90c
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 17:49:31 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 17:49:31 2016 +1000

----------------------------------------------------------------------
 libcloud/test/__init__.py         | 2 --
 libcloud/test/test_httplib_ssl.py | 2 --
 setup.py                          | 3 +--
 3 files changed, 1 insertion(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/e24c859c/libcloud/test/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/test/__init__.py b/libcloud/test/__init__.py
index 068de27..169f228 100644
--- a/libcloud/test/__init__.py
+++ b/libcloud/test/__init__.py
@@ -18,11 +18,9 @@ import random
 import requests
 
 from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import StringIO
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import parse_qs
 from libcloud.utils.py3 import parse_qsl
-from libcloud.utils.py3 import u
 from libcloud.utils.py3 import unittest2_required
 
 if unittest2_required:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/e24c859c/libcloud/test/test_httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_httplib_ssl.py b/libcloud/test/test_httplib_ssl.py
index 9c96df4..a669bb1 100644
--- a/libcloud/test/test_httplib_ssl.py
+++ b/libcloud/test/test_httplib_ssl.py
@@ -16,9 +16,7 @@
 import os
 import sys
 import os.path
-import socket
 
-import mock
 from mock import patch
 
 import libcloud.security

http://git-wip-us.apache.org/repos/asf/libcloud/blob/e24c859c/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index 351fcb9..dc1589f 100644
--- a/setup.py
+++ b/setup.py
@@ -60,8 +60,7 @@ SUPPORTED_VERSIONS = ['2.5', '2.6', '2.7', 'PyPy', '3.x']
 
 TEST_REQUIREMENTS = [
     'mock',
-    'requests',
-    'requests-mock'
+    'requests'
 ]
 
 if PY2_pre_279 or PY3_pre_32:


[19/33] libcloud git commit: Fix brightbox testing

Posted by an...@apache.org.
Fix brightbox testing


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d95474e0
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d95474e0
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d95474e0

Branch: refs/heads/requests
Commit: d95474e097accb1d7482c8c8b60ee06f7d1441f0
Parents: dc1290f
Author: anthony-shaw <an...@gmail.com>
Authored: Wed Mar 30 14:55:02 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Wed Mar 30 14:55:02 2016 +1100

----------------------------------------------------------------------
 libcloud/test/__init__.py               |  2 +-
 libcloud/test/compute/test_brightbox.py | 49 ++++++++++++++++------------
 2 files changed, 29 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d95474e0/libcloud/test/__init__.py
----------------------------------------------------------------------
diff --git a/libcloud/test/__init__.py b/libcloud/test/__init__.py
index cfd076c..af4a3b3 100644
--- a/libcloud/test/__init__.py
+++ b/libcloud/test/__init__.py
@@ -91,7 +91,7 @@ class MockResponse(object):
         self.reason = reason or self.reason
 
     def read(self, *args, **kwargs):
-        return self.body.read(*args, **kwargs)
+        return self.body
 
     def next(self):
         if sys.version_info >= (2, 5) and sys.version_info <= (2, 6):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/d95474e0/libcloud/test/compute/test_brightbox.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_brightbox.py b/libcloud/test/compute/test_brightbox.py
index 2ac57b0..d375f65 100644
--- a/libcloud/test/compute/test_brightbox.py
+++ b/libcloud/test/compute/test_brightbox.py
@@ -41,6 +41,7 @@ class BrightboxTest(unittest.TestCase, TestCaseMixin):
     def setUp(self):
         BrightboxNodeDriver.connectionCls.conn_class = BrightboxMockHttp
         BrightboxMockHttp.type = None
+        BrightboxNodeDriver.connectionCls.token = 'test'
         self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS)
 
     def test_authentication(self):
@@ -245,30 +246,36 @@ class BrightboxMockHttp(MockHttp):
 
     def _token(self, method, url, body, headers):
         if method == 'POST':
-            return self.response(httplib.OK, self.fixtures.load('token.json'))
+            return self.test_response(httplib.OK, self.fixtures.load('token.json'))
 
     def _token_INVALID_CLIENT(self, method, url, body, headers):
         if method == 'POST':
-            return self.response(httplib.BAD_REQUEST, '{"error":"invalid_client"}')
+            return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}')
 
     def _token_UNAUTHORIZED_CLIENT(self, method, url, body, headers):
         if method == 'POST':
-            return self.response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}')
+            return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}')
+
+    def _1_0_servers_INVALID_CLIENT(self, method, url, body, headers):
+        return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}')
+
+    def _1_0_servers_UNAUTHORIZED_CLIENT(self, method, url, body, headers):
+        return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}')
 
     def _1_0_images(self, method, url, body, headers):
         if method == 'GET':
-            return self.response(httplib.OK, self.fixtures.load('list_images.json'))
+            return self.test_response(httplib.OK, self.fixtures.load('list_images.json'))
 
     def _1_0_servers(self, method, url, body, headers):
         if method == 'GET':
-            return self.response(httplib.OK, self.fixtures.load('list_servers.json'))
+            return self.test_response(httplib.OK, self.fixtures.load('list_servers.json'))
         elif method == 'POST':
             body = json.loads(body)
             encoded = base64.b64encode(b(USER_DATA)).decode('ascii')
 
             if 'user_data' in body and body['user_data'] != encoded:
                 data = '{"error_name":"dodgy user data", "errors": ["User data not encoded properly"]}'
-                return self.response(httplib.BAD_REQUEST, data)
+                return self.test_response(httplib.BAD_REQUEST, data)
             if body.get('zone', '') == 'zon-remk1':
                 node = json.loads(
                     self.fixtures.load('create_server_gb1_b.json'))
@@ -281,30 +288,30 @@ class BrightboxMockHttp(MockHttp):
                                          for x in body['server_groups']]
             if 'user_data' in body:
                 node['user_data'] = body['user_data']
-            return self.response(httplib.ACCEPTED, json.dumps(node))
+            return self.test_response(httplib.ACCEPTED, json.dumps(node))
 
     def _1_0_servers_srv_xvpn7(self, method, url, body, headers):
         if method == 'DELETE':
-            return self.response(httplib.ACCEPTED, '')
+            return self.test_response(httplib.ACCEPTED, '')
 
     def _1_0_server_types(self, method, url, body, headers):
         if method == 'GET':
-            return self.response(httplib.OK, self.fixtures.load('list_server_types.json'))
+            return self.test_response(httplib.OK, self.fixtures.load('list_server_types.json'))
 
     def _1_0_zones(self, method, url, body, headers):
         if method == 'GET':
             if headers['Host'] == 'api.gbt.brightbox.com':
-                return self.response(httplib.OK, "{}")
+                return self.test_response(httplib.OK, "{}")
             else:
-                return self.response(httplib.OK, self.fixtures.load('list_zones.json'))
+                return self.test_response(httplib.OK, self.fixtures.load('list_zones.json'))
 
     def _2_0_zones(self, method, url, body, headers):
         data = '{"error_name":"unrecognised_endpoint", "errors": ["The request was for an unrecognised API endpoint"]}'
-        return self.response(httplib.BAD_REQUEST, data)
+        return self.test_response(httplib.BAD_REQUEST, data)
 
     def _1_0_cloud_ips(self, method, url, body, headers):
         if method == 'GET':
-            return self.response(httplib.OK, self.fixtures.load('list_cloud_ips.json'))
+            return self.test_response(httplib.OK, self.fixtures.load('list_cloud_ips.json'))
         elif method == 'POST':
             if body:
                 body = json.loads(body)
@@ -313,32 +320,32 @@ class BrightboxMockHttp(MockHttp):
 
             if 'reverse_dns' in body:
                 node['reverse_dns'] = body['reverse_dns']
-            return self.response(httplib.ACCEPTED, json.dumps(node))
+            return self.test_response(httplib.ACCEPTED, json.dumps(node))
 
     def _1_0_cloud_ips_cip_jsjc5(self, method, url, body, headers):
         if method == 'DELETE':
-            return self.response(httplib.OK, '')
+            return self.test_response(httplib.OK, '')
         elif method == 'PUT':
             body = json.loads(body)
             if body.get('reverse_dns', None) == 'fred.co.uk':
-                return self.response(httplib.OK, '')
+                return self.test_response(httplib.OK, '')
             else:
-                return self.response(httplib.BAD_REQUEST, '{"error_name":"bad dns", "errors": ["Bad dns"]}')
+                return self.test_response(httplib.BAD_REQUEST, '{"error_name":"bad dns", "errors": ["Bad dns"]}')
 
     def _1_0_cloud_ips_cip_jsjc5_map(self, method, url, body, headers):
         if method == 'POST':
             body = json.loads(body)
             if 'destination' in body:
-                return self.response(httplib.ACCEPTED, '')
+                return self.test_response(httplib.ACCEPTED, '')
             else:
                 data = '{"error_name":"bad destination", "errors": ["Bad destination"]}'
-                return self.response(httplib.BAD_REQUEST, data)
+                return self.test_response(httplib.BAD_REQUEST, data)
 
     def _1_0_cloud_ips_cip_jsjc5_unmap(self, method, url, body, headers):
         if method == 'POST':
-            return self.response(httplib.ACCEPTED, '')
+            return self.test_response(httplib.ACCEPTED, '')
 
-    def response(self, status, body):
+    def test_response(self, status, body):
         return (status, body, {'content-type': 'application/json'}, httplib.responses[status])
 
 


[13/33] libcloud git commit: Refactor all the unit tests to only have 1 mock connection class and use Connection.conn_class instead of Connection.conn_classes (tuple)

Posted by an...@apache.org.
Refactor all the unit tests to only have 1 mock connection class and use Connection.conn_class instead of Connection.conn_classes (tuple)


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/6fd28b6b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/6fd28b6b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/6fd28b6b

Branch: refs/heads/requests
Commit: 6fd28b6bac34d5065c3898accdcb4ecf0a1101e7
Parents: de1176e
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Mar 29 20:57:51 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Mar 29 20:57:51 2016 +1100

----------------------------------------------------------------------
 libcloud/common/base.py                         |  4 +++
 libcloud/common/openstack_identity.py           |  2 +-
 libcloud/test/backup/test_dimensiondata.py      |  2 +-
 libcloud/test/common/test_cloudstack.py         |  2 +-
 libcloud/test/common/test_digitalocean_v1.py    |  4 +--
 libcloud/test/common/test_digitalocean_v2.py    |  4 +--
 libcloud/test/common/test_google.py             |  9 ++----
 libcloud/test/common/test_openstack.py          |  6 ++--
 libcloud/test/common/test_openstack_identity.py | 10 +++----
 libcloud/test/compute/test_abiquo.py            |  4 +--
 libcloud/test/compute/test_azure.py             |  2 +-
 libcloud/test/compute/test_bluebox.py           |  2 +-
 libcloud/test/compute/test_brightbox.py         |  3 +-
 libcloud/test/compute/test_cloudsigma_v1_0.py   |  3 +-
 libcloud/test/compute/test_cloudsigma_v2_0.py   |  3 +-
 libcloud/test/compute/test_cloudstack.py        |  3 +-
 libcloud/test/compute/test_deployment.py        |  2 +-
 libcloud/test/compute/test_digitalocean_v1.py   |  4 +--
 libcloud/test/compute/test_digitalocean_v2.py   |  4 +--
 libcloud/test/compute/test_dimensiondata.py     |  2 +-
 libcloud/test/compute/test_ec2.py               | 10 +++----
 libcloud/test/compute/test_ecp.py               |  3 +-
 libcloud/test/compute/test_ecs.py               |  2 +-
 libcloud/test/compute/test_elasticstack.py      |  9 ++----
 libcloud/test/compute/test_gandi.py             |  6 ++--
 libcloud/test/compute/test_gce.py               |  5 ++--
 libcloud/test/compute/test_gogrid.py            |  2 +-
 libcloud/test/compute/test_gridspot.py          |  5 +---
 libcloud/test/compute/test_hostvirtual.py       |  3 +-
 libcloud/test/compute/test_joyent.py            |  2 +-
 libcloud/test/compute/test_ktucloud.py          |  3 +-
 libcloud/test/compute/test_linode.py            |  2 +-
 libcloud/test/compute/test_nephoscale.py        |  3 +-
 libcloud/test/compute/test_onapp.py             |  3 +-
 libcloud/test/compute/test_opennebula.py        | 18 ++++--------
 libcloud/test/compute/test_openstack.py         | 30 +++++++-------------
 libcloud/test/compute/test_packet.py            |  2 +-
 libcloud/test/compute/test_profitbricks.py      |  2 +-
 libcloud/test/compute/test_rackspace.py         |  7 ++---
 libcloud/test/compute/test_rimuhosting.py       |  3 +-
 libcloud/test/compute/test_runabove.py          |  3 +-
 libcloud/test/compute/test_softlayer.py         |  3 +-
 libcloud/test/compute/test_vcl.py               |  3 +-
 libcloud/test/compute/test_vcloud.py            | 11 +++----
 libcloud/test/compute/test_voxel.py             |  2 +-
 libcloud/test/compute/test_vpsnet.py            |  2 +-
 libcloud/test/compute/test_vultr.py             |  3 +-
 libcloud/test/container/test_docker.py          |  3 +-
 libcloud/test/container/test_docker_utils.py    |  3 +-
 libcloud/test/container/test_ecs.py             |  6 ++--
 libcloud/test/container/test_kubernetes.py      |  3 +-
 libcloud/test/dns/test_auroradns.py             |  3 +-
 libcloud/test/dns/test_cloudflare.py            |  3 +-
 libcloud/test/dns/test_digitalocean.py          |  3 +-
 libcloud/test/dns/test_dnsimple.py              |  3 +-
 libcloud/test/dns/test_durabledns.py            |  3 +-
 libcloud/test/dns/test_gandi.py                 |  3 +-
 libcloud/test/dns/test_godaddy.py               |  3 +-
 libcloud/test/dns/test_google.py                |  6 ++--
 libcloud/test/dns/test_hostvirtual.py           |  3 +-
 libcloud/test/dns/test_linode.py                |  3 +-
 libcloud/test/dns/test_liquidweb.py             |  3 +-
 libcloud/test/dns/test_nsone.py                 |  2 +-
 libcloud/test/dns/test_pointdns.py              |  3 +-
 libcloud/test/dns/test_rackspace.py             |  3 +-
 libcloud/test/dns/test_route53.py               |  3 +-
 libcloud/test/dns/test_softlayer.py             |  3 +-
 libcloud/test/dns/test_vultr.py                 |  3 +-
 libcloud/test/dns/test_worldwidedns.py          |  3 +-
 libcloud/test/dns/test_zerigo.py                |  3 +-
 libcloud/test/dns/test_zonomi.py                |  2 +-
 libcloud/test/loadbalancer/test_brightbox.py    |  3 +-
 libcloud/test/loadbalancer/test_cloudstack.py   |  3 +-
 .../test/loadbalancer/test_dimensiondata.py     |  2 +-
 libcloud/test/loadbalancer/test_elb.py          |  3 +-
 libcloud/test/loadbalancer/test_gce.py          |  7 ++---
 libcloud/test/loadbalancer/test_gogrid.py       |  3 +-
 libcloud/test/loadbalancer/test_rackspace.py    |  9 ++----
 libcloud/test/loadbalancer/test_slb.py          |  3 +-
 libcloud/test/loadbalancer/test_softlayer.py    |  3 +-
 libcloud/test/storage/test_atmos.py             |  2 +-
 libcloud/test/storage/test_azure_blobs.py       |  3 +-
 libcloud/test/storage/test_backblaze_b2.py      |  3 +-
 libcloud/test/storage/test_base.py              |  2 +-
 libcloud/test/storage/test_cloudfiles.py        |  3 +-
 libcloud/test/storage/test_oss.py               |  3 +-
 libcloud/test/storage/test_s3.py                |  3 +-
 87 files changed, 135 insertions(+), 218 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index 22852b4..acf9a7f 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -600,6 +600,10 @@ class Connection(object):
                 url = '?'.join((action, urlencode(params, doseq=True)))
         else:
             url = action
+            
+        # IF connection has not yet been established
+        if self.connection is None:
+            self.connect()
 
         try:
             # @TODO: Should we just pass File object as body to request method

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/common/openstack_identity.py
----------------------------------------------------------------------
diff --git a/libcloud/common/openstack_identity.py b/libcloud/common/openstack_identity.py
index e8cc6a8..6a76e04 100644
--- a/libcloud/common/openstack_identity.py
+++ b/libcloud/common/openstack_identity.py
@@ -583,7 +583,7 @@ class OpenStackIdentityConnection(ConnectionUserAndKey):
 
         # enable tests to use the same mock connection classes.
         if parent_conn:
-            self.conn_classes = parent_conn.conn_classes
+            self.conn_class = parent_conn.conn_class
             self.driver = parent_conn.driver
         else:
             self.driver = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/backup/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/backup/test_dimensiondata.py b/libcloud/test/backup/test_dimensiondata.py
index 62fa4e9..285c777 100644
--- a/libcloud/test/backup/test_dimensiondata.py
+++ b/libcloud/test/backup/test_dimensiondata.py
@@ -36,7 +36,7 @@ from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 class DimensionDataTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionData.connectionCls.conn_class = DimensionDataMockHttp
         DimensionDataMockHttp.type = None
         self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/common/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_cloudstack.py b/libcloud/test/common/test_cloudstack.py
index 2412d5c..0b59f01 100644
--- a/libcloud/test/common/test_cloudstack.py
+++ b/libcloud/test/common/test_cloudstack.py
@@ -47,7 +47,7 @@ class CloudStackMockDriver(object):
 
 class CloudStackCommonTest(unittest.TestCase):
     def setUp(self):
-        CloudStackConnection.conn_classes = (None, CloudStackMockHttp)
+        CloudStackConnection.conn_class = CloudStackMockHttp
         self.connection = CloudStackConnection('apikey', 'secret',
                                                host=CloudStackMockDriver.host)
         self.connection.poll_interval = 0.0

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/common/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v1.py b/libcloud/test/common/test_digitalocean_v1.py
index 9e99c7f..73481a7 100644
--- a/libcloud/test/common/test_digitalocean_v1.py
+++ b/libcloud/test/common/test_digitalocean_v1.py
@@ -26,8 +26,8 @@ from libcloud.utils.py3 import httplib
 class DigitalOceanTests(LibcloudTestCase):
 
     def setUp(self):
-        DigitalOceanBaseDriver.connectionCls.conn_classes = \
-            (None, DigitalOceanMockHttp)
+        DigitalOceanBaseDriver.connectionCls.conn_class = \
+            DigitalOceanMockHttp
         DigitalOceanMockHttp.type = None
         self.driver = DigitalOceanBaseDriver(*DIGITALOCEAN_v1_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/common/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_digitalocean_v2.py b/libcloud/test/common/test_digitalocean_v2.py
index 37b4929..e1582ea 100644
--- a/libcloud/test/common/test_digitalocean_v2.py
+++ b/libcloud/test/common/test_digitalocean_v2.py
@@ -26,8 +26,8 @@ from libcloud.utils.py3 import httplib
 class DigitalOceanTests(LibcloudTestCase):
 
     def setUp(self):
-        DigitalOceanBaseDriver.connectionCls.conn_classes = \
-            (None, DigitalOceanMockHttp)
+        DigitalOceanBaseDriver.connectionCls.conn_class = \
+            DigitalOceanMockHttp
         DigitalOceanMockHttp.type = None
         self.driver = DigitalOceanBaseDriver(*DIGITALOCEAN_v2_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/common/test_google.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_google.py b/libcloud/test/common/test_google.py
index 2266ddd..0b79da6 100644
--- a/libcloud/test/common/test_google.py
+++ b/libcloud/test/common/test_google.py
@@ -154,8 +154,7 @@ class GoogleBaseAuthConnectionTest(GoogleTestCase):
     """
 
     def setUp(self):
-        GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                 GoogleAuthMockHttp)
+        GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp
         self.mock_scopes = ['foo', 'bar']
         kwargs = {'scopes': self.mock_scopes}
         self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS,
@@ -191,8 +190,7 @@ class GoogleInstalledAppAuthConnectionTest(GoogleTestCase):
     """
 
     def setUp(self):
-        GoogleInstalledAppAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                         GoogleAuthMockHttp)
+        GoogleInstalledAppAuthConnection.conn_class = GoogleAuthMockHttp
         self.mock_scopes = ['https://www.googleapis.com/auth/foo']
         kwargs = {'scopes': self.mock_scopes}
         self.conn = GoogleInstalledAppAuthConnection(*GCE_PARAMS,
@@ -314,8 +312,7 @@ class GoogleBaseConnectionTest(GoogleTestCase):
     """
 
     def setUp(self):
-        GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                 GoogleAuthMockHttp)
+        GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp
         self.mock_scopes = ['https://www.googleapis.com/auth/foo']
         kwargs = {'scopes': self.mock_scopes,
                   'auth_type': GoogleAuthType.IA}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/common/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_openstack.py b/libcloud/test/common/test_openstack.py
index 79ec583..adef17e 100644
--- a/libcloud/test/common/test_openstack.py
+++ b/libcloud/test/common/test_openstack.py
@@ -25,7 +25,7 @@ from libcloud.utils.py3 import PY25
 class OpenStackBaseConnectionTest(unittest.TestCase):
     def setUp(self):
         self.timeout = 10
-        OpenStackBaseConnection.conn_classes = (None, Mock())
+        OpenStackBaseConnection.conn_class = Mock()
         self.connection = OpenStackBaseConnection('foo', 'bar',
                                                   timeout=self.timeout,
                                                   ex_force_auth_url='https://127.0.0.1')
@@ -36,10 +36,10 @@ class OpenStackBaseConnectionTest(unittest.TestCase):
         self.connection.connect()
         self.assertEqual(self.connection.timeout, self.timeout)
         if PY25:
-            self.connection.conn_classes[1].assert_called_with(host='127.0.0.1',
+            self.connection.conn_class.assert_called_with(host='127.0.0.1',
                                                                port=443)
         else:
-            self.connection.conn_classes[1].assert_called_with(host='127.0.0.1',
+            self.connection.conn_class.assert_called_with(host='127.0.0.1',
                                                                port=443,
                                                                timeout=10)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/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
index 7c57cf1..b94cf11 100644
--- a/libcloud/test/common/test_openstack_identity.py
+++ b/libcloud/test/common/test_openstack_identity.py
@@ -44,8 +44,7 @@ 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)
+        OpenStackBaseConnection.conn_class = OpenStackMockHttp
 
     def test_auth_url_is_correctly_assembled(self):
         tuples = [
@@ -207,8 +206,7 @@ class OpenStackIdentityConnectionTestCase(unittest.TestCase):
         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)
+        OpenStackBaseConnection.conn_class = mock_http_class
 
         if auth_url is None:
             auth_url = "https://auth.api.example.com"
@@ -226,7 +224,7 @@ class OpenStackIdentity_2_0_ConnectionTests(unittest.TestCase):
     def setUp(self):
         mock_cls = OpenStackIdentity_2_0_MockHttp
         mock_cls.type = None
-        OpenStackIdentity_2_0_Connection.conn_classes = (mock_cls, mock_cls)
+        OpenStackIdentity_2_0_Connection.conn_class = mock_cls
 
         self.auth_instance = OpenStackIdentity_2_0_Connection(auth_url='http://none',
                                                               user_id='test',
@@ -247,7 +245,7 @@ class OpenStackIdentity_3_0_ConnectionTests(unittest.TestCase):
     def setUp(self):
         mock_cls = OpenStackIdentity_3_0_MockHttp
         mock_cls.type = None
-        OpenStackIdentity_3_0_Connection.conn_classes = (mock_cls, mock_cls)
+        OpenStackIdentity_3_0_Connection.conn_class = mock_cls
 
         self.auth_instance = OpenStackIdentity_3_0_Connection(auth_url='http://none',
                                                               user_id='test',

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_abiquo.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_abiquo.py b/libcloud/test/compute/test_abiquo.py
index 55c82d4..4bae089 100644
--- a/libcloud/test/compute/test_abiquo.py
+++ b/libcloud/test/compute/test_abiquo.py
@@ -44,7 +44,7 @@ class AbiquoNodeDriverTest(unittest.TestCase, TestCaseMixin):
         """
         Set up the driver with the main user
         """
-        AbiquoNodeDriver.connectionCls.conn_classes = (AbiquoMockHttp, None)
+        AbiquoNodeDriver.connectionCls.conn_class = AbiquoMockHttp
         self.driver = AbiquoNodeDriver('son', 'goku',
                                        'http://dummy.host.com/api')
 
@@ -65,7 +65,7 @@ class AbiquoNodeDriverTest(unittest.TestCase, TestCaseMixin):
         Test, through the 'list_images' method, that a '403 Forbidden'
         raises an 'ForbidenError' instead of the 'MalformedUrlException'
         """
-        AbiquoNodeDriver.connectionCls.conn_classes = (AbiquoMockHttp, None)
+        AbiquoNodeDriver.connectionCls.conn_class = AbiquoMockHttp
         conn = AbiquoNodeDriver('son', 'gohan', 'http://dummy.host.com/api')
         self.assertRaises(ForbiddenError, conn.list_images)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_azure.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_azure.py b/libcloud/test/compute/test_azure.py
index 46360aa..800cd7a 100644
--- a/libcloud/test/compute/test_azure.py
+++ b/libcloud/test/compute/test_azure.py
@@ -40,7 +40,7 @@ class AzureNodeDriverTests(LibcloudTestCase):
 
     def setUp(self):
         Azure = get_driver(Provider.AZURE)
-        Azure.connectionCls.conn_classes = (None, AzureMockHttp)
+        Azure.connectionCls.conn_class = AzureMockHttp
         self.driver = Azure(self.SUBSCRIPTION_ID, self.KEY_FILE)
 
     def test_locations_returned_successfully(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_bluebox.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_bluebox.py b/libcloud/test/compute/test_bluebox.py
index bcee0a3..1967d11 100644
--- a/libcloud/test/compute/test_bluebox.py
+++ b/libcloud/test/compute/test_bluebox.py
@@ -29,7 +29,7 @@ from libcloud.test.secrets import BLUEBOX_PARAMS
 class BlueboxTest(unittest.TestCase):
 
     def setUp(self):
-        Bluebox.connectionCls.conn_classes = (None, BlueboxMockHttp)
+        Bluebox.connectionCls.conn_class = BlueboxMockHttp
         self.driver = Bluebox(*BLUEBOX_PARAMS)
 
     def test_create_node(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_brightbox.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_brightbox.py b/libcloud/test/compute/test_brightbox.py
index 651c349..2ac57b0 100644
--- a/libcloud/test/compute/test_brightbox.py
+++ b/libcloud/test/compute/test_brightbox.py
@@ -39,8 +39,7 @@ USER_DATA = '#!/bin/sh\ntest_script.sh\n'
 class BrightboxTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        BrightboxNodeDriver.connectionCls.conn_classes = (
-            None, BrightboxMockHttp)
+        BrightboxNodeDriver.connectionCls.conn_class = BrightboxMockHttp
         BrightboxMockHttp.type = None
         self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_cloudsigma_v1_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v1_0.py b/libcloud/test/compute/test_cloudsigma_v1_0.py
index d8fb310..197d63e 100644
--- a/libcloud/test/compute/test_cloudsigma_v1_0.py
+++ b/libcloud/test/compute/test_cloudsigma_v1_0.py
@@ -36,8 +36,7 @@ class CloudSigmaAPI10BaseTestCase(object):
         self.driver = self.driver_klass(*self.driver_args,
                                         **self.driver_kwargs)
 
-        self.driver.connectionCls.conn_classes = (None,
-                                                  CloudSigmaHttp)
+        self.driver.connectionCls.conn_class = CloudSigmaHttp
 
     def test_list_nodes(self):
         nodes = self.driver.list_nodes()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_cloudsigma_v2_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v2_0.py b/libcloud/test/compute/test_cloudsigma_v2_0.py
index 4bc66a5..44bc1ce 100644
--- a/libcloud/test/compute/test_cloudsigma_v2_0.py
+++ b/libcloud/test/compute/test_cloudsigma_v2_0.py
@@ -35,8 +35,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 
 class CloudSigmaAPI20BaseTestCase(object):
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = \
-            (CloudSigmaMockHttp, CloudSigmaMockHttp)
+        self.driver_klass.connectionCls.conn_class = CloudSigmaMockHttp
 
         CloudSigmaMockHttp.type = None
         CloudSigmaMockHttp.use_param = 'do'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index 9f6b939..ad7072e 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -43,8 +43,7 @@ class CloudStackCommonTestCase(TestCaseMixin):
     driver_klass = CloudStackNodeDriver
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = \
-            (None, CloudStackMockHttp)
+        self.driver_klass.connectionCls.conn_class = CloudStackMockHttp
         self.driver = self.driver_klass('apikey', 'secret',
                                         path='/test/path',
                                         host='api.dummy.com')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_deployment.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_deployment.py b/libcloud/test/compute/test_deployment.py
index 7fda79c..b2bdab2 100644
--- a/libcloud/test/compute/test_deployment.py
+++ b/libcloud/test/compute/test_deployment.py
@@ -66,7 +66,7 @@ class MockClient(BaseSSHClient):
 class DeploymentTests(unittest.TestCase):
 
     def setUp(self):
-        Rackspace.connectionCls.conn_classes = (None, RackspaceMockHttp)
+        Rackspace.connectionCls.conn_class = RackspaceMockHttp
         RackspaceMockHttp.type = None
         self.driver = Rackspace(*RACKSPACE_PARAMS)
         # normally authentication happens lazily, but we force it here

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_digitalocean_v1.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v1.py b/libcloud/test/compute/test_digitalocean_v1.py
index a09b1a8..7a409c9 100644
--- a/libcloud/test/compute/test_digitalocean_v1.py
+++ b/libcloud/test/compute/test_digitalocean_v1.py
@@ -36,8 +36,8 @@ from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
 class DigitalOcean_v1_Tests(LibcloudTestCase):
 
     def setUp(self):
-        DigitalOceanNodeDriver.connectionCls.conn_classes = \
-            (None, DigitalOceanMockHttp)
+        DigitalOceanNodeDriver.connectionCls.conn_class = \
+            DigitalOceanMockHttp
         DigitalOceanMockHttp.type = None
         self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v1_PARAMS,
                                              api_version='v1')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_digitalocean_v2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_digitalocean_v2.py b/libcloud/test/compute/test_digitalocean_v2.py
index 1754ce1..6a474af 100644
--- a/libcloud/test/compute/test_digitalocean_v2.py
+++ b/libcloud/test/compute/test_digitalocean_v2.py
@@ -39,8 +39,8 @@ from libcloud.test.secrets import DIGITALOCEAN_v2_PARAMS
 class DigitalOcean_v2_Tests(LibcloudTestCase):
 
     def setUp(self):
-        DigitalOceanNodeDriver.connectionCls.conn_classes = \
-            (None, DigitalOceanMockHttp)
+        DigitalOceanNodeDriver.connectionCls.conn_class = \
+            DigitalOceanMockHttp
         DigitalOceanMockHttp.type = None
         self.driver = DigitalOceanNodeDriver(*DIGITALOCEAN_v2_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_dimensiondata.py b/libcloud/test/compute/test_dimensiondata.py
index 8ec9d27..21b3d74 100644
--- a/libcloud/test/compute/test_dimensiondata.py
+++ b/libcloud/test/compute/test_dimensiondata.py
@@ -37,7 +37,7 @@ from libcloud.utils.xml import fixxpath, findtext
 class DimensionDataTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionData.connectionCls.conn_class = DimensionDataMockHttp
         DimensionDataMockHttp.type = None
         self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index 2356230..972c951 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -85,7 +85,7 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
 
     def setUp(self):
         EC2MockHttp.test = self
-        EC2NodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
+        EC2NodeDriver.connectionCls.conn_class = EC2MockHttp
         EC2MockHttp.use_param = 'Action'
         EC2MockHttp.type = None
 
@@ -1195,7 +1195,7 @@ class EC2OldStyleModelTests(EC2Tests):
 
     def setUp(self):
         EC2MockHttp.test = self
-        EC2NodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
+        EC2NodeDriver.connectionCls.conn_class = EC2MockHttp
         EC2MockHttp.use_param = 'Action'
         EC2MockHttp.type = None
 
@@ -1643,7 +1643,7 @@ class EucMockHttp(EC2MockHttp):
 class NimbusTests(EC2Tests):
 
     def setUp(self):
-        NimbusNodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
+        NimbusNodeDriver.connectionCls.conn_class = EC2MockHttp
         EC2MockHttp.use_param = 'Action'
         EC2MockHttp.type = None
         self.driver = NimbusNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1],
@@ -1701,7 +1701,7 @@ class NimbusTests(EC2Tests):
 class EucTests(LibcloudTestCase, TestCaseMixin):
 
     def setUp(self):
-        EucNodeDriver.connectionCls.conn_classes = (None, EucMockHttp)
+        EucNodeDriver.connectionCls.conn_class = EucMockHttp
         EC2MockHttp.use_param = 'Action'
         EC2MockHttp.type = None
         self.driver = EucNodeDriver(key=EC2_PARAMS[0], secret=EC2_PARAMS[1],
@@ -1730,7 +1730,7 @@ class EucTests(LibcloudTestCase, TestCaseMixin):
 class OutscaleTests(EC2Tests):
 
     def setUp(self):
-        OutscaleSASNodeDriver.connectionCls.conn_classes = (None, EC2MockHttp)
+        OutscaleSASNodeDriver.connectionCls.conn_class = EC2MockHttp
         EC2MockHttp.use_param = 'Action'
         EC2MockHttp.type = None
         self.driver = OutscaleSASNodeDriver(key=EC2_PARAMS[0],

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_ecp.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ecp.py b/libcloud/test/compute/test_ecp.py
index c39875c..93fdc71 100644
--- a/libcloud/test/compute/test_ecp.py
+++ b/libcloud/test/compute/test_ecp.py
@@ -29,8 +29,7 @@ from libcloud.test.secrets import ECP_PARAMS
 class ECPTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        ECPNodeDriver.connectionCls.conn_classes = (None,
-                                                    ECPMockHttp)
+        ECPNodeDriver.connectionCls.conn_class = ECPMockHttp
         self.driver = ECPNodeDriver(*ECP_PARAMS)
 
     def test_list_nodes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_ecs.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ecs.py b/libcloud/test/compute/test_ecs.py
index 495f7b2..f3012e0 100644
--- a/libcloud/test/compute/test_ecs.py
+++ b/libcloud/test/compute/test_ecs.py
@@ -36,7 +36,7 @@ class ECSDriverTestCase(LibcloudTestCase):
 
     def setUp(self):
         ECSMockHttp.test = self
-        ECSDriver.connectionCls.conn_classes = (ECSMockHttp, ECSMockHttp)
+        ECSDriver.connectionCls.conn_class = ECSMockHttp
         ECSMockHttp.use_param = 'Action'
         ECSMockHttp.type = None
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_elasticstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_elasticstack.py b/libcloud/test/compute/test_elasticstack.py
index 4cbbbe5..e6fb21c 100644
--- a/libcloud/test/compute/test_elasticstack.py
+++ b/libcloud/test/compute/test_elasticstack.py
@@ -149,8 +149,7 @@ class ElasticStackTestCase(object):
 class ElasticHostsTestCase(ElasticStackTestCase, unittest.TestCase):
 
     def setUp(self):
-        ElasticHosts.connectionCls.conn_classes = (None,
-                                                   ElasticStackMockHttp)
+        ElasticHosts.connectionCls.conn_class = ElasticStackMockHttp
 
         self.driver = ElasticHosts('foo', 'bar')
         images = self.driver.list_images()
@@ -181,8 +180,7 @@ class ElasticHostsTestCase(ElasticStackTestCase, unittest.TestCase):
 class SkaliCloudTestCase(ElasticStackTestCase, unittest.TestCase):
 
     def setUp(self):
-        SkaliCloud.connectionCls.conn_classes = (None,
-                                                 ElasticStackMockHttp)
+        SkaliCloud.connectionCls.conn_class = ElasticStackMockHttp
 
         self.driver = SkaliCloud('foo', 'bar')
 
@@ -195,8 +193,7 @@ class SkaliCloudTestCase(ElasticStackTestCase, unittest.TestCase):
 class ServerLoveTestCase(ElasticStackTestCase, unittest.TestCase):
 
     def setUp(self):
-        ServerLove.connectionCls.conn_classes = (None,
-                                                 ElasticStackMockHttp)
+        ServerLove.connectionCls.conn_class = ElasticStackMockHttp
 
         self.driver = ServerLove('foo', 'bar')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_gandi.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gandi.py b/libcloud/test/compute/test_gandi.py
index 0c00c15..abbedd5 100644
--- a/libcloud/test/compute/test_gandi.py
+++ b/libcloud/test/compute/test_gandi.py
@@ -34,8 +34,7 @@ class GandiTests(unittest.TestCase):
     node_name = 'test2'
 
     def setUp(self):
-        GandiNodeDriver.connectionCls.conn_classes = (
-            GandiMockHttp, GandiMockHttp)
+        GandiNodeDriver.connectionCls.conn_class = GandiMockHttp
         GandiMockHttp.type = None
         self.driver = GandiNodeDriver(*GANDI_PARAMS)
 
@@ -187,8 +186,7 @@ class GandiRatingTests(unittest.TestCase):
     node_name = 'test2'
 
     def setUp(self):
-        GandiNodeDriver.connectionCls.conn_classes = (
-            GandiMockRatingHttp, GandiMockRatingHttp)
+        GandiNodeDriver.connectionCls.conn_class = GandiMockRatingHttp
         GandiMockRatingHttp.type = None
         self.driver = GandiNodeDriver(*GANDI_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py
index 162a756..2e386aa 100644
--- a/libcloud/test/compute/test_gce.py
+++ b/libcloud/test/compute/test_gce.py
@@ -53,9 +53,8 @@ class GCENodeDriverTest(GoogleTestCase, TestCaseMixin):
 
     def setUp(self):
         GCEMockHttp.test = self
-        GCENodeDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp)
-        GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                 GoogleAuthMockHttp)
+        GCENodeDriver.connectionCls.conn_class = GCEMockHttp
+        GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp
         GCEMockHttp.type = None
         kwargs = GCE_KEYWORD_PARAMS.copy()
         kwargs['auth_type'] = 'IA'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_gogrid.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gogrid.py b/libcloud/test/compute/test_gogrid.py
index f7ceae6..08319d1 100644
--- a/libcloud/test/compute/test_gogrid.py
+++ b/libcloud/test/compute/test_gogrid.py
@@ -33,7 +33,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures  # pylint: disable-m
 class GoGridTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        GoGridNodeDriver.connectionCls.conn_classes = (None, GoGridMockHttp)
+        GoGridNodeDriver.connectionCls.conn_class = GoGridMockHttp
         GoGridMockHttp.type = None
         self.driver = GoGridNodeDriver("foo", "bar")
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_gridspot.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_gridspot.py b/libcloud/test/compute/test_gridspot.py
index 4e4de1b..a2e31f5 100644
--- a/libcloud/test/compute/test_gridspot.py
+++ b/libcloud/test/compute/test_gridspot.py
@@ -34,10 +34,7 @@ from libcloud.test.secrets import GRIDSPOT_PARAMS
 class GridspotTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        GridspotNodeDriver.connectionCls.conn_classes = (
-            None,
-            GridspotMockHttp
-        )
+        GridspotNodeDriver.conectionCls.conn_class = GridspotMockHttp
         GridspotMockHttp.type = None
         self.driver = GridspotNodeDriver(*GRIDSPOT_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_hostvirtual.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_hostvirtual.py b/libcloud/test/compute/test_hostvirtual.py
index 42cedc9..35d0fe1 100644
--- a/libcloud/test/compute/test_hostvirtual.py
+++ b/libcloud/test/compute/test_hostvirtual.py
@@ -28,8 +28,7 @@ from libcloud.test.secrets import HOSTVIRTUAL_PARAMS
 class HostVirtualTest(unittest.TestCase):
 
     def setUp(self):
-        HostVirtualNodeDriver.connectionCls.conn_classes = (
-            None, HostVirtualMockHttp)
+        HostVirtualNodeDriver.connectionCls.conn_class = HostVirtualMockHttp
         self.driver = HostVirtualNodeDriver(*HOSTVIRTUAL_PARAMS)
 
     def test_list_nodes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_joyent.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_joyent.py b/libcloud/test/compute/test_joyent.py
index 90718fc..927fe37 100644
--- a/libcloud/test/compute/test_joyent.py
+++ b/libcloud/test/compute/test_joyent.py
@@ -28,7 +28,7 @@ from libcloud.test.secrets import JOYENT_PARAMS
 class JoyentTestCase(unittest.TestCase):
 
     def setUp(self):
-        JoyentNodeDriver.connectionCls.conn_classes = (None, JoyentHttp)
+        JoyentNodeDriver.connectionCls.conn_class = JoyentHttp
         self.driver = JoyentNodeDriver(*JOYENT_PARAMS)
 
     def test_instantiate_multiple_drivers_with_different_region(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_ktucloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ktucloud.py b/libcloud/test/compute/test_ktucloud.py
index 2a27de1..9bb255e 100644
--- a/libcloud/test/compute/test_ktucloud.py
+++ b/libcloud/test/compute/test_ktucloud.py
@@ -35,8 +35,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 class KTUCloudNodeDriverTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        KTUCloudNodeDriver.connectionCls.conn_classes = \
-            (None, KTUCloudStackMockHttp)
+        KTUCloudNodeDriver.connectionCls.conn_class = KTUCloudStackMockHttp
         self.driver = KTUCloudNodeDriver('apikey', 'secret',
                                          path='/test/path',
                                          host='api.dummy.com')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_linode.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_linode.py b/libcloud/test/compute/test_linode.py
index 9a35f07..bc53148 100644
--- a/libcloud/test/compute/test_linode.py
+++ b/libcloud/test/compute/test_linode.py
@@ -34,7 +34,7 @@ class LinodeTest(unittest.TestCase, TestCaseMixin):
     # The Linode test suite
 
     def setUp(self):
-        LinodeNodeDriver.connectionCls.conn_classes = (None, LinodeMockHttp)
+        LinodeNodeDriver.connectionCls.conn_class = LinodeMockHttp
         LinodeMockHttp.use_param = 'api_action'
         self.driver = LinodeNodeDriver('foo')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_nephoscale.py b/libcloud/test/compute/test_nephoscale.py
index 0a0af0a..e279fab 100644
--- a/libcloud/test/compute/test_nephoscale.py
+++ b/libcloud/test/compute/test_nephoscale.py
@@ -30,8 +30,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 class NephoScaleTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        NephoscaleNodeDriver.connectionCls.conn_classes = (
-            NephoscaleMockHttp, NephoscaleMockHttp)
+        NephoscaleNodeDriver.connectionCls.conn_class = NephoscaleMockHttp
         self.driver = NephoscaleNodeDriver('user', 'password')
 
     def test_list_sizes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_onapp.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_onapp.py b/libcloud/test/compute/test_onapp.py
index 08760e5..fb95b09 100644
--- a/libcloud/test/compute/test_onapp.py
+++ b/libcloud/test/compute/test_onapp.py
@@ -13,8 +13,7 @@ class OnAppNodeTestCase(LibcloudTestCase):
     driver_klass = OnAppNodeDriver
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = \
-            (None, OnAppMockHttp)
+        self.driver_klass.connectionCls.conn_class = OnAppMockHttp
 
         self.driver = OnAppNodeDriver(*ONAPP_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_opennebula.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_opennebula.py b/libcloud/test/compute/test_opennebula.py
index 8dcedfd..345a2cf 100644
--- a/libcloud/test/compute/test_opennebula.py
+++ b/libcloud/test/compute/test_opennebula.py
@@ -73,8 +73,7 @@ class OpenNebula_1_4_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_1_4_MockHttp, OpenNebula_1_4_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_1_4_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('1.4',))
 
     def test_create_node(self):
@@ -270,8 +269,7 @@ class OpenNebula_2_0_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_2_0_MockHttp, OpenNebula_2_0_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_2_0_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('2.0',))
 
     def test_create_node(self):
@@ -542,8 +540,7 @@ class OpenNebula_3_0_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_3_0_MockHttp, OpenNebula_3_0_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_0_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.0',))
 
     def test_ex_list_networks(self):
@@ -586,8 +583,7 @@ class OpenNebula_3_2_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_3_2_MockHttp, OpenNebula_3_2_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_2_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.2',))
 
     def test_reboot_node(self):
@@ -651,8 +647,7 @@ class OpenNebula_3_6_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_3_6_MockHttp, OpenNebula_3_6_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_6_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.6',))
 
     def test_create_volume(self):
@@ -721,8 +716,7 @@ class OpenNebula_3_8_Tests(unittest.TestCase, OpenNebulaCaseMixin):
         """
         Setup test environment.
         """
-        OpenNebulaNodeDriver.connectionCls.conn_classes = (
-            OpenNebula_3_8_MockHttp, OpenNebula_3_8_MockHttp)
+        OpenNebulaNodeDriver.connectionCls.conn_class = OpenNebula_3_8_MockHttp
         self.driver = OpenNebulaNodeDriver(*OPENNEBULA_PARAMS + ('3.8',))
 
     def test_list_sizes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index ee2469d..2474b49 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -107,8 +107,7 @@ class OpenStack_1_0_Tests(unittest.TestCase, TestCaseMixin):
             return "https://servers.api.rackspacecloud.com/v1.0/slug"
         self.driver_klass.connectionCls.get_endpoint = get_endpoint
 
-        self.driver_klass.connectionCls.conn_classes = (OpenStackMockHttp,
-                                                        OpenStackMockHttp)
+        self.driver_klass.connectionCls.conn_class = OpenStackMockHttp
         self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com"
 
         OpenStackMockHttp.type = None
@@ -639,8 +638,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
         return self.driver_type(*self.driver_args, **self.driver_kwargs)
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = (
-            OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp)
+        self.driver_klass.connectionCls.conn_class = OpenStack_2_0_MockHttp
         self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com"
 
         OpenStackMockHttp.type = None
@@ -798,8 +796,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_list_nodes_no_image_id_attribute(self):
         # Regression test for LIBCLOD-455
-        self.driver_klass.connectionCls.conn_classes[0].type = 'ERROR_STATE_NO_IMAGE_ID'
-        self.driver_klass.connectionCls.conn_classes[1].type = 'ERROR_STATE_NO_IMAGE_ID'
+        self.driver_klass.connectionCls.conn_class.type = 'ERROR_STATE_NO_IMAGE_ID'
 
         nodes = self.driver.list_nodes()
         self.assertEqual(nodes[0].extra['imageId'], None)
@@ -1429,8 +1426,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_ex_list_snapshots(self):
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         snapshots = self.driver.ex_list_snapshots()
         self.assertEqual(len(snapshots), 3)
@@ -1447,8 +1443,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
         # rackspace needs a different mocked response for snapshots, but not for volumes
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         snapshots = self.driver.list_volume_snapshots(volume)
         self.assertEqual(len(snapshots), 1)
@@ -1457,8 +1452,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
     def test_create_volume_snapshot(self):
         volume = self.driver.list_volumes()[0]
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         ret = self.driver.create_volume_snapshot(volume,
                                                  'Test Volume',
@@ -1469,8 +1463,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
     def test_ex_create_snapshot(self):
         volume = self.driver.list_volumes()[0]
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         ret = self.driver.ex_create_snapshot(volume,
                                              'Test Volume',
@@ -1480,8 +1473,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_destroy_volume_snapshot(self):
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         snapshot = self.driver.ex_list_snapshots()[0]
         ret = self.driver.destroy_volume_snapshot(snapshot)
@@ -1489,8 +1481,7 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
     def test_ex_delete_snapshot(self):
         if self.driver_type.type == 'rackspace':
-            self.conn_classes[0].type = 'RACKSPACE'
-            self.conn_classes[1].type = 'RACKSPACE'
+            self.conn_class.type = 'RACKSPACE'
 
         snapshot = self.driver.ex_list_snapshots()[0]
         ret = self.driver.ex_delete_snapshot(snapshot)
@@ -1905,8 +1896,7 @@ class OpenStack_1_1_Auth_2_0_Tests(OpenStack_1_1_Tests):
     driver_kwargs = {'ex_force_auth_version': '2.0'}
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = \
-            (OpenStack_2_0_MockHttp, OpenStack_2_0_MockHttp)
+        self.driver_klass.connectionCls.conn_class = OpenStack_2_0_MockHttp
         self.driver_klass.connectionCls.auth_url = "https://auth.api.example.com"
         OpenStackMockHttp.type = None
         OpenStack_1_1_MockHttp.type = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_packet.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_packet.py b/libcloud/test/compute/test_packet.py
index 3a17b11..18799a5 100644
--- a/libcloud/test/compute/test_packet.py
+++ b/libcloud/test/compute/test_packet.py
@@ -33,7 +33,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 
 class PacketTest(unittest.TestCase, TestCaseMixin):
     def setUp(self):
-        PacketNodeDriver.connectionCls.conn_classes = (None, PacketMockHttp)
+        PacketNodeDriver.connectionCls.conn_class = PacketMockHttp
         self.driver = PacketNodeDriver('foo')
 
     def test_list_nodes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_profitbricks.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_profitbricks.py b/libcloud/test/compute/test_profitbricks.py
index 0a5c068..3d28493 100644
--- a/libcloud/test/compute/test_profitbricks.py
+++ b/libcloud/test/compute/test_profitbricks.py
@@ -29,7 +29,7 @@ class ProfitBricksTests(unittest.TestCase):
 
     def setUp(self):
         ProfitBricks = get_driver(Provider.PROFIT_BRICKS)
-        ProfitBricks.connectionCls.conn_classes = (None, ProfitBricksMockHttp)
+        ProfitBricks.connectionCls.conn_class = ProfitBricksMockHttp
         self.driver = ProfitBricks(*PROFIT_BRICKS_PARAMS)
 
     ''' Server Function Tests

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_rackspace.py b/libcloud/test/compute/test_rackspace.py
index e24b873..3c31316 100644
--- a/libcloud/test/compute/test_rackspace.py
+++ b/libcloud/test/compute/test_rackspace.py
@@ -119,17 +119,16 @@ class RackspaceNovaLonMockHttp(RackspaceNovaMockHttp):
 
 # Does not derive from TestCase because it should not be used by setup.py test
 class BaseRackspaceNovaTestCase(object):
-    conn_classes = (RackspaceNovaMockHttp, RackspaceNovaMockHttp)
+    conn_class = RackspaceNovaMockHttp
     auth_url = 'https://auth.api.example.com'
 
     def create_driver(self):
         return self.driver_type(*self.driver_args, **self.driver_kwargs)
 
     def setUp(self):
-        self.driver_klass.connectionCls.conn_classes = self.conn_classes
+        self.driver_klass.connectionCls.conn_class = self.conn_class
         self.driver_klass.connectionCls.auth_url = self.auth_url
-        self.conn_classes[0].type = None
-        self.conn_classes[1].type = None
+        self.conn_class.type = None
         self.driver = self.create_driver()
         # normally authentication happens lazily, but we force it here
         self.driver.connection._populate_hosts_and_request_paths()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_rimuhosting.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_rimuhosting.py b/libcloud/test/compute/test_rimuhosting.py
index f8eb3ab..76b2c91 100644
--- a/libcloud/test/compute/test_rimuhosting.py
+++ b/libcloud/test/compute/test_rimuhosting.py
@@ -28,8 +28,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 class RimuHostingTest(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        RimuHostingNodeDriver.connectionCls.conn_classes = (None,
-                                                            RimuHostingMockHttp)
+        RimuHostingNodeDriver.connectionCls.conn_class = RimuHostingMockHttp
         self.driver = RimuHostingNodeDriver('foo')
 
     def test_list_nodes(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_runabove.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_runabove.py b/libcloud/test/compute/test_runabove.py
index a1538e0..bf20b87 100644
--- a/libcloud/test/compute/test_runabove.py
+++ b/libcloud/test/compute/test_runabove.py
@@ -107,8 +107,7 @@ class RunAboveMockHttp(BaseRunAboveMockHttp):
 @patch('libcloud.common.runabove.RunAboveConnection._timedelta', 42)
 class RunAboveTests(unittest.TestCase):
     def setUp(self):
-        RunAboveNodeDriver.connectionCls.conn_classes = (
-            RunAboveMockHttp, RunAboveMockHttp)
+        RunAboveNodeDriver.connectionCls.conn_class = RunAboveMockHttp
         RunAboveMockHttp.type = None
         self.driver = RunAboveNodeDriver(*RUNABOVE_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_softlayer.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_softlayer.py b/libcloud/test/compute/test_softlayer.py
index d1e74fa..b3ebcb6 100644
--- a/libcloud/test/compute/test_softlayer.py
+++ b/libcloud/test/compute/test_softlayer.py
@@ -45,8 +45,7 @@ null_fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \
 class SoftLayerTests(unittest.TestCase):
 
     def setUp(self):
-        SoftLayer.connectionCls.conn_classes = (
-            SoftLayerMockHttp, SoftLayerMockHttp)
+        SoftLayer.connectionCls.conn_class = SoftLayerMockHttp
         SoftLayerMockHttp.type = None
         self.driver = SoftLayer(*SOFTLAYER_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_vcl.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_vcl.py b/libcloud/test/compute/test_vcl.py
index 31d0fb0..f8604d0 100644
--- a/libcloud/test/compute/test_vcl.py
+++ b/libcloud/test/compute/test_vcl.py
@@ -30,8 +30,7 @@ from libcloud.test.secrets import VCL_PARAMS
 class VCLTests(unittest.TestCase):
 
     def setUp(self):
-        VCL.connectionCls.conn_classes = (
-            VCLMockHttp, VCLMockHttp)
+        VCL.connectionCls.conn_class = VCLMockHttp
         VCLMockHttp.type = None
         self.driver = VCL(*VCL_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_vcloud.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_vcloud.py b/libcloud/test/compute/test_vcloud.py
index 74acaeb..4a743f4 100644
--- a/libcloud/test/compute/test_vcloud.py
+++ b/libcloud/test/compute/test_vcloud.py
@@ -42,7 +42,7 @@ class TerremarkTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         VCloudNodeDriver.connectionCls.host = "test"
-        VCloudNodeDriver.connectionCls.conn_classes = (None, TerremarkMockHttp)
+        VCloudNodeDriver.connectionCls.conn_class = TerremarkMockHttp
         TerremarkMockHttp.type = None
         self.driver = TerremarkDriver(*VCLOUD_PARAMS)
 
@@ -96,8 +96,7 @@ class VCloud_1_5_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         VCloudNodeDriver.connectionCls.host = 'test'
-        VCloudNodeDriver.connectionCls.conn_classes = (
-            None, VCloud_1_5_MockHttp)
+        VCloudNodeDriver.connectionCls.conn_class = VCloud_1_5_MockHttp
         VCloud_1_5_MockHttp.type = None
         self.driver = VCloud_1_5_NodeDriver(*VCLOUD_PARAMS)
 
@@ -339,8 +338,7 @@ class VCloud_5_1_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         VCloudNodeDriver.connectionCls.host = 'test'
-        VCloudNodeDriver.connectionCls.conn_classes = (
-            None, VCloud_1_5_MockHttp)
+        VCloudNodeDriver.connectionCls.conn_class = VCloud_1_5_MockHttp
         VCloud_1_5_MockHttp.type = None
         self.driver = VCloudNodeDriver(
             *VCLOUD_PARAMS, **{'api_version': '5.1'})
@@ -397,8 +395,7 @@ class VCloud_5_5_Tests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
         VCloudNodeDriver.connectionCls.host = 'test'
-        VCloudNodeDriver.connectionCls.conn_classes = (
-            None, VCloud_5_5_MockHttp)
+        VCloudNodeDriver.connectionCls.conn_class = VCloud_5_5_MockHttp
         VCloud_5_5_MockHttp.type = None
         self.driver = VCloudNodeDriver(
             *VCLOUD_PARAMS, **{'api_version': '5.5'})

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_voxel.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_voxel.py b/libcloud/test/compute/test_voxel.py
index e8ea8b0..a9486c9 100644
--- a/libcloud/test/compute/test_voxel.py
+++ b/libcloud/test/compute/test_voxel.py
@@ -30,7 +30,7 @@ class VoxelTest(unittest.TestCase):
 
     def setUp(self):
 
-        Voxel.connectionCls.conn_classes = (None, VoxelMockHttp)
+        Voxel.connectionCls.conn_class = VoxelMockHttp
         VoxelMockHttp.type = None
         self.driver = Voxel(*VOXEL_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_vpsnet.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_vpsnet.py b/libcloud/test/compute/test_vpsnet.py
index 9053a46..d01b1b0 100644
--- a/libcloud/test/compute/test_vpsnet.py
+++ b/libcloud/test/compute/test_vpsnet.py
@@ -30,7 +30,7 @@ from libcloud.test.file_fixtures import ComputeFileFixtures
 class VPSNetTests(unittest.TestCase, TestCaseMixin):
 
     def setUp(self):
-        VPSNetNodeDriver.connectionCls.conn_classes = (None, VPSNetMockHttp)
+        VPSNetNodeDriver.connectionCls.conn_class = VPSNetMockHttp
         self.driver = VPSNetNodeDriver(*VPSNET_PARAMS)
 
     def test_create_node(self):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/compute/test_vultr.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_vultr.py b/libcloud/test/compute/test_vultr.py
index 066cc86..6a34194 100644
--- a/libcloud/test/compute/test_vultr.py
+++ b/libcloud/test/compute/test_vultr.py
@@ -33,8 +33,7 @@ from libcloud.test.secrets import VULTR_PARAMS
 class VultrTests(LibcloudTestCase):
 
     def setUp(self):
-        VultrNodeDriver.connectionCls.conn_classes = \
-            (VultrMockHttp, VultrMockHttp)
+        VultrNodeDriver.connectionCls.conn_class = VultrMockHttp
         VultrMockHttp.type = None
         self.driver = VultrNodeDriver(*VULTR_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/container/test_docker.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_docker.py b/libcloud/test/container/test_docker.py
index a1978f7..ba2f29a 100644
--- a/libcloud/test/container/test_docker.py
+++ b/libcloud/test/container/test_docker.py
@@ -30,8 +30,7 @@ from libcloud.test import MockHttp
 class DockerContainerDriverTestCase(unittest.TestCase):
 
     def setUp(self):
-        DockerContainerDriver.connectionCls.conn_classes = (
-            DockerMockHttp, DockerMockHttp)
+        DockerContainerDriver.connectionCls.conn_class = DockerMockHttp
         DockerMockHttp.type = None
         DockerMockHttp.use_param = 'a'
         self.driver = DockerContainerDriver(*CONTAINER_PARAMS_DOCKER)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/container/test_docker_utils.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_docker_utils.py b/libcloud/test/container/test_docker_utils.py
index 8c8bd90..adf66a8 100644
--- a/libcloud/test/container/test_docker_utils.py
+++ b/libcloud/test/container/test_docker_utils.py
@@ -25,8 +25,7 @@ from libcloud.test import MockHttp
 class DockerUtilitiesTestCase(unittest.TestCase):
 
     def setUp(self):
-        HubClient.connectionCls.conn_classes = (
-            DockerMockHttp, DockerMockHttp)
+        HubClient.connectionCls.conn_class = DockerMockHttp
         DockerMockHttp.type = None
         DockerMockHttp.use_param = 'a'
         self.driver = HubClient()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/container/test_ecs.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_ecs.py b/libcloud/test/container/test_ecs.py
index 73a35b3..59956d8 100644
--- a/libcloud/test/container/test_ecs.py
+++ b/libcloud/test/container/test_ecs.py
@@ -30,12 +30,10 @@ from libcloud.test import MockHttp
 class ElasticContainerDriverTestCase(unittest.TestCase):
 
     def setUp(self):
-        ElasticContainerDriver.connectionCls.conn_classes = (
-            ECSMockHttp, ECSMockHttp)
+        ElasticContainerDriver.connectionCls.conn_class = ECSMockHttp
         ECSMockHttp.type = None
         ECSMockHttp.use_param = 'a'
-        ElasticContainerDriver.ecrConnectionClass.conn_classes = (
-            ECSMockHttp, ECSMockHttp)
+        ElasticContainerDriver.ecrConnectionClass.conn_class = ECSMockHttp
 
         self.driver = ElasticContainerDriver(*CONTAINER_PARAMS_ECS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/container/test_kubernetes.py
----------------------------------------------------------------------
diff --git a/libcloud/test/container/test_kubernetes.py b/libcloud/test/container/test_kubernetes.py
index b60a648..5ec57d9 100644
--- a/libcloud/test/container/test_kubernetes.py
+++ b/libcloud/test/container/test_kubernetes.py
@@ -30,8 +30,7 @@ from libcloud.test import MockHttp
 class KubernetesContainerDriverTestCase(unittest.TestCase):
 
     def setUp(self):
-        KubernetesContainerDriver.connectionCls.conn_classes = (
-            KubernetesMockHttp, KubernetesMockHttp)
+        KubernetesContainerDriver.connectionCls.conn_class = KubernetesMockHttp
         KubernetesMockHttp.type = None
         KubernetesMockHttp.use_param = 'a'
         self.driver = KubernetesContainerDriver(*CONTAINER_PARAMS_KUBERNETES)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_auroradns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_auroradns.py b/libcloud/test/dns/test_auroradns.py
index 278f76d..e599c65 100644
--- a/libcloud/test/dns/test_auroradns.py
+++ b/libcloud/test/dns/test_auroradns.py
@@ -33,8 +33,7 @@ from libcloud.utils.py3 import httplib
 class AuroraDNSDriverTests(LibcloudTestCase):
 
     def setUp(self):
-        AuroraDNSDriver.connectionCls.conn_classes = (None,
-                                                      AuroraDNSDriverMockHttp)
+        AuroraDNSDriver.connectionCls.conn_class = AuroraDNSDriverMockHttp
         AuroraDNSDriverMockHttp.type = None
         self.driver = AuroraDNSDriver(*DNS_PARAMS_AURORADNS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_cloudflare.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_cloudflare.py b/libcloud/test/dns/test_cloudflare.py
index 8cf3fe0..53ff755 100644
--- a/libcloud/test/dns/test_cloudflare.py
+++ b/libcloud/test/dns/test_cloudflare.py
@@ -30,8 +30,7 @@ from libcloud.test import MockHttp
 class CloudFlareDNSDriverTestCase(unittest.TestCase):
 
     def setUp(self):
-        CloudFlareDNSDriver.connectionCls.conn_classes = (
-            CloudFlareMockHttp, CloudFlareMockHttp)
+        CloudFlareDNSDriver.connectionCls.conn_class = CloudFlareMockHttp
         CloudFlareMockHttp.type = None
         CloudFlareMockHttp.use_param = 'a'
         self.driver = CloudFlareDNSDriver(*DNS_PARAMS_CLOUDFLARE)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_digitalocean.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_digitalocean.py b/libcloud/test/dns/test_digitalocean.py
index f1bb92e..8046fda 100644
--- a/libcloud/test/dns/test_digitalocean.py
+++ b/libcloud/test/dns/test_digitalocean.py
@@ -26,8 +26,7 @@ from libcloud.utils.py3 import httplib
 class DigitalOceanDNSTests(LibcloudTestCase):
 
     def setUp(self):
-        DigitalOceanDNSDriver.connectionCls.conn_classes = \
-            (None, DigitalOceanDNSMockHttp)
+        DigitalOceanDNSDriver.connectionCls.conn_class = DigitalOceanDNSMockHttp
         DigitalOceanDNSMockHttp.type = None
         self.driver = DigitalOceanDNSDriver(*DIGITALOCEAN_v2_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_dnsimple.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_dnsimple.py b/libcloud/test/dns/test_dnsimple.py
index b73ce75..3e48207 100644
--- a/libcloud/test/dns/test_dnsimple.py
+++ b/libcloud/test/dns/test_dnsimple.py
@@ -26,8 +26,7 @@ from libcloud.test.secrets import DNS_PARAMS_DNSIMPLE
 
 class DNSimpleDNSTests(unittest.TestCase):
     def setUp(self):
-        DNSimpleDNSDriver.connectionCls.conn_classes = (
-            None, DNSimpleDNSMockHttp)
+        DNSimpleDNSDriver.connectionCls.conn_class = DNSimpleDNSMockHttp
         DNSimpleDNSMockHttp.type = None
         self.driver = DNSimpleDNSDriver(*DNS_PARAMS_DNSIMPLE)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_durabledns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_durabledns.py b/libcloud/test/dns/test_durabledns.py
index 4d6cc88..5c0b041 100644
--- a/libcloud/test/dns/test_durabledns.py
+++ b/libcloud/test/dns/test_durabledns.py
@@ -34,8 +34,7 @@ from libcloud.dns.drivers.durabledns import RECORD_EXTRA_PARAMS_DEFAULT_VALUES
 class DurableDNSTests(LibcloudTestCase):
 
     def setUp(self):
-        DurableDNSDriver.connectionCls.conn_classes = \
-            (None, DurableDNSMockHttp)
+        DurableDNSDriver.connectionCls.conn_class = DurableDNSMockHttp
         DurableDNSMockHttp.type = None
         self.driver = DurableDNSDriver(*DNS_PARAMS_DURABLEDNS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_gandi.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_gandi.py b/libcloud/test/dns/test_gandi.py
index 4c3d6b6..c2c847a 100644
--- a/libcloud/test/dns/test_gandi.py
+++ b/libcloud/test/dns/test_gandi.py
@@ -28,8 +28,7 @@ from libcloud.test.common.test_gandi import BaseGandiMockHttp
 class GandiTests(unittest.TestCase):
 
     def setUp(self):
-        GandiDNSDriver.connectionCls.conn_classes = (
-            GandiMockHttp, GandiMockHttp)
+        GandiDNSDriver.connectionCls.conn_class = GandiMockHttp
         GandiMockHttp.type = None
         self.driver = GandiDNSDriver(*DNS_GANDI)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_godaddy.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_godaddy.py b/libcloud/test/dns/test_godaddy.py
index 76360b1..405c774 100644
--- a/libcloud/test/dns/test_godaddy.py
+++ b/libcloud/test/dns/test_godaddy.py
@@ -28,8 +28,7 @@ class GoDaddyTests(unittest.TestCase):
 
     def setUp(self):
         GoDaddyMockHttp.type = None
-        GoDaddyDNSDriver.connectionCls.conn_classes = (
-            None, GoDaddyMockHttp)
+        GoDaddyDNSDriver.connectionCls.conn_class = GoDaddyMockHttp
         self.driver = GoDaddyDNSDriver(*DNS_PARAMS_GODADDY)
 
     def assertHasKeys(self, dictionary, keys):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_google.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_google.py b/libcloud/test/dns/test_google.py
index 5c8adca..ebc2c0f 100644
--- a/libcloud/test/dns/test_google.py
+++ b/libcloud/test/dns/test_google.py
@@ -32,10 +32,8 @@ class GoogleTests(GoogleTestCase):
 
     def setUp(self):
         GoogleDNSMockHttp.test = self
-        GoogleDNSDriver.connectionCls.conn_classes = (GoogleDNSMockHttp,
-                                                      GoogleDNSMockHttp)
-        GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                 GoogleAuthMockHttp)
+        GoogleDNSDriver.connectionCls.conn_class = GoogleDNSMockHttp
+        GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp
         GoogleDNSMockHttp.type = None
         kwargs = DNS_KEYWORD_PARAMS_GOOGLE.copy()
         kwargs['auth_type'] = 'IA'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_hostvirtual.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_hostvirtual.py b/libcloud/test/dns/test_hostvirtual.py
index cb6ed8f..7fdfb2b 100644
--- a/libcloud/test/dns/test_hostvirtual.py
+++ b/libcloud/test/dns/test_hostvirtual.py
@@ -28,8 +28,7 @@ from libcloud.test.secrets import DNS_PARAMS_HOSTVIRTUAL
 
 class HostVirtualTests(unittest.TestCase):
     def setUp(self):
-        HostVirtualDNSDriver.connectionCls.conn_classes = (
-            None, HostVirtualMockHttp)
+        HostVirtualDNSDriver.connectionCls.conn_class = HostVirtualMockHttp
         HostVirtualMockHttp.type = None
         self.driver = HostVirtualDNSDriver(*DNS_PARAMS_HOSTVIRTUAL)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_linode.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_linode.py b/libcloud/test/dns/test_linode.py
index 7933a51..d197c1d 100644
--- a/libcloud/test/dns/test_linode.py
+++ b/libcloud/test/dns/test_linode.py
@@ -29,8 +29,7 @@ from libcloud.test.secrets import DNS_PARAMS_LINODE
 
 class LinodeTests(unittest.TestCase):
     def setUp(self):
-        LinodeDNSDriver.connectionCls.conn_classes = (
-            None, LinodeMockHttp)
+        LinodeDNSDriver.connectionCls.conn_class = LinodeMockHttp
         LinodeMockHttp.use_param = 'api_action'
         LinodeMockHttp.type = None
         self.driver = LinodeDNSDriver(*DNS_PARAMS_LINODE)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_liquidweb.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_liquidweb.py b/libcloud/test/dns/test_liquidweb.py
index f7f96fa..95e4b78 100644
--- a/libcloud/test/dns/test_liquidweb.py
+++ b/libcloud/test/dns/test_liquidweb.py
@@ -31,8 +31,7 @@ class LiquidWebTests(unittest.TestCase):
 
     def setUp(self):
         LiquidWebMockHttp.type = None
-        LiquidWebDNSDriver.connectionCls.conn_classes = (
-            None, LiquidWebMockHttp)
+        LiquidWebDNSDriver.connectionCls.conn_class = LiquidWebMockHttp
         self.driver = LiquidWebDNSDriver(*DNS_PARAMS_LIQUIDWEB)
         self.test_zone = Zone(id='11', type='master', ttl=None,
                               domain='example.com', extra={},

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_nsone.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_nsone.py b/libcloud/test/dns/test_nsone.py
index 9387542..91f8b00 100644
--- a/libcloud/test/dns/test_nsone.py
+++ b/libcloud/test/dns/test_nsone.py
@@ -14,7 +14,7 @@ from libcloud.dns.base import Zone, Record
 class NsOneTests(unittest.TestCase):
     def setUp(self):
         NsOneMockHttp.type = None
-        NsOneDNSDriver.connectionCls.conn_classes = (None, NsOneMockHttp)
+        NsOneDNSDriver.connectionCls.conn_class = NsOneMockHttp
         self.driver = NsOneDNSDriver(*DNS_PARAMS_NSONE)
         self.test_zone = Zone(id='test.com', type='master', ttl=None,
                               domain='test.com', extra={}, driver=self)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_pointdns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_pointdns.py b/libcloud/test/dns/test_pointdns.py
index 0dfb417..3a8180d 100644
--- a/libcloud/test/dns/test_pointdns.py
+++ b/libcloud/test/dns/test_pointdns.py
@@ -30,8 +30,7 @@ from libcloud.test.secrets import DNS_PARAMS_POINTDNS
 
 class PointDNSTests(unittest.TestCase):
     def setUp(self):
-        PointDNSDriver.connectionCls.conn_classes = (
-            None, PointDNSMockHttp)
+        PointDNSDriver.connectionCls.conn_class = PointDNSMockHttp
         PointDNSMockHttp.type = None
         self.driver = PointDNSDriver(*DNS_PARAMS_POINTDNS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_rackspace.py b/libcloud/test/dns/test_rackspace.py
index aa8ad10..6140987 100644
--- a/libcloud/test/dns/test_rackspace.py
+++ b/libcloud/test/dns/test_rackspace.py
@@ -51,8 +51,7 @@ class RackspaceUSTests(unittest.TestCase):
     endpoint_url = 'https://dns.api.rackspacecloud.com/v1.0/11111'
 
     def setUp(self):
-        self.klass.connectionCls.conn_classes = (
-            None, RackspaceMockHttp)
+        self.klass.connectionCls.conn_class = RackspaceMockHttp
         RackspaceMockHttp.type = None
         self.driver = self.klass(*DNS_PARAMS_RACKSPACE)
         self.driver.connection.poll_interval = 0.0

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_route53.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_route53.py b/libcloud/test/dns/test_route53.py
index 157d469..1692f22 100644
--- a/libcloud/test/dns/test_route53.py
+++ b/libcloud/test/dns/test_route53.py
@@ -28,8 +28,7 @@ from libcloud.test.secrets import DNS_PARAMS_ROUTE53
 
 class Route53Tests(unittest.TestCase):
     def setUp(self):
-        Route53DNSDriver.connectionCls.conn_classes = (
-            Route53MockHttp, Route53MockHttp)
+        Route53DNSDriver.connectionCls.conn_class = Route53MockHttp
         Route53MockHttp.type = None
         self.driver = Route53DNSDriver(*DNS_PARAMS_ROUTE53)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_softlayer.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_softlayer.py b/libcloud/test/dns/test_softlayer.py
index fcb6d4d..4a9e93f 100644
--- a/libcloud/test/dns/test_softlayer.py
+++ b/libcloud/test/dns/test_softlayer.py
@@ -30,8 +30,7 @@ from libcloud.utils.py3 import xmlrpclib
 class SoftLayerTests(unittest.TestCase):
 
     def setUp(self):
-        SoftLayerDNSDriver.connectionCls.conn_classes = (
-            SoftLayerDNSMockHttp, SoftLayerDNSMockHttp)
+        SoftLayerDNSDriver.connectionCls.conn_class = SoftLayerDNSMockHttp
         SoftLayerDNSMockHttp.type = None
         self.driver = SoftLayerDNSDriver(*SOFTLAYER_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_vultr.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_vultr.py b/libcloud/test/dns/test_vultr.py
index abbc570..2a1a848 100644
--- a/libcloud/test/dns/test_vultr.py
+++ b/libcloud/test/dns/test_vultr.py
@@ -31,8 +31,7 @@ class VultrTests(unittest.TestCase):
 
     def setUp(self):
         VultrMockHttp.type = None
-        VultrDNSDriver.connectionCls.conn_classes = (
-            None, VultrMockHttp)
+        VultrDNSDriver.connectionCls.conn_class = VultrMockHttp
         self.driver = VultrDNSDriver(*VULTR_PARAMS)
         self.test_zone = Zone(id='test.com', type='master', ttl=None,
                               domain='test.com', extra={}, driver=self)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_worldwidedns.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_worldwidedns.py b/libcloud/test/dns/test_worldwidedns.py
index 388e5c0..ccd54b7 100644
--- a/libcloud/test/dns/test_worldwidedns.py
+++ b/libcloud/test/dns/test_worldwidedns.py
@@ -31,8 +31,7 @@ from libcloud.test.secrets import DNS_PARAMS_WORLDWIDEDNS
 
 class WorldWideDNSTests(unittest.TestCase):
     def setUp(self):
-        WorldWideDNSDriver.connectionCls.conn_classes = (
-            None, WorldWideDNSMockHttp)
+        WorldWideDNSDriver.connectionCls.conn_class = WorldWideDNSMockHttp
         WorldWideDNSMockHttp.type = None
         self.driver = WorldWideDNSDriver(*DNS_PARAMS_WORLDWIDEDNS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_zerigo.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_zerigo.py b/libcloud/test/dns/test_zerigo.py
index 7897c00..ec4141f 100644
--- a/libcloud/test/dns/test_zerigo.py
+++ b/libcloud/test/dns/test_zerigo.py
@@ -29,8 +29,7 @@ from libcloud.test.secrets import DNS_PARAMS_ZERIGO
 
 class ZerigoTests(unittest.TestCase):
     def setUp(self):
-        ZerigoDNSDriver.connectionCls.conn_classes = (
-            None, ZerigoMockHttp)
+        ZerigoDNSDriver.connectionCls.conn_class = ZerigoMockHttp
         ZerigoMockHttp.type = None
         self.driver = ZerigoDNSDriver(*DNS_PARAMS_ZERIGO)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/dns/test_zonomi.py
----------------------------------------------------------------------
diff --git a/libcloud/test/dns/test_zonomi.py b/libcloud/test/dns/test_zonomi.py
index 186e2f5..302ead3 100644
--- a/libcloud/test/dns/test_zonomi.py
+++ b/libcloud/test/dns/test_zonomi.py
@@ -31,7 +31,7 @@ from libcloud.dns.base import Zone, Record
 class ZonomiTests(unittest.TestCase):
 
     def setUp(self):
-        ZonomiDNSDriver.connectionCls.conn_classes = (None, ZonomiMockHttp)
+        ZonomiDNSDriver.connectionCls.conn_class = ZonomiMockHttp
         ZonomiMockHttp.type = None
         self.driver = ZonomiDNSDriver(*DNS_PARAMS_ZONOMI)
         self.test_zone = Zone(id='zone.com', domain='zone.com',

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_brightbox.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_brightbox.py b/libcloud/test/loadbalancer/test_brightbox.py
index 2509d13..ba95c64 100644
--- a/libcloud/test/loadbalancer/test_brightbox.py
+++ b/libcloud/test/loadbalancer/test_brightbox.py
@@ -28,8 +28,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 
 class BrightboxLBTests(unittest.TestCase):
     def setUp(self):
-        BrightboxLBDriver.connectionCls.conn_classes = (None,
-                                                        BrightboxLBMockHttp)
+        BrightboxLBDriver.connectionCls.conn_class = BrightboxLBMockHttp
         BrightboxLBMockHttp.type = None
         self.driver = BrightboxLBDriver(*LB_BRIGHTBOX_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_cloudstack.py b/libcloud/test/loadbalancer/test_cloudstack.py
index 05f3cbc..4218f6e 100644
--- a/libcloud/test/loadbalancer/test_cloudstack.py
+++ b/libcloud/test/loadbalancer/test_cloudstack.py
@@ -21,8 +21,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 
 class CloudStackLBTests(unittest.TestCase):
     def setUp(self):
-        CloudStackLBDriver.connectionCls.conn_classes = \
-            (None, CloudStackMockHttp)
+        CloudStackLBDriver.connectionCls.conn_class = CloudStackMockHttp
 
         CloudStackLBDriver.path = '/test/path'
         CloudStackLBDriver.type = -1

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_dimensiondata.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_dimensiondata.py b/libcloud/test/loadbalancer/test_dimensiondata.py
index 2b6a1f9..d5b84ad 100644
--- a/libcloud/test/loadbalancer/test_dimensiondata.py
+++ b/libcloud/test/loadbalancer/test_dimensiondata.py
@@ -32,7 +32,7 @@ from libcloud.test.secrets import DIMENSIONDATA_PARAMS
 class DimensionDataTests(unittest.TestCase):
 
     def setUp(self):
-        DimensionData.connectionCls.conn_classes = (None, DimensionDataMockHttp)
+        DimensionData.connectionCls.conn_class = DimensionDataMockHttp
         DimensionDataMockHttp.type = None
         self.driver = DimensionData(*DIMENSIONDATA_PARAMS)
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_elb.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_elb.py b/libcloud/test/loadbalancer/test_elb.py
index 88f5555..31213e8 100644
--- a/libcloud/test/loadbalancer/test_elb.py
+++ b/libcloud/test/loadbalancer/test_elb.py
@@ -29,8 +29,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 class ElasticLBTests(unittest.TestCase):
     def setUp(self):
         ElasticLBMockHttp.test = self
-        ElasticLBDriver.connectionCls.conn_classes = (None,
-                                                      ElasticLBMockHttp)
+        ElasticLBDriver.connectionCls.conn_class = ElasticLBMockHttp
         ElasticLBMockHttp.type = None
         ElasticLBMockHttp.use_param = 'Action'
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_gce.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_gce.py b/libcloud/test/loadbalancer/test_gce.py
index 41d0594..8d5384f 100644
--- a/libcloud/test/loadbalancer/test_gce.py
+++ b/libcloud/test/loadbalancer/test_gce.py
@@ -32,10 +32,9 @@ class GCELoadBalancerTest(GoogleTestCase):
 
     def setUp(self):
         GCEMockHttp.test = self
-        GCELBDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp)
-        GCENodeDriver.connectionCls.conn_classes = (GCEMockHttp, GCEMockHttp)
-        GoogleBaseAuthConnection.conn_classes = (GoogleAuthMockHttp,
-                                                 GoogleAuthMockHttp)
+        GCELBDriver.connectionCls.conn_class = GCEMockHttp
+        GCENodeDriver.connectionCls.conn_class = GCEMockHttp
+        GoogleBaseAuthConnection.conn_class = GoogleAuthMockHttp
         GCEMockHttp.type = None
         kwargs = GCE_KEYWORD_PARAMS.copy()
         kwargs['auth_type'] = 'IA'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_gogrid.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_gogrid.py b/libcloud/test/loadbalancer/test_gogrid.py
index 5ad3e80..53ce120 100644
--- a/libcloud/test/loadbalancer/test_gogrid.py
+++ b/libcloud/test/loadbalancer/test_gogrid.py
@@ -32,8 +32,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 class GoGridTests(unittest.TestCase):
 
     def setUp(self):
-        GoGridLBDriver.connectionCls.conn_classes = (None,
-                                                     GoGridLBMockHttp)
+        GoGridLBDriver.connectionCls.conn_class = GoGridLBMockHttp
         GoGridLBMockHttp.type = None
         self.driver = GoGridLBDriver('user', 'key')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_rackspace.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_rackspace.py b/libcloud/test/loadbalancer/test_rackspace.py
index 9b78395..1eefeb8 100644
--- a/libcloud/test/loadbalancer/test_rackspace.py
+++ b/libcloud/test/loadbalancer/test_rackspace.py
@@ -42,8 +42,7 @@ from libcloud.test.file_fixtures import OpenStackFixtures
 class RackspaceLBTests(unittest.TestCase):
 
     def setUp(self):
-        RackspaceLBDriver.connectionCls.conn_classes = (None,
-                                                        RackspaceLBMockHttp)
+        RackspaceLBDriver.connectionCls.conn_class = RackspaceLBMockHttp
         RackspaceLBMockHttp.type = None
         self.driver = RackspaceLBDriver('user', 'key')
         self.driver.connection.poll_interval = 0.0
@@ -168,8 +167,7 @@ class RackspaceLBTests(unittest.TestCase):
         self.assertEqual(balancer.id, '8290')
 
     def test_ex_create_balancer(self):
-        RackspaceLBDriver.connectionCls.conn_classes = (None,
-                                                        RackspaceLBWithVIPMockHttp)
+        RackspaceLBDriver.connectionCls.conn_class = RackspaceLBWithVIPMockHttp
         RackspaceLBMockHttp.type = None
         driver = RackspaceLBDriver('user', 'key')
         balancer = driver.ex_create_balancer(name='test2',
@@ -919,8 +917,7 @@ class RackspaceLBTests(unittest.TestCase):
 class RackspaceUKLBTests(RackspaceLBTests):
 
     def setUp(self):
-        RackspaceLBDriver.connectionCls.conn_classes = (None,
-                                                        RackspaceLBMockHttp)
+        RackspaceLBDriver.connectionCls.conn_class = RackspaceLBMockHttp
         RackspaceLBMockHttp.type = None
         self.driver = RackspaceUKLBDriver('user', 'key')
         # normally authentication happens lazily, but we force it here

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_slb.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_slb.py b/libcloud/test/loadbalancer/test_slb.py
index 0325cb2..e7d7546 100644
--- a/libcloud/test/loadbalancer/test_slb.py
+++ b/libcloud/test/loadbalancer/test_slb.py
@@ -34,8 +34,7 @@ class SLBDriverTestCases(unittest.TestCase):
 
     def setUp(self):
         SLBMockHttp.test = self
-        SLBDriver.connectionCls.conn_classes = (None,
-                                                SLBMockHttp)
+        SLBDriver.connectionCls.conn_class = SLBMockHttp
         SLBMockHttp.type = None
         SLBMockHttp.use_param = 'Action'
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/loadbalancer/test_softlayer.py
----------------------------------------------------------------------
diff --git a/libcloud/test/loadbalancer/test_softlayer.py b/libcloud/test/loadbalancer/test_softlayer.py
index 90499be..ea19e79 100644
--- a/libcloud/test/loadbalancer/test_softlayer.py
+++ b/libcloud/test/loadbalancer/test_softlayer.py
@@ -32,8 +32,7 @@ from libcloud.test.file_fixtures import LoadBalancerFileFixtures
 class SoftlayerLBTests(unittest.TestCase):
     def setUp(self):
 
-        SoftlayerLBDriver.connectionCls.conn_classes = (SoftLayerMockHttp,
-                                                        SoftLayerMockHttp)
+        SoftlayerLBDriver.connectionCls.conn_class = SoftLayerMockHttp
         SoftLayerMockHttp.type = None
 
         self.driver = SoftlayerLBDriver(*SOFTLAYER_PARAMS)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_atmos.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_atmos.py b/libcloud/test/storage/test_atmos.py
index 561ac2f..27287eb 100644
--- a/libcloud/test/storage/test_atmos.py
+++ b/libcloud/test/storage/test_atmos.py
@@ -40,7 +40,7 @@ from libcloud.test.file_fixtures import StorageFileFixtures
 class AtmosTests(unittest.TestCase):
 
     def setUp(self):
-        AtmosDriver.connectionCls.conn_classes = (None, AtmosMockHttp)
+        AtmosDriver.connectionCls.conn_class = AtmosMockHttp
         AtmosDriver.connectionCls.rawResponseCls = AtmosMockRawResponse
         AtmosDriver.path = ''
         AtmosMockHttp.type = None

http://git-wip-us.apache.org/repos/asf/libcloud/blob/6fd28b6b/libcloud/test/storage/test_azure_blobs.py
----------------------------------------------------------------------
diff --git a/libcloud/test/storage/test_azure_blobs.py b/libcloud/test/storage/test_azure_blobs.py
index f9ee585..9f42298 100644
--- a/libcloud/test/storage/test_azure_blobs.py
+++ b/libcloud/test/storage/test_azure_blobs.py
@@ -374,8 +374,7 @@ class AzureBlobsTests(unittest.TestCase):
         return self.driver_type(*self.driver_args)
 
     def setUp(self):
-        self.driver_type.connectionCls.conn_classes = (None,
-                                                       self.mock_response_klass)
+        self.driver_type.connectionCls.conn_class = self.mock_response_klass
         self.driver_type.connectionCls.rawResponseCls = \
             self.mock_raw_response_klass
         self.mock_response_klass.type = None


[06/33] libcloud git commit: Setup proxy using a requests session instead of instantiating sockets

Posted by an...@apache.org.
Setup proxy using a requests session instead of instantiating sockets


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/41919008
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/41919008
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/41919008

Branch: refs/heads/requests
Commit: 41919008fcb86c2d914c2927ca691f6d980f15f2
Parents: 96f69cf
Author: anthony-shaw <an...@gmail.com>
Authored: Sun Mar 27 11:50:07 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Sun Mar 27 11:50:07 2016 +1100

----------------------------------------------------------------------
 libcloud/httplib_ssl.py             | 92 ++++++++------------------------
 libcloud/test/secrets.py            | 91 +++++++++++++++++++++++++++++++
 libcloud/test/test_connection.py    |  2 +-
 libcloud/utils/loggingconnection.py |  2 +-
 4 files changed, 115 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/httplib_ssl.py
----------------------------------------------------------------------
diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py
index 2cf00fb..6e89a14 100644
--- a/libcloud/httplib_ssl.py
+++ b/libcloud/httplib_ssl.py
@@ -64,6 +64,8 @@ class LibcloudBaseConnection(object):
     Note: This class should not be instantiated directly.
     """
 
+    session = None
+
     proxy_scheme = None
     proxy_host = None
     proxy_port = None
@@ -73,6 +75,9 @@ class LibcloudBaseConnection(object):
 
     http_proxy_used = False
 
+    def __init__(self):
+        self.session = requests.Session()
+
     def set_http_proxy(self, proxy_url):
         """
         Set a HTTP proxy which will be used with this connection.
@@ -97,7 +102,9 @@ class LibcloudBaseConnection(object):
         self.proxy_password = password
         self.http_proxy_used = True
 
-        self._setup_http_proxy()
+        self.session.proxies = {
+            self.proxy_scheme: proxy_url
+        }
 
     def _parse_proxy_url(self, proxy_url):
         """
@@ -137,61 +144,6 @@ class LibcloudBaseConnection(object):
         return (proxy_scheme, proxy_host, proxy_port, proxy_username,
                 proxy_password)
 
-    def _setup_http_proxy(self):
-        """
-        Set up HTTP proxy.
-
-        :param proxy_url: Proxy URL (e.g. http://<host>:3128)
-        :type proxy_url: ``str``
-        """
-        headers = {}
-
-        if self.proxy_username and self.proxy_password:
-            # Include authentication header
-            user_pass = '%s:%s' % (self.proxy_username, self.proxy_password)
-            encoded = base64.encodestring(b(urlunquote(user_pass))).strip()
-            auth_header = 'Basic %s' % (encoded.decode('utf-8'))
-            headers['Proxy-Authorization'] = auth_header
-
-        if hasattr(self, 'set_tunnel'):
-            # Python 2.7 and higher
-            # pylint: disable=no-member
-            self.set_tunnel(host=self.host, port=self.port, headers=headers)
-        elif hasattr(self, '_set_tunnel'):
-            # Python 2.6
-            # pylint: disable=no-member
-            self._set_tunnel(host=self.host, port=self.port, headers=headers)
-        else:
-            raise ValueError('Unsupported Python version')
-
-        self._set_hostport(host=self.proxy_host, port=self.proxy_port)
-
-    def _activate_http_proxy(self, sock):
-        self.sock = sock
-        self._tunnel()  # pylint: disable=no-member
-
-    def _set_hostport(self, host, port):
-        """
-        Backported from Python stdlib so Proxy support also works with
-        Python 3.4.
-        """
-        if port is None:
-            i = host.rfind(':')
-            j = host.rfind(']')         # ipv6 addresses have [...]
-            if i > j:
-                try:
-                    port = int(host[i + 1:])
-                except ValueError:
-                    msg = "nonnumeric port: '%s'" % (host[i + 1:])
-                    raise httplib.InvalidURL(msg)
-                host = host[:i]
-            else:
-                port = self.default_port  # pylint: disable=no-member
-            if host and host[0] == '[' and host[-1] == ']':
-                host = host[1:-1]
-        self.host = host
-        self.port = port
-
 
 class LibcloudHTTPConnection(LibcloudBaseConnection):
     def __init__(self, *args, **kwargs):
@@ -199,23 +151,23 @@ class LibcloudHTTPConnection(LibcloudBaseConnection):
         proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
         proxy_url = kwargs.pop('proxy_url', proxy_url_env)
 
-        super(LibcloudHTTPConnection, self).__init__(*args, **kwargs)
+        super(LibcloudHTTPConnection, self).__init__()
 
         if proxy_url:
             self.set_http_proxy(proxy_url=proxy_url)
 
-        def connect():
-            pass
+    def connect():
+        pass
 
-        def request(method, url, body=None, headers=None):
-            method = method.lower()
-            if method == 'get':
-                response = requests.get(url, headers=headers)
-            elif method == 'post':
-                response = requests.post(url, data=body, headers=headers)
-            elif method == 'head':
-                response = requests.head(url, headers=headers)
-            return response
+    def request(self, method, url, body=None, headers=None):
+        method = method.lower()
+        if method == 'get':
+            response = self.session.get(url, headers=headers)
+        elif method == 'post':
+            response = self.session.post(url, data=body, headers=headers)
+        elif method == 'head':
+            response = self.session.head(url, headers=headers)
+        return response
 
 
 class LibcloudHTTPSConnection(LibcloudBaseConnection):
@@ -237,7 +189,7 @@ class LibcloudHTTPSConnection(LibcloudBaseConnection):
         proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
         proxy_url = kwargs.pop('proxy_url', proxy_url_env)
 
-        super(LibcloudHTTPSConnection, self).__init__(*args, **kwargs)
+        super(LibcloudHTTPSConnection, self).__init__()
 
         if proxy_url:
             self.set_http_proxy(proxy_url=proxy_url)
@@ -281,7 +233,7 @@ class LibcloudHTTPSConnection(LibcloudBaseConnection):
     def connect(self):
         pass
 
-    def request(method, url, body=None, headers=None):
+    def request(self, method, url, body=None, headers=None):
             method = method.lower()
             if method == 'get':
                 response = requests.get(url, headers=headers)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/test/secrets.py
----------------------------------------------------------------------
diff --git a/libcloud/test/secrets.py b/libcloud/test/secrets.py
index 5b228bc..480ac3f 100644
--- a/libcloud/test/secrets.py
+++ b/libcloud/test/secrets.py
@@ -1 +1,92 @@
+# 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.
+
+# Make a copy of this file named 'secrets.py' and add your credentials there.
+# Note you can run unit tests without setting your credentials.
+
+BLUEBOX_PARAMS = ('customer_id', 'api_key')
+BRIGHTBOX_PARAMS = ('client_id', 'client_secret')
+EC2_PARAMS = ('access_id', 'secret')
+ECP_PARAMS = ('user_name', 'password')
+GANDI_PARAMS = ('user',)
+GCE_PARAMS = ('email@developer.gserviceaccount.com', 'key')  # Service Account Authentication
+# GCE_PARAMS = ('client_id', 'client_secret')  # Installed App Authentication
+GCE_KEYWORD_PARAMS = {'project': 'project_name'}
+HOSTINGCOM_PARAMS = ('user', 'secret')
+IBM_PARAMS = ('user', 'secret')
+ONAPP_PARAMS = ('key',)
+# OPENSTACK_PARAMS = ('user_name', 'api_key', secure_bool, 'host', port_int)
+OPENSTACK_PARAMS = ('user_name', 'api_key', False, 'host', 8774)
+OPENNEBULA_PARAMS = ('user', 'key')
+DIMENSIONDATA_PARAMS = ('user', 'password')
+OPSOURCE_PARAMS = ('user', 'password')
+RUNABOVE_PARAMS = ('application_key', 'application_secret', 'consumer_key')
+RACKSPACE_PARAMS = ('user', 'key')
+RACKSPACE_NOVA_PARAMS = ('user_name', 'api_key', False, 'host', 8774)
+SLICEHOST_PARAMS = ('key',)
+SOFTLAYER_PARAMS = ('user', 'api_key')
+VCLOUD_PARAMS = ('user', 'secret')
+VOXEL_PARAMS = ('key', 'secret')
+VPSNET_PARAMS = ('user', 'key')
+JOYENT_PARAMS = ('user', 'key')
+VCL_PARAMS = ('user', 'pass', True, 'foo.bar.com')
+GRIDSPOT_PARAMS = ('key',)
+HOSTVIRTUAL_PARAMS = ('key',)
+DIGITALOCEAN_v1_PARAMS = ('user', 'key')
+DIGITALOCEAN_v2_PARAMS = ('token',)
+CLOUDFRAMES_PARAMS = ('key', 'secret', False, 'host', 8888)
+PROFIT_BRICKS_PARAMS = ('user', 'key')
+VULTR_PARAMS = ('key')
+PACKET_PARAMS = ('api_key')
+ECS_PARAMS = ('access_key', 'access_secret')
+
+# Storage
+STORAGE_S3_PARAMS = ('key', 'secret')
+STORAGE_OSS_PARAMS = ('key', 'secret')
+# Google key = 20 char alphanumeric string starting with GOOG
+STORAGE_GOOGLE_STORAGE_PARAMS = ('GOOG0123456789ABCXYZ', 'secret')
+
+# Azure key is b64 encoded and must be decoded before signing requests
+STORAGE_AZURE_BLOBS_PARAMS = ('account', 'cGFzc3dvcmQ=')
+
+# Loadbalancer
+LB_BRIGHTBOX_PARAMS = ('user', 'key')
+LB_ELB_PARAMS = ('access_id', 'secret', 'region')
+LB_SLB_PARAMS = ('access_id', 'secret', 'region')
+
+# DNS
+DNS_PARAMS_LINODE = ('user', 'key')
+DNS_PARAMS_ZERIGO = ('email', 'api token')
+DNS_PARAMS_RACKSPACE = ('user', 'key')
+DNS_PARAMS_HOSTVIRTUAL = ('key',)
+DNS_PARAMS_ROUTE53 = ('access_id', 'secret')
+DNS_GANDI = ('user', )
+DNS_PARAMS_GOOGLE = ('email_address', 'key')
+DNS_KEYWORD_PARAMS_GOOGLE = {'project': 'project_name'}
+DNS_PARAMS_WORLDWIDEDNS = ('user', 'key')
+DNS_PARAMS_DNSIMPLE = ('user', 'key')
+DNS_PARAMS_POINTDNS = ('user', 'key')
+DNS_PARAMS_LIQUIDWEB = ('user', 'key')
+DNS_PARAMS_ZONOMI = ('key')
+DNS_PARAMS_DURABLEDNS = ('api_user', 'api_key')
+DNS_PARAMS_GODADDY = ('customer-id', 'api_user', 'api_key')
+DNS_PARAMS_CLOUDFLARE = ('user@example.com', 'key')
+DNS_PARAMS_AURORADNS = ('apikey', 'secretkey')
 DNS_PARAMS_NSONE = ('key', )
+
+# Container
+CONTAINER_PARAMS_DOCKER = ('user', 'password')
+CONTAINER_PARAMS_ECS = ('user', 'password', 'region')
+CONTAINER_PARAMS_KUBERNETES = ('user', 'password')

http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/test/test_connection.py
----------------------------------------------------------------------
diff --git a/libcloud/test/test_connection.py b/libcloud/test/test_connection.py
index 783ed6a..a588ca6 100644
--- a/libcloud/test/test_connection.py
+++ b/libcloud/test/test_connection.py
@@ -23,7 +23,7 @@ from mock import Mock, call, patch
 
 from libcloud.test import unittest
 from libcloud.common.base import Connection
-from libcloud.common.utils.loggingconnection import LoggingConnection
+from libcloud.utils.loggingconnection import LoggingConnection
 from libcloud.httplib_ssl import LibcloudBaseConnection
 from libcloud.httplib_ssl import LibcloudHTTPConnection
 from libcloud.utils.misc import retry

http://git-wip-us.apache.org/repos/asf/libcloud/blob/41919008/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index bffd8f9..2b6550d 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -23,11 +23,11 @@ import xml.dom.minidom
 
 import sys
 import os
-import httplib
 
 from libcloud.common.base import (LibcloudHTTPConnection,
                                   LibcloudHTTPSConnection,
                                   HTTPResponse)
+from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import PY3
 from libcloud.utils.py3 import StringIO
 from libcloud.utils.py3 import u


[26/33] libcloud git commit: Fix cloudsigma tests

Posted by an...@apache.org.
Fix cloudsigma tests


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/d0f6d22d
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/d0f6d22d
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/d0f6d22d

Branch: refs/heads/requests
Commit: d0f6d22dbefe1de31cd13bdff813bb82c18f1a3d
Parents: 52778e5
Author: anthony-shaw <an...@gmail.com>
Authored: Fri Apr 1 15:08:25 2016 +1100
Committer: anthony-shaw <an...@gmail.com>
Committed: Fri Apr 1 15:08:25 2016 +1100

----------------------------------------------------------------------
 libcloud/test/compute/test_cloudsigma_v1_0.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/d0f6d22d/libcloud/test/compute/test_cloudsigma_v1_0.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudsigma_v1_0.py b/libcloud/test/compute/test_cloudsigma_v1_0.py
index 4c9f2e3..8a73cdd 100644
--- a/libcloud/test/compute/test_cloudsigma_v1_0.py
+++ b/libcloud/test/compute/test_cloudsigma_v1_0.py
@@ -33,10 +33,10 @@ class CloudSigmaAPI10BaseTestCase(object):
     driver_kwargs = {}
 
     def setUp(self):
+        self.driver_klass.connectionCls.conn_class = CloudSigmaHttp
+        CloudSigmaHttp.type = None
         self.driver = self.driver_klass(*self.driver_args,
                                         **self.driver_kwargs)
-        CloudSigmaHttp.type = None
-        self.driver.connectionCls.conn_class = CloudSigmaHttp
 
     def test_list_nodes(self):
         nodes = self.driver.list_nodes()


[33/33] libcloud git commit: Fix remaining test classes

Posted by an...@apache.org.
Fix remaining test classes


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/2519c34d
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/2519c34d
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/2519c34d

Branch: refs/heads/requests
Commit: 2519c34d7b375618d96ca60902e33b4d17f29dbe
Parents: 04d4655
Author: anthony-shaw <an...@gmail.com>
Authored: Tue Apr 5 18:25:03 2016 +1000
Committer: anthony-shaw <an...@gmail.com>
Committed: Tue Apr 5 18:25:03 2016 +1000

----------------------------------------------------------------------
 libcloud/common/base.py                  |  9 +++------
 libcloud/test/common/test_nfsn.py        |  2 +-
 libcloud/test/common/test_retry_limit.py | 26 --------------------------
 libcloud/utils/loggingconnection.py      |  1 +
 4 files changed, 5 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/2519c34d/libcloud/common/base.py
----------------------------------------------------------------------
diff --git a/libcloud/common/base.py b/libcloud/common/base.py
index b1ec3d9..2479394 100644
--- a/libcloud/common/base.py
+++ b/libcloud/common/base.py
@@ -36,7 +36,7 @@ import requests
 
 import libcloud
 
-from libcloud.utils.py3 import PY25, basestring
+from libcloud.utils.py3 import PY25
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import urlparse
 from libcloud.utils.py3 import urlencode
@@ -152,11 +152,8 @@ class Response(object):
         self.error = response.reason
         self.status = response.status_code
 
-        if isinstance(response.text, basestring):
-            self.body = response.text.strip() \
-                if response.text is not None else ''
-        else:
-            self.body = ''
+        self.body = response.text.strip() \
+            if response.text is not None else ''
 
         if not self.success():
             raise exception_from_message(code=self.status,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/2519c34d/libcloud/test/common/test_nfsn.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_nfsn.py b/libcloud/test/common/test_nfsn.py
index 5e77f32..8295f00 100644
--- a/libcloud/test/common/test_nfsn.py
+++ b/libcloud/test/common/test_nfsn.py
@@ -20,7 +20,7 @@ mock_header = 'testid;1000000;yumsalty1234;66dfb282a9532e5b8e6a9517764d5fbc001a4
 class NFSNConnectionTestCase(LibcloudTestCase):
 
     def setUp(self):
-        NFSNConnection.conn_classes = (None, NFSNMockHttp)
+        NFSNConnection.conn_class = NFSNMockHttp
         NFSNMockHttp.type = None
         self.driver = NFSNConnection('testid', 'testsecret')
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/2519c34d/libcloud/test/common/test_retry_limit.py
----------------------------------------------------------------------
diff --git a/libcloud/test/common/test_retry_limit.py b/libcloud/test/common/test_retry_limit.py
index 06eac2a..f57ccb3 100644
--- a/libcloud/test/common/test_retry_limit.py
+++ b/libcloud/test/common/test_retry_limit.py
@@ -14,16 +14,12 @@
 # limitations under the License.
 
 import socket
-import tempfile
 import ssl
 
 from mock import Mock, patch, MagicMock
 
-from libcloud.utils.py3 import httplib
 from libcloud.utils.misc import TRANSIENT_SSL_ERROR
 from libcloud.common.base import Connection
-from libcloud.common.base import Response
-from libcloud.common.exceptions import RateLimitReachedError
 from libcloud.test import unittest
 
 CONFLICT_RESPONSE_STATUS = [
@@ -65,27 +61,5 @@ class FailedRequestRetryTestCase(unittest.TestCase):
                 self.assertRaises(ssl.SSLError, conn.request, '/')
                 self.assertGreater(connection.request.call_count, 1)
 
-    def test_rate_limit_error(self):
-        sock = Mock()
-        con = Connection()
-
-        try:
-            with patch('libcloud.utils.py3.httplib.HTTPResponse.getheaders',
-                       MagicMock(return_value=CONFLICT_RESPONSE_STATUS)):
-                with patch(
-                        'libcloud.utils.py3.httplib.HTTPResponse._read_status',
-                        MagicMock(return_value=SIMPLE_RESPONSE_STATUS)):
-                    with tempfile.TemporaryFile(mode='w+b') as f:
-                        f.write('HTTP/1.1 429 CONFLICT\n'.encode())
-                        f.flush()
-                        sock.makefile = Mock(return_value=f)
-                        mock_obj = httplib.HTTPResponse(sock)
-                        mock_obj.begin()
-                        Response(mock_obj, con)
-        except RateLimitReachedError:
-            pass
-        except Exception:
-            self.fail('Failed to raise Rate Limit exception')
-
 if __name__ == '__main__':
     unittest.main()

http://git-wip-us.apache.org/repos/asf/libcloud/blob/2519c34d/libcloud/utils/loggingconnection.py
----------------------------------------------------------------------
diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py
index 966023a..71931b0 100644
--- a/libcloud/utils/loggingconnection.py
+++ b/libcloud/utils/loggingconnection.py
@@ -175,6 +175,7 @@ class LoggingConnection(LoggingBaseConnection, LibcloudConnection):
     """
 
     protocol = 'https'
+    port = None
 
     def getresponse(self):
         r = LibcloudConnection.getresponse(self)