Add a PlacementFixture

Some of the functional tests are calling the scheduler for getting the destination.
Once we will accept having the scheduler be calling the Placement service in order
to know a list of valid resource providers, we will need to run a local fixture
for having those tests faking the Placement service.

Change-Id: I6883888bf5d1920ab57dbf3dcaa1a7b375591754
This commit is contained in:
Sylvain Bauza 2017-01-20 17:13:11 +01:00
parent 58719f52a5
commit 98936fb28f
2 changed files with 115 additions and 0 deletions

View File

@ -23,6 +23,7 @@ import os
import warnings
import fixtures
from keystoneauth1 import session as ks
import mock
from oslo_concurrency import lockutils
from oslo_config import cfg
@ -31,6 +32,7 @@ import oslo_messaging as messaging
from oslo_messaging import conffixture as messaging_conffixture
import six
from nova.api.openstack.placement import deploy as placement_deploy
from nova.compute import rpcapi as compute_rpcapi
from nova import context
from nova.db import migration
@ -43,6 +45,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')
@ -1143,3 +1146,96 @@ class CinderFixture(fixtures.Fixture):
lambda *args, **kwargs: None)
self.test.stub_out('nova.volume.cinder.API.unreserve_volume',
fake_unreserve_volume)
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'))
app = placement_deploy.loadapp(CONF)
# in order to run these in tests we need to bind only to local
# host, and dynamically allocate ports
self.service = wsgi.Server('placement', app, host='127.0.0.1')
self.service.start()
self.addCleanup(self.service.stop)
self._client = ks.Session(auth=None)
self.useFixture(fixtures.MonkeyPatch(
'nova.scheduler.client.report.SchedulerReportClient.get',
self._fake_get))
self.useFixture(fixtures.MonkeyPatch(
'nova.scheduler.client.report.SchedulerReportClient.post',
self._fake_post))
self.useFixture(fixtures.MonkeyPatch(
'nova.scheduler.client.report.SchedulerReportClient.put',
self._fake_put))
self.useFixture(fixtures.MonkeyPatch(
'nova.scheduler.client.report.SchedulerReportClient.delete',
self._fake_delete))
def _fake_get(self, *args):
(url,) = args[1:]
# TODO(sbauza): The current placement NoAuthMiddleware returns a 401
# in case a token is not provided. We should change that by creating
# a fake token so we could remove adding the header below.
return self._client.get(
url,
endpoint_override="http://127.0.0.1:%s" % self.service.port,
headers={'x-auth-token': self.token},
raise_exc=False)
def _fake_post(self, *args):
(url, data) = args[1:]
# NOTE(sdague): using json= instead of data= sets the
# media type to application/json for us. Placement API is
# more sensitive to this than other APIs in the OpenStack
# ecosystem.
# TODO(sbauza): The current placement NoAuthMiddleware returns a 401
# in case a token is not provided. We should change that by creating
# a fake token so we could remove adding the header below.
return self._client.post(
url, json=data,
endpoint_override="http://127.0.0.1:%s" % self.service.port,
headers={'x-auth-token': self.token},
raise_exc=False)
def _fake_put(self, *args):
(url, data) = args[1:]
# NOTE(sdague): using json= instead of data= sets the
# media type to application/json for us. Placement API is
# more sensitive to this than other APIs in the OpenStack
# ecosystem.
# TODO(sbauza): The current placement NoAuthMiddleware returns a 401
# in case a token is not provided. We should change that by creating
# a fake token so we could remove adding the header below.
return self._client.put(
url, json=data,
endpoint_override="http://127.0.0.1:%s" % self.service.port,
headers={'x-auth-token': self.token},
raise_exc=False)
def _fake_delete(self, *args):
(url,) = args[1:]
# TODO(sbauza): The current placement NoAuthMiddleware returns a 401
# in case a token is not provided. We should change that by creating
# a fake token so we could remove adding the header below.
return self._client.delete(
url,
endpoint_override="http://127.0.0.1:%s" % self.service.port,
headers={'x-auth-token': self.token},
raise_exc=False)

View File

@ -468,3 +468,22 @@ class TestSingleCellSimpleFixture(testtools.TestCase):
self.useFixture(fixtures.SingleCellSimple())
with context.target_cell(mock.sentinel.context, None) as c:
self.assertIs(mock.sentinel.context, c)
class TestPlacementFixture(testtools.TestCase):
def test_responds_to_version(self):
"""Ensure the Placement server responds to calls sensibly."""
placement_fixture = self.useFixture(fixtures.PlacementFixture())
# request the API root, which provides us the versions of the API
resp = placement_fixture._fake_get(None, '/')
self.assertEqual(200, resp.status_code)
# request a known bad url, and we should get a 404
resp = placement_fixture._fake_get(None, '/foo')
self.assertEqual(404, resp.status_code)
# unsets the token so we fake missing it
placement_fixture.token = None
resp = placement_fixture._fake_get(None, '/foo')
self.assertEqual(401, resp.status_code)