From 1151a0514b8fb7b0cc5d0cd1312df2ee412043a4 Mon Sep 17 00:00:00 2001 From: Chris Dent <cdent@anticdent.org> Date: Tue, 25 Jul 2017 02:22:56 +0000 Subject: [PATCH] Use wsgi-intercept in OSAPIFixture To lessen the amount of eventlet socket handling present in the functional tests, run osapi_compute via wsgi-intercept rather than spawning an eventlet server to run it in a "thread". To get this to work three main changes are made to the fixture: * gain access to the wsgi app via Loader().load_app. This is used because it involves the least amount of manipulation of CONF. The init_application in nova/api/openstack/wsgi_app.py tries to re-read configuration. * manually register the osapi_compute service (previously built in as a result of using WSGIService) * Override the TCPKeepAliveAdapter keystone session adapter. It's use of socket_options does not work will with the way that six and wsgi-intercept mess with the HTTPConnection class. The change in integrated_helpers is required because the new fixture must provide access to the WSGI app in a different way. Change-Id: Ia91fd7d7605dfb1a6f4376b1680cd26ea410d0f3 Related-Bug: #1705753 --- nova/tests/fixtures.py | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/nova/tests/fixtures.py b/nova/tests/fixtures.py index 6609e5f83..a08481d50 100644 --- a/nova/tests/fixtures.py +++ b/nova/tests/fixtures.py @@ -35,6 +35,7 @@ from wsgi_intercept import interceptor from nova.api.openstack.compute import tenant_networks from nova.api.openstack.placement import deploy as placement_deploy +from nova.api.openstack import wsgi_app from nova.compute import rpcapi as compute_rpcapi from nova import context from nova.db import migration @@ -49,6 +50,7 @@ from nova import rpc from nova import service from nova.tests.functional.api import client from nova.tests import uuidsentinel +from nova import wsgi _TRUE_VALUES = ('True', 'true', '1', 'yes') @@ -792,26 +794,44 @@ class OSAPIFixture(fixtures.Fixture): def setUp(self): super(OSAPIFixture, self).setUp() - # in order to run these in tests we need to bind only to local - # host, and dynamically allocate ports + # A unique hostname for the wsgi-intercept. + hostname = uuidsentinel.osapi_host + port = 80 + service_name = 'osapi_compute' + endpoint = 'http://%s:%s/' % (hostname, port) conf_overrides = { - 'osapi_compute_listen': '127.0.0.1', - 'osapi_compute_listen_port': 0, + 'osapi_compute_listen': hostname, + 'osapi_compute_listen_port': port, 'debug': True, } self.useFixture(ConfPatcher(**conf_overrides)) - self.osapi = service.WSGIService("osapi_compute") - self.osapi.start() - self.addCleanup(self.osapi.stop) + # Turn off manipulation of socket_options in TCPKeepAliveAdapter + # to keep wsgi-intercept happy. Replace it with the method + # from its superclass. + self.useFixture(fixtures.MonkeyPatch( + 'keystoneauth1.session.TCPKeepAliveAdapter.init_poolmanager', + adapters.HTTPAdapter.init_poolmanager)) + + loader = wsgi.Loader().load_app(service_name) + app = lambda: loader + + # re-use service setup code from wsgi_app to register + # service, which is looked for in some tests + wsgi_app._setup_service(CONF.host, service_name) + intercept = interceptor.RequestsInterceptor(app, url=endpoint) + intercept.install_intercept() + self.addCleanup(intercept.uninstall_intercept) self.auth_url = 'http://%(host)s:%(port)s/%(api_version)s' % ({ - 'host': self.osapi.host, 'port': self.osapi.port, - 'api_version': self.api_version}) + 'host': hostname, 'port': port, 'api_version': self.api_version}) self.api = client.TestOpenStackClient('fake', 'fake', self.auth_url, self.project_id) self.admin_api = client.TestOpenStackClient( 'admin', 'admin', self.auth_url, self.project_id) + # Provide a way to access the wsgi application to tests using + # the fixture. + self.app = app class OSMetadataServer(fixtures.Fixture):