Skip to content

Commit

Permalink
Prevent WantReadError when using https
Browse files Browse the repository at this point in the history
If the glance client is instantiated when the socket module has been
monkey patched requests to the server can yield a WantReadError because
the socket has been set to non-blocking but this is not being handled
correctly. When this is the case use eventlet's GreenConnection which
handles non-blocking sockets correctly.

Also, for now, add a required getsockopt method to GreenConnection.
This can be removed once the eventlet fix
(https://bitbucket.org/eventlet/eventlet/commits/609f230) lands.

Fixes bug 1157864.

Change-Id: I187b69f75b8bcfe16facd41e69b1cd0490dae605
  • Loading branch information
Stuart McLaren committed Apr 23, 2013
1 parent 42757e8 commit 2f33f5f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
25 changes: 20 additions & 5 deletions glanceclient/common/http.py
Expand Up @@ -37,6 +37,21 @@
from glanceclient import exc
from glanceclient.common import utils

try:
from eventlet import patcher
# Handle case where we are running in a monkey patched environment
if patcher.is_monkey_patched('socket'):
from eventlet.green.httplib import HTTPSConnection
from eventlet.green.OpenSSL.SSL import GreenConnection as Connection
from eventlet.greenio import GreenSocket
# TODO(mclaren): A getsockopt workaround: see 'getsockopt' doc string
GreenSocket.getsockopt = utils.getsockopt
else:
raise ImportError
except ImportError:
from httplib import HTTPSConnection
from OpenSSL.SSL import Connection as Connection


LOG = logging.getLogger(__name__)
USER_AGENT = 'python-glanceclient'
Expand Down Expand Up @@ -256,7 +271,7 @@ class OpenSSLConnectionDelegator(object):
a delegator must be used.
"""
def __init__(self, *args, **kwargs):
self.connection = OpenSSL.SSL.Connection(*args, **kwargs)
self.connection = Connection(*args, **kwargs)

def __getattr__(self, name):
return getattr(self.connection, name)
Expand All @@ -265,7 +280,7 @@ def makefile(self, *args, **kwargs):
return socket._fileobject(self.connection, *args, **kwargs)


class VerifiedHTTPSConnection(httplib.HTTPSConnection):
class VerifiedHTTPSConnection(HTTPSConnection):
"""
Extended HTTPSConnection which uses the OpenSSL library
for enhanced SSL support.
Expand All @@ -275,9 +290,9 @@ class VerifiedHTTPSConnection(httplib.HTTPSConnection):
def __init__(self, host, port=None, key_file=None, cert_file=None,
cacert=None, timeout=None, insecure=False,
ssl_compression=True):
httplib.HTTPSConnection.__init__(self, host, port,
key_file=key_file,
cert_file=cert_file)
HTTPSConnection.__init__(self, host, port,
key_file=key_file,
cert_file=cert_file)
self.key_file = key_file
self.cert_file = cert_file
self.timeout = timeout
Expand Down
11 changes: 11 additions & 0 deletions glanceclient/common/utils.py
Expand Up @@ -263,3 +263,14 @@ def ensure_str(text, incoming=None,
return text.encode(encoding, errors)

return text


def getsockopt(self, *args, **kwargs):
"""
A function which allows us to monkey patch eventlet's
GreenSocket, adding a required 'getsockopt' method.
TODO: (mclaren) we can remove this once the eventlet fix
(https://bitbucket.org/eventlet/eventlet/commits/609f230)
lands in mainstream packages.
"""
return self.fd.getsockopt(*args, **kwargs)

0 comments on commit 2f33f5f

Please sign in to comment.