Merge "Make CellDatabases fixture work over RPC"
This commit is contained in:
@@ -330,6 +330,32 @@ class SingleCellSimple(fixtures.Fixture):
|
|||||||
yield context
|
yield context
|
||||||
|
|
||||||
|
|
||||||
|
class CheatingSerializer(rpc.RequestContextSerializer):
|
||||||
|
"""A messaging.RequestContextSerializer that helps with cells.
|
||||||
|
|
||||||
|
Our normal serializer does not pass in the context like db_connection
|
||||||
|
and mq_connection, for good reason. We don't really want/need to
|
||||||
|
force a remote RPC server to use our values for this. However,
|
||||||
|
during unit and functional tests, since we're all in the same
|
||||||
|
process, we want cell-targeted RPC calls to preserve these values.
|
||||||
|
Unless we had per-service config and database layer state for
|
||||||
|
the fake services we start, this is a reasonable cheat.
|
||||||
|
"""
|
||||||
|
def serialize_context(self, context):
|
||||||
|
"""Serialize context with the db_connection inside."""
|
||||||
|
values = super(CheatingSerializer, self).serialize_context(context)
|
||||||
|
values['db_connection'] = context.db_connection
|
||||||
|
values['mq_connection'] = context.mq_connection
|
||||||
|
return values
|
||||||
|
|
||||||
|
def deserialize_context(self, values):
|
||||||
|
"""Deserialize context and honor db_connection if present."""
|
||||||
|
ctxt = super(CheatingSerializer, self).deserialize_context(values)
|
||||||
|
ctxt.db_connection = values.pop('db_connection', None)
|
||||||
|
ctxt.mq_connection = values.pop('mq_connection', None)
|
||||||
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
class CellDatabases(fixtures.Fixture):
|
class CellDatabases(fixtures.Fixture):
|
||||||
"""Create per-cell databases for testing.
|
"""Create per-cell databases for testing.
|
||||||
|
|
||||||
@@ -389,11 +415,36 @@ class CellDatabases(fixtures.Fixture):
|
|||||||
return ctxt_mgr
|
return ctxt_mgr
|
||||||
|
|
||||||
def _wrap_get_context_manager(self, context):
|
def _wrap_get_context_manager(self, context):
|
||||||
|
try:
|
||||||
|
# If already targeted, we can proceed without a lock
|
||||||
|
if context.db_connection:
|
||||||
|
return context.db_connection
|
||||||
|
except AttributeError:
|
||||||
|
# Unit tests with None, FakeContext, etc
|
||||||
|
pass
|
||||||
|
|
||||||
# NOTE(melwitt): This is a hack to try to deal with
|
# NOTE(melwitt): This is a hack to try to deal with
|
||||||
# local accesses i.e. non target_cell accesses.
|
# local accesses i.e. non target_cell accesses.
|
||||||
with self._cell_lock.read_lock():
|
with self._cell_lock.read_lock():
|
||||||
return self._last_ctxt_mgr
|
return self._last_ctxt_mgr
|
||||||
|
|
||||||
|
def _wrap_get_server(self, target, endpoints, serializer=None):
|
||||||
|
"""Mirror rpc.get_server() but with our special sauce."""
|
||||||
|
serializer = CheatingSerializer(serializer)
|
||||||
|
return messaging.get_rpc_server(rpc.TRANSPORT,
|
||||||
|
target,
|
||||||
|
endpoints,
|
||||||
|
executor='eventlet',
|
||||||
|
serializer=serializer)
|
||||||
|
|
||||||
|
def _wrap_get_client(self, target, version_cap=None, serializer=None):
|
||||||
|
"""Mirror rpc.get_client() but with our special sauce."""
|
||||||
|
serializer = CheatingSerializer(serializer)
|
||||||
|
return messaging.RPCClient(rpc.TRANSPORT,
|
||||||
|
target,
|
||||||
|
version_cap=version_cap,
|
||||||
|
serializer=serializer)
|
||||||
|
|
||||||
def add_cell_database(self, connection_str, default=False):
|
def add_cell_database(self, connection_str, default=False):
|
||||||
"""Add a cell database to the fixture.
|
"""Add a cell database to the fixture.
|
||||||
|
|
||||||
@@ -454,6 +505,13 @@ class CellDatabases(fixtures.Fixture):
|
|||||||
'nova.context.target_cell',
|
'nova.context.target_cell',
|
||||||
self._wrap_target_cell))
|
self._wrap_target_cell))
|
||||||
|
|
||||||
|
self.useFixture(fixtures.MonkeyPatch(
|
||||||
|
'nova.rpc.get_server',
|
||||||
|
self._wrap_get_server))
|
||||||
|
self.useFixture(fixtures.MonkeyPatch(
|
||||||
|
'nova.rpc.get_client',
|
||||||
|
self._wrap_get_client))
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
for ctxt_mgr in self._ctxt_mgrs.values():
|
for ctxt_mgr in self._ctxt_mgrs.values():
|
||||||
engine = ctxt_mgr.get_legacy_facade().get_engine()
|
engine = ctxt_mgr.get_legacy_facade().get_engine()
|
||||||
|
|||||||
Reference in New Issue
Block a user