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
This commit is contained in:
Chris Dent 2017-07-25 02:22:56 +00:00
parent 3c1d175556
commit 1151a0514b

@ -35,6 +35,7 @@ from wsgi_intercept import interceptor
from nova.api.openstack.compute import tenant_networks from nova.api.openstack.compute import tenant_networks
from nova.api.openstack.placement import deploy as placement_deploy 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.compute import rpcapi as compute_rpcapi
from nova import context from nova import context
from nova.db import migration from nova.db import migration
@ -49,6 +50,7 @@ from nova import rpc
from nova import service from nova import service
from nova.tests.functional.api import client from nova.tests.functional.api import client
from nova.tests import uuidsentinel from nova.tests import uuidsentinel
from nova import wsgi
_TRUE_VALUES = ('True', 'true', '1', 'yes') _TRUE_VALUES = ('True', 'true', '1', 'yes')
@ -792,26 +794,44 @@ class OSAPIFixture(fixtures.Fixture):
def setUp(self): def setUp(self):
super(OSAPIFixture, self).setUp() super(OSAPIFixture, self).setUp()
# in order to run these in tests we need to bind only to local # A unique hostname for the wsgi-intercept.
# host, and dynamically allocate ports hostname = uuidsentinel.osapi_host
port = 80
service_name = 'osapi_compute'
endpoint = 'http://%s:%s/' % (hostname, port)
conf_overrides = { conf_overrides = {
'osapi_compute_listen': '127.0.0.1', 'osapi_compute_listen': hostname,
'osapi_compute_listen_port': 0, 'osapi_compute_listen_port': port,
'debug': True, 'debug': True,
} }
self.useFixture(ConfPatcher(**conf_overrides)) self.useFixture(ConfPatcher(**conf_overrides))
self.osapi = service.WSGIService("osapi_compute") # Turn off manipulation of socket_options in TCPKeepAliveAdapter
self.osapi.start() # to keep wsgi-intercept happy. Replace it with the method
self.addCleanup(self.osapi.stop) # 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' % ({ self.auth_url = 'http://%(host)s:%(port)s/%(api_version)s' % ({
'host': self.osapi.host, 'port': self.osapi.port, 'host': hostname, 'port': port, 'api_version': self.api_version})
'api_version': self.api_version})
self.api = client.TestOpenStackClient('fake', 'fake', self.auth_url, self.api = client.TestOpenStackClient('fake', 'fake', self.auth_url,
self.project_id) self.project_id)
self.admin_api = client.TestOpenStackClient( self.admin_api = client.TestOpenStackClient(
'admin', 'admin', self.auth_url, self.project_id) '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): class OSMetadataServer(fixtures.Fixture):