summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2012-11-09 13:53:48 -0800
committerAdam Young <ayoung@redhat.com>2012-11-09 17:56:29 -0500
commit164326b433c7e8b7ff5afe4e478d346233a4062b (patch)
tree75809399f979db5d948d944e82828df3dee359b5
parenta10bd7a8eb418a4d9e84a9511ca3f0669e6e02e7 (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-xbin/keystone-all5
-rw-r--r--keystone/common/cms.py61
-rw-r--r--keystone/middleware/auth_token.py3
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