diff options
| author | Vishvananda Ishaya <vishvananda@gmail.com> | 2012-11-09 13:53:48 -0800 |
|---|---|---|
| committer | Adam Young <ayoung@redhat.com> | 2012-11-09 17:56:29 -0500 |
| commit | 164326b433c7e8b7ff5afe4e478d346233a4062b (patch) | |
| tree | 75809399f979db5d948d944e82828df3dee359b5 | |
| parent | a10bd7a8eb418a4d9e84a9511ca3f0669e6e02e7 (diff) | |
Use the right subprocess based on os monkeypatch
This works around the following eventlet bug:
https://bitbucket.org/which_linden/eventlet/issue/92
by using the green version of Popen if os has been
monkeypatched. It also has the side effect of making the ssl
calls not block the reactor for workers that use eventlet.
Change-Id: I1457237f52310f0536fbcdcaa42174b17e8edbf5
| -rwxr-xr-x | bin/keystone-all | 5 | ||||
| -rw-r--r-- | keystone/common/cms.py | 61 | ||||
| -rw-r--r-- | keystone/middleware/auth_token.py | 3 |
3 files changed, 38 insertions, 31 deletions
diff --git a/bin/keystone-all b/bin/keystone-all index a51bb2c6..7724660d 100755 --- a/bin/keystone-all +++ b/bin/keystone-all @@ -3,7 +3,6 @@ import greenlet import eventlet -from eventlet.green import subprocess import logging import os import signal @@ -23,7 +22,6 @@ if os.path.exists(os.path.join(possible_topdir, from paste import deploy from keystone import config -from keystone.common import cms from keystone.common import wsgi from keystone.common import utils from keystone.openstack.common import importutils @@ -70,8 +68,6 @@ def serve(*servers): except greenlet.GreenletExit: pass -def monkeypatch_cms(): - cms.Popen = subprocess.Popen if __name__ == '__main__': @@ -98,7 +94,6 @@ if __name__ == '__main__': monkeypatch_thread = not CONF._cli_values['standard_threads'] eventlet.patcher.monkey_patch(all=False, socket=True, time=True, thread=monkeypatch_thread) - monkeypatch_cms() options = deploy.appconfig('config:%s' % CONF.config_file[0]) diff --git a/keystone/common/cms.py b/keystone/common/cms.py index 68d3a230..60885ddd 100644 --- a/keystone/common/cms.py +++ b/keystone/common/cms.py @@ -1,30 +1,43 @@ import hashlib -import subprocess -#Importing Popen directly knowingly goes against the coding standard -#It is required due to the need to Monkeypatch the cms use of Popen when -#running in eventlet. -from subprocess import Popen from keystone.common import logging +subprocess = None LOG = logging.getLogger(__name__) PKI_ANS1_PREFIX = 'MII' +def _ensure_subprocess(): + # NOTE(vish): late loading subprocess so we can + # use the green version if we are in + # eventlet. + global subprocess + if not subprocess: + try: + from eventlet import patcher + if patcher.already_patched.get('os'): + from eventlet.green import subprocess + else: + import subprocess + except ImportError: + import subprocess + + def cms_verify(formatted, signing_cert_file_name, ca_file_name): """ verifies the signature of the contents IAW CMS syntax """ - process = Popen(["openssl", "cms", "-verify", - "-certfile", signing_cert_file_name, - "-CAfile", ca_file_name, - "-inform", "PEM", - "-nosmimecap", "-nodetach", - "-nocerts", "-noattr"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + _ensure_subprocess() + process = subprocess.Popen(["openssl", "cms", "-verify", + "-certfile", signing_cert_file_name, + "-CAfile", ca_file_name, + "-inform", "PEM", + "-nosmimecap", "-nodetach", + "-nocerts", "-noattr"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) output, err = process.communicate(formatted) retcode = process.poll() if retcode: @@ -105,16 +118,16 @@ def cms_sign_text(text, signing_cert_file_name, signing_key_file_name): Produces a Base64 encoding of a DER formatted CMS Document http://en.wikipedia.org/wiki/Cryptographic_Message_Syntax """ - - process = Popen(["openssl", "cms", "-sign", - "-signer", signing_cert_file_name, - "-inkey", signing_key_file_name, - "-outform", "PEM", - "-nosmimecap", "-nodetach", - "-nocerts", "-noattr"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + _ensure_subprocess() + process = subprocess.Popen(["openssl", "cms", "-sign", + "-signer", signing_cert_file_name, + "-inkey", signing_key_file_name, + "-outform", "PEM", + "-nosmimecap", "-nodetach", + "-nocerts", "-noattr"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) output, err = process.communicate(text) retcode = process.poll() if retcode or "Error" in err: diff --git a/keystone/middleware/auth_token.py b/keystone/middleware/auth_token.py index c4dddc7b..86fcb66b 100644 --- a/keystone/middleware/auth_token.py +++ b/keystone/middleware/auth_token.py @@ -99,7 +99,6 @@ import json import logging import os import stat -import subprocess import time import webob import webob.exc @@ -736,7 +735,7 @@ class AuthProtocol(object): try: output = cms.cms_verify(data, self.signing_cert_file_name, self.ca_file_name) - except subprocess.CalledProcessError as err: + except cms.subprocess.CalledProcessError as err: if self.cert_file_missing(err, self.signing_cert_file_name): self.fetch_signing_cert() continue |
