Extract part of PlacementFixture to placement

In nova.tests.fixtures is a PlacementFixture that peforms two roles. One
is to provide a working placement service via wsgi-intercept. The other
is to provide a working client of that service in the form of a
scheduler report client that uses appropriate headers and endpoints.

This change extracts the first role to a new fixture hosted within the
placement hierarchy and makes the second role a subclass of the first.

To make this work nicely, existing placement fixtures (in fixtures.py),
used solely for the gabbi tests are moved into a new directory called
"fixtures" and renamed to "gabbits.py". "gabbi.py" can't be used
because of naming conflicts while importing.

This is a small part of ongoing work related to
blueprint placement-extract

Change-Id: I126ada549d3879f89d1ec64b743da14807a39351
This commit is contained in:
Chris Dent 2018-05-14 20:52:11 +01:00
parent f902e0d5d8
commit b268454987
5 changed files with 81 additions and 15 deletions

View File

@ -37,7 +37,6 @@ from requests import adapters
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.api import wsgi
from nova.compute import rpcapi as compute_rpcapi
@ -53,6 +52,7 @@ from nova import quota as nova_quota
from nova import rpc
from nova import service
from nova.tests.functional.api import client
from nova.tests.functional.api.openstack.placement.fixtures import placement
from nova.tests import uuidsentinel
_TRUE_VALUES = ('True', 'true', '1', 'yes')
@ -1691,7 +1691,7 @@ class PlacementApiClient(object):
self.fixture._fake_put(None, url, body, **kwargs))
class PlacementFixture(fixtures.Fixture):
class PlacementFixture(placement.PlacementFixture):
"""A fixture to placement operations.
Runs a local WSGI server bound on a free port and having the Placement
@ -1703,21 +1703,9 @@ class PlacementFixture(fixtures.Fixture):
all calls would be passing this token.
"""
def __init__(self, token='admin'):
self.token = token
def setUp(self):
super(PlacementFixture, self).setUp()
self.useFixture(ConfPatcher(group='api', auth_strategy='noauth2'))
loader = placement_deploy.loadapp(CONF)
app = lambda: loader
host = uuidsentinel.placement_host
self.endpoint = 'http://%s/placement' % host
intercept = interceptor.RequestsInterceptor(app, url=self.endpoint)
intercept.install_intercept()
self.addCleanup(intercept.uninstall_intercept)
# Turn off manipulation of socket_options in TCPKeepAliveAdapter
# to keep wsgi-intercept happy. Replace it with the method
# from its superclass.

View File

@ -0,0 +1,76 @@
# 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 fixtures
from oslo_config import cfg
from oslo_utils import uuidutils
from wsgi_intercept import interceptor
from nova.api.openstack.placement import deploy
CONF = cfg.CONF
class ConfPatcher(fixtures.Fixture):
"""Fixture to patch and restore global CONF.
This also resets overrides for everything that is patched during
its teardown.
"""
# TODO(cdent): This is intentionally duplicated from nova's fixtures.
# This comment becomes redundant once placement is extracted.
def __init__(self, **kwargs):
"""Constructor
:params group: if specified all config options apply to that group.
:params **kwargs: the rest of the kwargs are processed as a
set of key/value pairs to be set as configuration override.
"""
super(ConfPatcher, self).__init__()
self.group = kwargs.pop('group', None)
self.args = kwargs
def setUp(self):
super(ConfPatcher, self).setUp()
for k, v in self.args.items():
self.addCleanup(CONF.clear_override, k, self.group)
CONF.set_override(k, v, self.group)
class PlacementFixture(fixtures.Fixture):
"""A fixture to placement operations.
Runs a local WSGI server bound on a free port and having the Placement
application with NoAuth middleware.
This fixture also prevents calling the ServiceCatalog for getting the
endpoint.
It's possible to ask for a specific token when running the fixtures so
all calls would be passing this token.
"""
def __init__(self, token='admin'):
self.token = token
def setUp(self):
super(PlacementFixture, self).setUp()
self.useFixture(ConfPatcher(group='api', auth_strategy='noauth2'))
loader = deploy.loadapp(CONF)
app = lambda: loader
self.endpoint = 'http://%s/placement' % uuidutils.generate_uuid()
intercept = interceptor.RequestsInterceptor(app, url=self.endpoint)
intercept.install_intercept()
self.addCleanup(intercept.uninstall_intercept)

View File

@ -17,7 +17,9 @@ import wsgi_intercept
from gabbi import driver
from nova.tests import fixtures as nova_fixtures
from nova.tests.functional.api.openstack.placement import fixtures
# TODO(cdent): This whitespace blight will go away post extraction.
from nova.tests.functional.api.openstack.placement.fixtures \
import gabbits as fixtures
# Check that wsgi application response headers are always
# native str.