Use db connection from RequestContext during queries
Now that db connections can be specified through the RequestContext, any queries on tables that reside in cell dbs must use the methods provided to create transaction context managers on-the-fly using the db connection from the RequestContext instead of using the "main_context_manager" for all accesses. The get_context_manager() method returns the main_context_manager if no db connection is found in the RequestContext, so things continue to work even when no cell dbs exist. The tables that reside in cell dbs are based on the Cells v2 database split doc [1]. Related to blueprint cells-db-connection-switching [1] https://review.openstack.org/#/c/277543 Change-Id: I4452116ae0c88ba18672839f2856247092bf6b9a
This commit is contained in:
parent
c62159d0bf
commit
5572a50f6d
File diff suppressed because it is too large
Load Diff
@ -197,7 +197,12 @@ class Timeout(fixtures.Fixture):
|
||||
|
||||
|
||||
class Database(fixtures.Fixture):
|
||||
def __init__(self, database='main'):
|
||||
def __init__(self, database='main', connection=None):
|
||||
"""Create a database fixture.
|
||||
|
||||
:param database: The type of database, 'main' or 'api'
|
||||
:param connection: The connection string to use
|
||||
"""
|
||||
super(Database, self).__init__()
|
||||
# NOTE(pkholkin): oslo_db.enginefacade is configured in tests the same
|
||||
# way as it is done for any other service that uses db
|
||||
@ -207,7 +212,13 @@ class Database(fixtures.Fixture):
|
||||
SESSION_CONFIGURED = True
|
||||
self.database = database
|
||||
if database == 'main':
|
||||
self.get_engine = session.get_engine
|
||||
if connection is not None:
|
||||
ctxt_mgr = session.create_context_manager(
|
||||
connection=connection)
|
||||
facade = ctxt_mgr.get_legacy_facade()
|
||||
self.get_engine = facade.get_engine
|
||||
else:
|
||||
self.get_engine = session.get_engine
|
||||
elif database == 'api':
|
||||
self.get_engine = session.get_api_engine
|
||||
|
||||
|
63
nova/tests/functional/db/test_connection_switch.py
Normal file
63
nova/tests/functional/db/test_connection_switch.py
Normal file
@ -0,0 +1,63 @@
|
||||
# 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 os
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova import test
|
||||
from nova.tests import fixtures
|
||||
|
||||
|
||||
class ConnectionSwitchTestCase(test.NoDBTestCase):
|
||||
test_filename = 'foo.db'
|
||||
|
||||
def setUp(self):
|
||||
super(ConnectionSwitchTestCase, self).setUp()
|
||||
self.addCleanup(self.cleanup)
|
||||
|
||||
def cleanup(self):
|
||||
try:
|
||||
os.remove(self.test_filename)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def test_connection_switch(self):
|
||||
# Use a file-based sqlite database so data will persist across new
|
||||
# connections
|
||||
fake_conn = 'sqlite:///' + self.test_filename
|
||||
|
||||
# The 'main' database connection will stay open, so in-memory is fine
|
||||
self.useFixture(fixtures.Database(database='main'))
|
||||
self.useFixture(fixtures.Database(connection=fake_conn))
|
||||
|
||||
# Make a request context with a cell mapping
|
||||
mapping = objects.CellMapping(database_connection=fake_conn)
|
||||
# In the tests, the admin context is required in order to read
|
||||
# an Instance back after write, for some reason
|
||||
ctxt = context.get_admin_context()
|
||||
# Create an instance in the cell database
|
||||
uuid = uuidutils.generate_uuid()
|
||||
with context.target_cell(ctxt, mapping):
|
||||
instance = objects.Instance(context=ctxt, uuid=uuid)
|
||||
instance.create()
|
||||
|
||||
# Verify the instance is found in the cell database
|
||||
inst = objects.Instance.get_by_uuid(ctxt, uuid)
|
||||
self.assertEqual(uuid, inst.uuid)
|
||||
|
||||
# Verify the instance isn't found in the main database
|
||||
self.assertRaises(exception.InstanceNotFound,
|
||||
objects.Instance.get_by_uuid, ctxt, uuid)
|
Loading…
Reference in New Issue
Block a user