From 3afd9791ef3e2472987cdabb54ef5f27a062469c Mon Sep 17 00:00:00 2001 From: Jamie Lennox Date: Thu, 30 May 2013 17:48:04 +1000 Subject: Isolate eventlet code into environment. The environment module will be configured once, during code initialization. Subsequently all other possibly-evented modules will retrieve from environment and transparently obtain either the eventlet or standard library modules. If eventlet, httplib, subprocess or other environment dependant module is referenced outside of the environment module it should be considered a bug. The changes to tests are required to ensure that test is imported first to setup the environment. Hopefully these can all be replaced with an __init__.py in a post-nose keystone. Implements: blueprint extract-eventlet Change-Id: Icacd6f2ee0906ac5d303777c1f87a184f38283bf --- bin/keystone-all | 12 +-- bin/keystone-manage | 2 + httpd/keystone.py | 2 + keystone/auth/token_factory.py | 4 +- keystone/common/cms.py | 62 +++++------- keystone/common/environment/__init__.py | 78 +++++++++++++++ keystone/common/environment/eventlet_server.py | 114 +++++++++++++++++++++ keystone/common/openssl.py | 4 +- keystone/common/utils.py | 7 +- keystone/common/wsgi_server.py | 133 ------------------------- keystone/middleware/ec2_token.py | 6 +- keystone/middleware/s3_token.py | 10 +- keystone/test.py | 16 ++- keystone/token/controllers.py | 4 +- tests/test_auth.py | 3 +- tests/test_auth_plugin.py | 3 +- tests/test_backend.py | 3 +- tests/test_backend_kvs.py | 3 +- tests/test_backend_ldap.py | 3 +- tests/test_backend_memcache.py | 3 +- tests/test_backend_pam.py | 3 +- tests/test_backend_sql.py | 3 +- tests/test_backend_templated.py | 3 +- tests/test_cert_setup.py | 3 +- tests/test_config.py | 3 +- tests/test_content_types.py | 3 +- tests/test_contrib_s3_core.py | 3 +- tests/test_exception.py | 3 +- tests/test_import_legacy.py | 3 +- tests/test_ipv6.py | 8 +- tests/test_keystoneclient.py | 3 +- tests/test_keystoneclient_sql.py | 3 +- tests/test_middleware.py | 3 +- tests/test_migrate_nova_auth.py | 3 +- tests/test_policy.py | 3 +- tests/test_sizelimit.py | 3 +- tests/test_sql_upgrade.py | 3 +- tests/test_ssl.py | 28 +++--- tests/test_url_middleware.py | 3 +- tests/test_utils.py | 3 +- tests/test_v3.py | 3 +- tests/test_versions.py | 3 +- tests/test_wsgi.py | 3 +- 43 files changed, 322 insertions(+), 249 deletions(-) create mode 100644 keystone/common/environment/__init__.py create mode 100644 keystone/common/environment/eventlet_server.py delete mode 100644 keystone/common/wsgi_server.py diff --git a/bin/keystone-all b/bin/keystone-all index 7e6711b5..53b50199 100755 --- a/bin/keystone-all +++ b/bin/keystone-all @@ -1,7 +1,6 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -import greenlet import logging import os import signal @@ -21,8 +20,8 @@ if os.path.exists(os.path.join(possible_topdir, from paste import deploy import pbr.version +from keystone.common import environment from keystone.common import utils -from keystone.common import wsgi_server from keystone import config from keystone.openstack.common import gettextutils from keystone.openstack.common import importutils @@ -33,7 +32,7 @@ CONF = config.CONF def create_server(conf, name, host, port): app = deploy.loadapp('config:%s' % conf, name=name) - server = wsgi_server.Server(app, host=host, port=port) + server = environment.Server(app, host=host, port=port) if CONF.ssl.enable: server.set_ssl(CONF.ssl.certfile, CONF.ssl.keyfile, CONF.ssl.ca_certs, CONF.ssl.cert_required) @@ -64,10 +63,7 @@ def serve(*servers): logging.exception('Failed to execute onready command') for server in servers: - try: - server.wait() - except greenlet.GreenletExit: - pass + server.wait() if __name__ == '__main__': @@ -100,7 +96,7 @@ if __name__ == '__main__': # http://lists.openstack.org/pipermail/openstack-dev/2012-August/ # 000794.html monkeypatch_thread = False - wsgi_server.monkey_patch_eventlet(monkeypatch_thread=monkeypatch_thread) + environment.use_eventlet(monkeypatch_thread) servers = [] servers.append(create_server(paste_config, diff --git a/bin/keystone-manage b/bin/keystone-manage index 89ada5bd..3eedea3b 100755 --- a/bin/keystone-manage +++ b/bin/keystone-manage @@ -14,11 +14,13 @@ if os.path.exists(os.path.join(possible_topdir, sys.path.insert(0, possible_topdir) from keystone import cli +from keystone.common import environment from keystone.openstack.common import gettextutils if __name__ == '__main__': gettextutils.install('keystone') + environment.use_stdlib() dev_conf = os.path.join(possible_topdir, 'etc', diff --git a/httpd/keystone.py b/httpd/keystone.py index 8b1ab740..65298409 100644 --- a/httpd/keystone.py +++ b/httpd/keystone.py @@ -2,6 +2,7 @@ import os from paste import deploy +from keystone.common import environment from keystone.common import logging from keystone import config @@ -9,6 +10,7 @@ LOG = logging.getLogger(__name__) CONF = config.CONF CONF(project='keystone') +environment.use_stdlib() name = os.path.basename(__file__) if CONF.debug: diff --git a/keystone/auth/token_factory.py b/keystone/auth/token_factory.py index 43a23ce6..64f945fa 100644 --- a/keystone/auth/token_factory.py +++ b/keystone/auth/token_factory.py @@ -17,12 +17,12 @@ """Token Factory""" import json -import subprocess import uuid import webob from keystone import catalog from keystone.common import cms +from keystone.common import environment from keystone.common import logging from keystone.common import utils from keystone import config @@ -310,7 +310,7 @@ def create_token(context, auth_context, auth_info): token_id = cms.cms_sign_token(json.dumps(token_data), CONF.signing.certfile, CONF.signing.keyfile) - except subprocess.CalledProcessError: + except environment.subprocess.CalledProcessError: raise exception.UnexpectedError(_( 'Unable to sign token.')) else: diff --git a/keystone/common/cms.py b/keystone/common/cms.py index 307542b4..6ec740f8 100644 --- a/keystone/common/cms.py +++ b/keystone/common/cms.py @@ -1,46 +1,31 @@ import hashlib +from keystone.common import environment 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 # nopep8 - - def cms_verify(formatted, signing_cert_file_name, ca_file_name): """Verifies the signature of the contents IAW CMS syntax.""" - _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) + process = environment.subprocess.Popen(["openssl", "cms", "-verify", + "-certfile", + signing_cert_file_name, + "-CAfile", ca_file_name, + "-inform", "PEM", + "-nosmimecap", "-nodetach", + "-nocerts", "-noattr"], + stdin=environment.subprocess.PIPE, + stdout=environment.subprocess.PIPE, + stderr=environment.subprocess.PIPE) output, err = process.communicate(formatted) retcode = process.poll() if retcode: LOG.error(_('Verify error: %s') % err) - raise subprocess.CalledProcessError(retcode, "openssl", output=err) + raise environment.subprocess.CalledProcessError(retcode, + "openssl", output=err) return output @@ -117,16 +102,15 @@ 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 """ - _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) + process = environment.subprocess.Popen(["openssl", "cms", "-sign", + "-signer", signing_cert_file_name, + "-inkey", signing_key_file_name, + "-outform", "PEM", + "-nosmimecap", "-nodetach", + "-nocerts", "-noattr"], + stdin=environment.subprocess.PIPE, + stdout=environment.subprocess.PIPE, + stderr=environment.subprocess.PIPE) output, err = process.communicate(text) retcode = process.poll() if retcode or "Error" in err: @@ -136,7 +120,7 @@ def cms_sign_text(text, signing_cert_file_name, signing_key_file_name): "'keystone-manage pki_setup'")) else: LOG.error(_('Signing error: %s') % err) - raise subprocess.CalledProcessError(retcode, "openssl") + raise environment.subprocess.CalledProcessError(retcode, "openssl") return output diff --git a/keystone/common/environment/__init__.py b/keystone/common/environment/__init__.py new file mode 100644 index 00000000..ac93e24f --- /dev/null +++ b/keystone/common/environment/__init__.py @@ -0,0 +1,78 @@ +import functools +import os + +from keystone.common import config +from keystone.common import logging + +CONF = config.CONF +LOG = logging.getLogger(__name__) + + +__all__ = ['Server', 'httplib', 'subprocess'] + +_configured = False + +Server = None +httplib = None +subprocess = None + + +def configure_once(name): + """Ensure that environment configuration is only run once. + + If environment is reconfigured in the same way then it is ignored. + It is an error to attempt to reconfigure environment in a different way. + """ + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + global _configured + if _configured: + if _configured == name: + return + else: + raise SystemError("Environment has already been " + "configured as %s" % _configured) + + LOG.info(_("Environment configured as: %s"), name) + _configured = name + return func(*args, **kwargs) + + return wrapper + return decorator + + +@configure_once('eventlet') +def use_eventlet(monkeypatch_thread=None): + global httplib, subprocess, Server + + # This must be set before the initial import of eventlet because if + # dnspython is present in your environment then eventlet monkeypatches + # socket.getaddrinfo() with an implementation which doesn't work for IPv6. + os.environ['EVENTLET_NO_GREENDNS'] = 'yes' + + import eventlet + from eventlet.green import httplib as _httplib + from eventlet.green import subprocess as _subprocess + from keystone.common.environment import eventlet_server + + if monkeypatch_thread is None: + monkeypatch_thread = not os.getenv('STANDARD_THREADS') + + eventlet.patcher.monkey_patch(all=False, socket=True, time=True, + thread=monkeypatch_thread) + + Server = eventlet_server.Server + httplib = _httplib + subprocess = _subprocess + + +@configure_once('stdlib') +def use_stdlib(): + global httplib, subprocess + + import httplib as _httplib + import subprocess as _subprocess + + httplib = _httplib + subprocess = _subprocess diff --git a/keystone/common/environment/eventlet_server.py b/keystone/common/environment/eventlet_server.py new file mode 100644 index 00000000..18987d26 --- /dev/null +++ b/keystone/common/environment/eventlet_server.py @@ -0,0 +1,114 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 OpenStack LLC +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# Licensed 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. + +import socket +import ssl +import sys + +import eventlet +import eventlet.wsgi +import greenlet + +from keystone.common import logging +from keystone.common import wsgi + + +LOG = logging.getLogger(__name__) + + +class Server(object): + """Server class to manage multiple WSGI sockets and applications.""" + + def __init__(self, application, host=None, port=None, threads=1000): + self.application = application + self.host = host or '0.0.0.0' + self.port = port or 0 + self.pool = eventlet.GreenPool(threads) + self.socket_info = {} + self.greenthread = None + self.do_ssl = False + self.cert_required = False + + def start(self, key=None, backlog=128): + """Run a WSGI server with the given application.""" + LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') % + {'arg0': sys.argv[0], + 'host': self.host, + 'port': self.port}) + + # TODO(dims): eventlet's green dns/socket module does not actually + # support IPv6 in getaddrinfo(). We need to get around this in the + # future or monitor upstream for a fix + info = socket.getaddrinfo(self.host, + self.port, + socket.AF_UNSPEC, + socket.SOCK_STREAM)[0] + _socket = eventlet.listen(info[-1], + family=info[0], + backlog=backlog) + if key: + self.socket_info[key] = _socket.getsockname() + # SSL is enabled + if self.do_ssl: + if self.cert_required: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + sslsocket = eventlet.wrap_ssl(_socket, certfile=self.certfile, + keyfile=self.keyfile, + server_side=True, + cert_reqs=cert_reqs, + ca_certs=self.ca_certs) + _socket = sslsocket + + self.greenthread = self.pool.spawn(self._run, + self.application, + _socket) + + def set_ssl(self, certfile, keyfile=None, ca_certs=None, + cert_required=True): + self.certfile = certfile + self.keyfile = keyfile + self.ca_certs = ca_certs + self.cert_required = cert_required + self.do_ssl = True + + def kill(self): + if self.greenthread: + self.greenthread.kill() + + def wait(self): + """Wait until all servers have completed running.""" + try: + self.pool.waitall() + except KeyboardInterrupt: + pass + except greenlet.GreenletExit: + pass + + def _run(self, application, socket): + """Start a WSGI server in a new green thread.""" + log = logging.getLogger('eventlet.wsgi.server') + try: + eventlet.wsgi.server(socket, application, custom_pool=self.pool, + log=wsgi.WritableLogger(log)) + except Exception: + LOG.exception(_('Server error')) + raise diff --git a/keystone/common/openssl.py b/keystone/common/openssl.py index 47ac5aa6..427202ae 100644 --- a/keystone/common/openssl.py +++ b/keystone/common/openssl.py @@ -16,8 +16,8 @@ import os import stat -import subprocess +from keystone.common import environment from keystone.common import logging from keystone import config @@ -77,7 +77,7 @@ class BaseCertificateConfigure(object): def exec_command(self, command): to_exec = command % self.ssl_dictionary LOG.info(to_exec) - subprocess.check_call(to_exec.rsplit(' ')) + environment.subprocess.check_call(to_exec.rsplit(' ')) def build_ssl_config_file(self): if not file_exists(self.ssl_config_file_name): diff --git a/keystone/common/utils.py b/keystone/common/utils.py index fc62de97..fd2d7567 100644 --- a/keystone/common/utils.py +++ b/keystone/common/utils.py @@ -21,12 +21,12 @@ import hashlib import json import os -import subprocess import time import passlib.hash from keystone.common import config +from keystone.common import environment from keystone.common import logging from keystone import exception @@ -160,14 +160,15 @@ def check_output(*popenargs, **kwargs): if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') LOG.debug(' '.join(popenargs[0])) - process = subprocess.Popen(stdout=subprocess.PIPE, *popenargs, **kwargs) + process = environment.subprocess.Popen(stdout=environment.subprocess.PIPE, + *popenargs, **kwargs) output, unused_err = process.communicate() retcode = process.poll() if retcode: cmd = kwargs.get('args') if cmd is None: cmd = popenargs[0] - raise subprocess.CalledProcessError(retcode, cmd) + raise environment.subprocess.CalledProcessError(retcode, cmd) return output diff --git a/keystone/common/wsgi_server.py b/keystone/common/wsgi_server.py deleted file mode 100644 index d8d2512f..00000000 --- a/keystone/common/wsgi_server.py +++ /dev/null @@ -1,133 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 OpenStack LLC -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2010 OpenStack LLC. -# All Rights Reserved. -# -# Licensed 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. - -import os -import socket -import ssl -import sys - -# NOTE(mikal): All of this is because if dnspython is present in your -# environment then eventlet monkeypatches socket.getaddrinfo() with an -# implementation which doesn't work for IPv6. What we're checking here is -# that the magic environment variable was set when the import happened. -if ('eventlet' in sys.modules and - os.environ.get('EVENTLET_NO_GREENDNS', '').lower() != 'yes'): - raise ImportError('eventlet imported before ' - 'keystone.common.wsgi_server ' - '(EVENTLET_NO_GREENDNS env var set to %s)' - % os.environ.get('EVENTLET_NO_GREENDNS')) - -os.environ['EVENTLET_NO_GREENDNS'] = 'yes' - -import eventlet -import eventlet.wsgi - -from keystone.common import logging -from keystone.common import wsgi - - -LOG = logging.getLogger(__name__) - - -def monkey_patch_eventlet(monkeypatch_thread=None): - if monkeypatch_thread is None: - monkeypatch_thread = not os.getenv('STANDARD_THREADS') - - eventlet.patcher.monkey_patch(all=False, socket=True, time=True, - thread=monkeypatch_thread) - - -class Server(object): - """Server class to manage multiple WSGI sockets and applications.""" - - def __init__(self, application, host=None, port=None, threads=1000): - self.application = application - self.host = host or '0.0.0.0' - self.port = port or 0 - self.pool = eventlet.GreenPool(threads) - self.socket_info = {} - self.greenthread = None - self.do_ssl = False - self.cert_required = False - - def start(self, key=None, backlog=128): - """Run a WSGI server with the given application.""" - LOG.debug(_('Starting %(arg0)s on %(host)s:%(port)s') % - {'arg0': sys.argv[0], - 'host': self.host, - 'port': self.port}) - - # TODO(dims): eventlet's green dns/socket module does not actually - # support IPv6 in getaddrinfo(). We need to get around this in the - # future or monitor upstream for a fix - info = socket.getaddrinfo(self.host, - self.port, - socket.AF_UNSPEC, - socket.SOCK_STREAM)[0] - _socket = eventlet.listen(info[-1], - family=info[0], - backlog=backlog) - if key: - self.socket_info[key] = _socket.getsockname() - # SSL is enabled - if self.do_ssl: - if self.cert_required: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - sslsocket = eventlet.wrap_ssl(_socket, certfile=self.certfile, - keyfile=self.keyfile, - server_side=True, - cert_reqs=cert_reqs, - ca_certs=self.ca_certs) - _socket = sslsocket - - self.greenthread = self.pool.spawn(self._run, - self.application, - _socket) - - def set_ssl(self, certfile, keyfile=None, ca_certs=None, - cert_required=True): - self.certfile = certfile - self.keyfile = keyfile - self.ca_certs = ca_certs - self.cert_required = cert_required - self.do_ssl = True - - def kill(self): - if self.greenthread: - self.greenthread.kill() - - def wait(self): - """Wait until all servers have completed running.""" - try: - self.pool.waitall() - except KeyboardInterrupt: - pass - - def _run(self, application, socket): - """Start a WSGI server in a new green thread.""" - log = logging.getLogger('eventlet.wsgi.server') - try: - eventlet.wsgi.server(socket, application, custom_pool=self.pool, - log=wsgi.WritableLogger(log)) - except Exception: - LOG.exception(_('Server error')) - raise diff --git a/keystone/middleware/ec2_token.py b/keystone/middleware/ec2_token.py index 7cd007c7..265ccaa6 100644 --- a/keystone/middleware/ec2_token.py +++ b/keystone/middleware/ec2_token.py @@ -24,7 +24,6 @@ Starting point for routing EC2 requests. import urlparse -from eventlet.green import httplib import webob.dec import webob.exc @@ -32,6 +31,7 @@ from nova import flags from nova import utils from nova import wsgi +from keystone.common import environment FLAGS = flags.FLAGS flags.DEFINE_string('keystone_ec2_url', @@ -75,9 +75,9 @@ class EC2Token(wsgi.Middleware): # pylint: disable-msg=E1101 o = urlparse.urlparse(FLAGS.keystone_ec2_url) if o.scheme == 'http': - conn = httplib.HTTPConnection(o.netloc) + conn = environment.httplib.HTTPConnection(o.netloc) else: - conn = httplib.HTTPSConnection(o.netloc) + conn = environment.httplib.HTTPSConnection(o.netloc) conn.request('POST', o.path, body=creds_json, headers=headers) response = conn.getresponse().read() conn.close() diff --git a/keystone/middleware/s3_token.py b/keystone/middleware/s3_token.py index 74be5864..a5eff289 100644 --- a/keystone/middleware/s3_token.py +++ b/keystone/middleware/s3_token.py @@ -33,13 +33,13 @@ This WSGI component: """ -import httplib - import webob -from keystone.openstack.common import jsonutils from swift.common import utils as swift_utils +from keystone.common import environment +from keystone.openstack.common import jsonutils + PROTOCOL_NAME = 'S3 Token Authentication' @@ -62,9 +62,9 @@ class S3Token(object): self.auth_port = int(conf.get('auth_port', 35357)) self.auth_protocol = conf.get('auth_protocol', 'https') if self.auth_protocol == 'http': - self.http_client_class = httplib.HTTPConnection + self.http_client_class = environment.httplib.HTTPConnection else: - self.http_client_class = httplib.HTTPSConnection + self.http_client_class = environment.httplib.HTTPSConnection # SSL self.cert_file = conf.get('certfile') self.key_file = conf.get('keyfile') diff --git a/keystone/test.py b/keystone/test.py index 3fc0b301..d0570ca7 100644 --- a/keystone/test.py +++ b/keystone/test.py @@ -19,7 +19,6 @@ import errno import os import socket import StringIO -import subprocess import sys import time @@ -31,12 +30,16 @@ from paste import deploy import stubout import unittest2 as unittest +gettext.install('keystone', unicode=1) + +from keystone.common import environment +environment.use_eventlet() + from keystone import catalog from keystone.common import kvs from keystone.common import logging from keystone.common import utils from keystone.common import wsgi -from keystone.common import wsgi_server from keystone import config from keystone import credential from keystone import exception @@ -47,11 +50,6 @@ from keystone import token from keystone import trust -wsgi_server.monkey_patch_eventlet() - - -gettext.install('keystone', unicode=1) - LOG = logging.getLogger(__name__) ROOTDIR = os.path.dirname(os.path.abspath(os.curdir)) VENDOR = os.path.join(ROOTDIR, 'vendor') @@ -115,7 +113,7 @@ def checkout_vendor(repo, rev): # write out a modified time with open(modcheck, 'w') as fd: fd.write('1') - except subprocess.CalledProcessError: + except environment.subprocess.CalledProcessError: LOG.warning(_('Failed to checkout %s'), repo) cd(working_dir) return revdir @@ -320,7 +318,7 @@ class TestCase(NoModule, unittest.TestCase): def serveapp(self, config, name=None, cert=None, key=None, ca=None, cert_required=None, host="127.0.0.1", port=0): app = self.loadapp(config, name=name) - server = wsgi_server.Server(app, host, port) + server = environment.Server(app, host, port) if cert is not None and ca is not None and key is not None: server.set_ssl(certfile=cert, keyfile=key, ca_certs=ca, cert_required=cert_required) diff --git a/keystone/token/controllers.py b/keystone/token/controllers.py index 2d429742..68a3ebcd 100644 --- a/keystone/token/controllers.py +++ b/keystone/token/controllers.py @@ -1,10 +1,10 @@ import json -import subprocess import uuid from keystone.common import cms from keystone.common import controller from keystone.common import dependency +from keystone.common import environment from keystone.common import logging from keystone.common import utils from keystone import config @@ -117,7 +117,7 @@ class Auth(controller.V2Controller): token_id = cms.cms_sign_token(json.dumps(token_data), CONF.signing.certfile, CONF.signing.keyfile) - except subprocess.CalledProcessError: + except environment.subprocess.CalledProcessError: raise exception.UnexpectedError(_( 'Unable to sign token.')) else: diff --git a/tests/test_auth.py b/tests/test_auth.py index e7c9704a..465a0896 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -16,11 +16,12 @@ import copy import datetime import uuid +from keystone import test + from keystone import auth from keystone import config from keystone import exception from keystone.openstack.common import timeutils -from keystone import test from keystone import token from keystone import trust diff --git a/tests/test_auth_plugin.py b/tests/test_auth_plugin.py index 47080b53..22357471 100644 --- a/tests/test_auth_plugin.py +++ b/tests/test_auth_plugin.py @@ -16,9 +16,10 @@ import uuid +from keystone import test + from keystone import auth from keystone import exception -from keystone import test # for testing purposes only diff --git a/tests/test_backend.py b/tests/test_backend.py index bd9d53ca..7cb1e1ac 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -18,11 +18,12 @@ import datetime import default_fixtures import uuid +from keystone import test + from keystone.catalog import core from keystone import config from keystone import exception from keystone.openstack.common import timeutils -from keystone import test CONF = config.CONF diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py index 3a4e2da8..dce1f756 100644 --- a/tests/test_backend_kvs.py +++ b/tests/test_backend_kvs.py @@ -17,11 +17,12 @@ import uuid import nose.exc +from keystone import test + from keystone import catalog from keystone.catalog.backends import kvs as catalog_kvs from keystone import exception from keystone import identity -from keystone import test from keystone.token.backends import kvs as token_kvs from keystone.trust.backends import kvs as trust_kvs diff --git a/tests/test_backend_ldap.py b/tests/test_backend_ldap.py index ee02c7a4..16530f10 100644 --- a/tests/test_backend_ldap.py +++ b/tests/test_backend_ldap.py @@ -19,11 +19,12 @@ import uuid import nose.exc +from keystone import test + from keystone.common.ldap import fakeldap from keystone import config from keystone import exception from keystone import identity -from keystone import test import default_fixtures import test_backend diff --git a/tests/test_backend_memcache.py b/tests/test_backend_memcache.py index 5391d7f9..e31f1576 100644 --- a/tests/test_backend_memcache.py +++ b/tests/test_backend_memcache.py @@ -20,11 +20,12 @@ import uuid import memcache +from keystone import test + from keystone.common import utils from keystone import exception from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils -from keystone import test from keystone import token from keystone.token.backends import memcache as token_memcache diff --git a/tests/test_backend_pam.py b/tests/test_backend_pam.py index a8f4e575..3a66f014 100644 --- a/tests/test_backend_pam.py +++ b/tests/test_backend_pam.py @@ -16,9 +16,10 @@ import uuid +from keystone import test + from keystone import config from keystone.identity.backends import pam as identity_pam -from keystone import test CONF = config.CONF diff --git a/tests/test_backend_sql.py b/tests/test_backend_sql.py index e4a19ef9..3136bacb 100644 --- a/tests/test_backend_sql.py +++ b/tests/test_backend_sql.py @@ -16,13 +16,14 @@ import uuid +from keystone import test + from keystone import catalog from keystone.common import sql from keystone import config from keystone import exception from keystone import identity from keystone import policy -from keystone import test from keystone import token from keystone import trust diff --git a/tests/test_backend_templated.py b/tests/test_backend_templated.py index 31d77acd..72dd21a7 100644 --- a/tests/test_backend_templated.py +++ b/tests/test_backend_templated.py @@ -16,10 +16,11 @@ import os +from keystone import test + from keystone import catalog from keystone.catalog.backends import templated as catalog_templated from keystone import exception -from keystone import test import default_fixtures import test_backend diff --git a/tests/test_cert_setup.py b/tests/test_cert_setup.py index fb7326b3..74e5466a 100644 --- a/tests/test_cert_setup.py +++ b/tests/test_cert_setup.py @@ -18,9 +18,10 @@ import os import shutil +from keystone import test + from keystone.common import openssl from keystone import exception -from keystone import test from keystone import token import default_fixtures diff --git a/tests/test_config.py b/tests/test_config.py index ae134b68..3165a4f4 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,6 +1,7 @@ +from keystone import test + from keystone import config from keystone import exception -from keystone import test CONF = config.CONF diff --git a/tests/test_content_types.py b/tests/test_content_types.py index fd99eae8..820dc0dd 100644 --- a/tests/test_content_types.py +++ b/tests/test_content_types.py @@ -21,9 +21,10 @@ from lxml import etree import nose.exc import webtest +from keystone import test + from keystone.common import serializer from keystone.openstack.common import jsonutils -from keystone import test import default_fixtures diff --git a/tests/test_contrib_s3_core.py b/tests/test_contrib_s3_core.py index c76bc898..e2c328b5 100644 --- a/tests/test_contrib_s3_core.py +++ b/tests/test_contrib_s3_core.py @@ -16,11 +16,12 @@ import uuid +from keystone import test + from keystone.contrib import ec2 from keystone.contrib import s3 from keystone import exception -from keystone import test class S3ContribCore(test.TestCase): diff --git a/tests/test_exception.py b/tests/test_exception.py index e479f61c..ef06f633 100644 --- a/tests/test_exception.py +++ b/tests/test_exception.py @@ -16,11 +16,12 @@ import uuid +from keystone import test + from keystone.common import wsgi from keystone import config from keystone import exception from keystone.openstack.common import jsonutils -from keystone import test CONF = config.CONF diff --git a/tests/test_import_legacy.py b/tests/test_import_legacy.py index 50bf22f9..bc7f347a 100644 --- a/tests/test_import_legacy.py +++ b/tests/test_import_legacy.py @@ -21,13 +21,14 @@ try: except ImportError: from pysqlite2 import dbapi2 as dbapi +from keystone import test + from keystone.catalog.backends import templated as catalog_templated from keystone.common.sql import legacy from keystone.common.sql import util as sql_util from keystone import config from keystone import identity from keystone.identity.backends import sql as identity_sql -from keystone import test CONF = config.CONF diff --git a/tests/test_ipv6.py b/tests/test_ipv6.py index 0973648f..9825a5fa 100644 --- a/tests/test_ipv6.py +++ b/tests/test_ipv6.py @@ -15,10 +15,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import httplib +from keystone import test +from keystone.common import environment from keystone import config -from keystone import test CONF = config.CONF @@ -40,12 +40,12 @@ class IPv6TestCase(test.TestCase): self.admin_server = self.serveapp('keystone', name='admin', host="::1", port=0) # Verify Admin - conn = httplib.HTTPConnection('::1', CONF.admin_port) + conn = environment.httplib.HTTPConnection('::1', CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public - conn = httplib.HTTPConnection('::1', CONF.public_port) + conn = environment.httplib.HTTPConnection('::1', CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) diff --git a/tests/test_keystoneclient.py b/tests/test_keystoneclient.py index bd538700..b9828559 100644 --- a/tests/test_keystoneclient.py +++ b/tests/test_keystoneclient.py @@ -19,10 +19,11 @@ import webob import nose.exc +from keystone import test + from keystone import config from keystone.openstack.common import jsonutils from keystone.openstack.common import timeutils -from keystone import test import default_fixtures diff --git a/tests/test_keystoneclient_sql.py b/tests/test_keystoneclient_sql.py index 30f59022..5706bef5 100644 --- a/tests/test_keystoneclient_sql.py +++ b/tests/test_keystoneclient_sql.py @@ -18,9 +18,10 @@ import uuid import nose.exc +from keystone import test + from keystone.common import sql from keystone import config -from keystone import test import test_keystoneclient diff --git a/tests/test_middleware.py b/tests/test_middleware.py index eafdcb92..38ba09e9 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -16,10 +16,11 @@ import webob +from keystone import test + from keystone import config from keystone import middleware from keystone.openstack.common import jsonutils -from keystone import test CONF = config.CONF diff --git a/tests/test_migrate_nova_auth.py b/tests/test_migrate_nova_auth.py index a4ad0fb4..97709b89 100644 --- a/tests/test_migrate_nova_auth.py +++ b/tests/test_migrate_nova_auth.py @@ -16,13 +16,14 @@ import uuid +from keystone import test + from keystone.common.sql import nova from keystone.common.sql import util as sql_util from keystone import config from keystone.contrib.ec2.backends import sql as ec2_sql from keystone import identity from keystone.identity.backends import sql as identity_sql -from keystone import test CONF = config.CONF diff --git a/tests/test_policy.py b/tests/test_policy.py index 465fd69a..010a5abf 100644 --- a/tests/test_policy.py +++ b/tests/test_policy.py @@ -19,11 +19,12 @@ import StringIO import tempfile import urllib2 +from keystone import test + from keystone import config from keystone import exception from keystone.openstack.common import policy as common_policy from keystone.policy.backends import rules -from keystone import test CONF = config.CONF diff --git a/tests/test_sizelimit.py b/tests/test_sizelimit.py index aec57ecf..abd2b639 100644 --- a/tests/test_sizelimit.py +++ b/tests/test_sizelimit.py @@ -14,10 +14,11 @@ import webob +from keystone import test + from keystone import config from keystone import exception from keystone import middleware -from keystone import test CONF = config.CONF MAX_REQUEST_BODY_SIZE = CONF.max_request_body_size diff --git a/tests/test_sql_upgrade.py b/tests/test_sql_upgrade.py index 59a8800c..ac4e5637 100644 --- a/tests/test_sql_upgrade.py +++ b/tests/test_sql_upgrade.py @@ -32,10 +32,11 @@ import uuid from migrate.versioning import api as versioning_api import sqlalchemy +from keystone import test + from keystone.common import sql from keystone.common.sql import migration from keystone import config -from keystone import test import default_fixtures diff --git a/tests/test_ssl.py b/tests/test_ssl.py index da9e4c06..8de5cc19 100644 --- a/tests/test_ssl.py +++ b/tests/test_ssl.py @@ -15,13 +15,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -import httplib import os import ssl -from keystone import config from keystone import test +from keystone.common import environment +from keystone import config CONF = config.CONF @@ -45,12 +45,14 @@ class SSLTestCase(test.TestCase): self.admin_server = self.serveapp('keystone', name='admin', cert=CERT, key=KEY, ca=CA) # Verify Admin - conn = httplib.HTTPSConnection('127.0.0.1', CONF.admin_port) + conn = environment.httplib.HTTPSConnection('127.0.0.1', + CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public - conn = httplib.HTTPSConnection('127.0.0.1', CONF.public_port) + conn = environment.httplib.HTTPSConnection('127.0.0.1', + CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) @@ -67,13 +69,13 @@ class SSLTestCase(test.TestCase): 'keystone', name='admin', cert=CERT, key=KEY, ca=CA, cert_required=True) # Verify Admin - conn = httplib.HTTPSConnection( + conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.admin_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public - conn = httplib.HTTPSConnection( + conn = environment.httplib.HTTPSConnection( '127.0.0.1', CONF.public_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() @@ -89,12 +91,12 @@ class SSLTestCase(test.TestCase): cert=CERT, key=KEY, ca=CA, host="::1", port=0) # Verify Admin - conn = httplib.HTTPSConnection('::1', CONF.admin_port) + conn = environment.httplib.HTTPSConnection('::1', CONF.admin_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public - conn = httplib.HTTPSConnection('::1', CONF.public_port) + conn = environment.httplib.HTTPSConnection('::1', CONF.public_port) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) @@ -114,13 +116,13 @@ class SSLTestCase(test.TestCase): key=KEY, ca=CA, cert_required=True, host="::1", port=0) # Verify Admin - conn = httplib.HTTPSConnection( + conn = environment.httplib.HTTPSConnection( '::1', CONF.admin_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() self.assertEqual(resp.status, 300) # Verify Public - conn = httplib.HTTPSConnection( + conn = environment.httplib.HTTPSConnection( '::1', CONF.public_port, CLIENT, CLIENT) conn.request('GET', '/') resp = conn.getresponse() @@ -135,14 +137,16 @@ class SSLTestCase(test.TestCase): 'keystone', name='admin', cert=CERT, key=KEY, ca=CA, cert_required=True) # Verify Admin - conn = httplib.HTTPSConnection('127.0.0.1', CONF.admin_port) + conn = environment.httplib.HTTPSConnection('127.0.0.1', + CONF.admin_port) try: conn.request('GET', '/') self.fail('Admin API shoulda failed with SSL handshake!') except ssl.SSLError: pass # Verify Public - conn = httplib.HTTPSConnection('127.0.0.1', CONF.public_port) + conn = environment.httplib.HTTPSConnection('127.0.0.1', + CONF.public_port) try: conn.request('GET', '/') self.fail('Public API shoulda failed with SSL handshake!') diff --git a/tests/test_url_middleware.py b/tests/test_url_middleware.py index d5c2eef1..2a36e8c2 100644 --- a/tests/test_url_middleware.py +++ b/tests/test_url_middleware.py @@ -16,9 +16,10 @@ import webob -from keystone import middleware from keystone import test +from keystone import middleware + class FakeApp(object): """Fakes a WSGI app URL normalized.""" diff --git a/tests/test_utils.py b/tests/test_utils.py index 15ef51a5..4a65bea1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -29,9 +29,10 @@ # License for the specific language governing permissions and limitations # under the License. -from keystone.common import utils from keystone import test +from keystone.common import utils + class UtilsTestCase(test.TestCase): def test_hash(self): diff --git a/tests/test_v3.py b/tests/test_v3.py index 8373ae98..93293b6c 100644 --- a/tests/test_v3.py +++ b/tests/test_v3.py @@ -4,13 +4,14 @@ import uuid from lxml import etree import webtest +from keystone import test + from keystone import auth from keystone.common import serializer from keystone.common.sql import util as sql_util from keystone import config from keystone.openstack.common import timeutils from keystone.policy.backends import rules -from keystone import test import test_content_types diff --git a/tests/test_versions.py b/tests/test_versions.py index 2a53952f..c0d712f0 100644 --- a/tests/test_versions.py +++ b/tests/test_versions.py @@ -15,10 +15,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +from keystone import test + from keystone import config from keystone import controllers from keystone.openstack.common import jsonutils -from keystone import test CONF = config.CONF diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py index 0cd6a733..8e266749 100644 --- a/tests/test_wsgi.py +++ b/tests/test_wsgi.py @@ -16,10 +16,11 @@ import webob +from keystone import test + from keystone.common import wsgi from keystone import exception from keystone.openstack.common import jsonutils -from keystone import test class FakeApp(wsgi.Application): -- cgit