def4b17934
nova/db/__init__.py was importing * from nova.db.api. This meant that any time any code anywhere within the nova.db package was imported then nova.db.api was too, leading to a cascade of imports that may not have been desired. Also, in general, code in __init__.py is a pain. Therefore, this change adjusts code that so that either: * nova.db.api is used directly * nova.db.api is imported as 'db' In either case, the functionality remains the same. The primary goal of this change was to make it possible to import the model files without having to import the db api. Moving the model files to a different place in the directory hierarchy was considered, but given that "code in __init__.py is a pain" this mode was chosen. This looks like a very large change, but it is essentially adjusting package names, many in mocks. Change-Id: Ic1fd7c87ceda05eeb96735da2a415ef37060bb1a
214 lines
7.1 KiB
Python
214 lines
7.1 KiB
Python
# Copyright (c) 2012 Rackspace Hosting
|
|
# All Rights Reserved.
|
|
#
|
|
# 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.
|
|
"""
|
|
Fakes For Cells tests.
|
|
"""
|
|
|
|
from nova.cells import driver
|
|
from nova.cells import manager as cells_manager
|
|
from nova.cells import state as cells_state
|
|
from nova.cells import utils as cells_utils
|
|
import nova.conf
|
|
import nova.db.api
|
|
from nova.db import base
|
|
from nova import exception
|
|
from nova import objects
|
|
|
|
CONF = nova.conf.CONF
|
|
|
|
|
|
# Fake Cell Hierarchy
|
|
FAKE_TOP_LEVEL_CELL_NAME = 'api-cell'
|
|
FAKE_CELL_LAYOUT = [{'child-cell1': []},
|
|
{'child-cell2': [{'grandchild-cell1': []}]},
|
|
{'child-cell3': [{'grandchild-cell2': []},
|
|
{'grandchild-cell3': []}]},
|
|
{'child-cell4': []}]
|
|
|
|
# build_cell_stub_infos() below will take the above layout and create
|
|
# a fake view of the DB from the perspective of each of the cells.
|
|
# For each cell, a CellStubInfo will be created with this info.
|
|
CELL_NAME_TO_STUB_INFO = {}
|
|
|
|
|
|
class FakeDBApi(object):
|
|
"""Cells uses a different DB in each cell. This means in order to
|
|
stub out things differently per cell, I need to create a fake DBApi
|
|
object that is instantiated by each fake cell.
|
|
"""
|
|
def __init__(self, cell_db_entries):
|
|
self.cell_db_entries = cell_db_entries
|
|
|
|
def __getattr__(self, key):
|
|
return getattr(nova.db.api, key)
|
|
|
|
def cell_get_all(self, ctxt):
|
|
return self.cell_db_entries
|
|
|
|
def instance_get_all_by_filters(self, ctxt, *args, **kwargs):
|
|
return []
|
|
|
|
def instance_get_by_uuid(self, ctxt, instance_uuid):
|
|
raise exception.InstanceNotFound(instance_id=instance_uuid)
|
|
|
|
|
|
class FakeCellsDriver(driver.BaseCellsDriver):
|
|
pass
|
|
|
|
|
|
class FakeCellState(cells_state.CellState):
|
|
def send_message(self, message):
|
|
message_runner = get_message_runner(self.name)
|
|
orig_ctxt = message.ctxt
|
|
json_message = message.to_json()
|
|
message = message_runner.message_from_json(json_message)
|
|
# Restore this so we can use mox and verify same context
|
|
message.ctxt = orig_ctxt
|
|
message.process()
|
|
|
|
|
|
class FakeCellStateManager(cells_state.CellStateManagerDB):
|
|
def __init__(self, *args, **kwargs):
|
|
super(FakeCellStateManager, self).__init__(*args,
|
|
cell_state_cls=FakeCellState, **kwargs)
|
|
|
|
|
|
class FakeCellsManager(cells_manager.CellsManager):
|
|
def __init__(self, *args, **kwargs):
|
|
super(FakeCellsManager, self).__init__(*args,
|
|
cell_state_manager=FakeCellStateManager,
|
|
**kwargs)
|
|
|
|
|
|
class CellStubInfo(object):
|
|
def __init__(self, test_case, cell_name, db_entries):
|
|
self.test_case = test_case
|
|
self.cell_name = cell_name
|
|
self.db_entries = db_entries
|
|
|
|
def fake_base_init(_self, *args, **kwargs):
|
|
_self.db = FakeDBApi(db_entries)
|
|
|
|
@staticmethod
|
|
def _fake_compute_node_get_all(context):
|
|
return []
|
|
|
|
@staticmethod
|
|
def _fake_service_get_by_binary(context, binary):
|
|
return []
|
|
|
|
test_case.stubs.Set(base.Base, '__init__', fake_base_init)
|
|
test_case.stubs.Set(objects.ComputeNodeList, 'get_all',
|
|
_fake_compute_node_get_all)
|
|
test_case.stubs.Set(objects.ServiceList, 'get_by_binary',
|
|
_fake_service_get_by_binary)
|
|
self.cells_manager = FakeCellsManager()
|
|
# Fix the cell name, as it normally uses CONF.cells.name
|
|
msg_runner = self.cells_manager.msg_runner
|
|
msg_runner.our_name = self.cell_name
|
|
self.cells_manager.state_manager.my_cell_state.name = self.cell_name
|
|
|
|
|
|
def _build_cell_transport_url(cur_db_id):
|
|
username = 'username%s' % cur_db_id
|
|
password = 'password%s' % cur_db_id
|
|
hostname = 'rpc_host%s' % cur_db_id
|
|
port = 3090 + cur_db_id
|
|
virtual_host = 'rpc_vhost%s' % cur_db_id
|
|
|
|
return 'rabbit://%s:%s@%s:%s/%s' % (username, password, hostname, port,
|
|
virtual_host)
|
|
|
|
|
|
def _build_cell_stub_info(test_case, our_name, parent_path, children):
|
|
cell_db_entries = []
|
|
cur_db_id = 1
|
|
sep_char = cells_utils.PATH_CELL_SEP
|
|
if parent_path:
|
|
cell_db_entries.append(
|
|
dict(id=cur_db_id,
|
|
name=parent_path.split(sep_char)[-1],
|
|
is_parent=True,
|
|
transport_url=_build_cell_transport_url(cur_db_id)))
|
|
cur_db_id += 1
|
|
our_path = parent_path + sep_char + our_name
|
|
else:
|
|
our_path = our_name
|
|
for child in children:
|
|
for child_name, grandchildren in child.items():
|
|
_build_cell_stub_info(test_case, child_name, our_path,
|
|
grandchildren)
|
|
cell_entry = dict(id=cur_db_id,
|
|
name=child_name,
|
|
transport_url=_build_cell_transport_url(
|
|
cur_db_id),
|
|
is_parent=False)
|
|
cell_db_entries.append(cell_entry)
|
|
cur_db_id += 1
|
|
stub_info = CellStubInfo(test_case, our_name, cell_db_entries)
|
|
CELL_NAME_TO_STUB_INFO[our_name] = stub_info
|
|
|
|
|
|
def _build_cell_stub_infos(test_case):
|
|
_build_cell_stub_info(test_case, FAKE_TOP_LEVEL_CELL_NAME, '',
|
|
FAKE_CELL_LAYOUT)
|
|
|
|
|
|
def init(test_case):
|
|
global CELL_NAME_TO_STUB_INFO
|
|
CELL_NAME_TO_STUB_INFO = {}
|
|
_build_cell_stub_infos(test_case)
|
|
|
|
|
|
def _get_cell_stub_info(cell_name):
|
|
return CELL_NAME_TO_STUB_INFO[cell_name]
|
|
|
|
|
|
def get_state_manager(cell_name):
|
|
return _get_cell_stub_info(cell_name).cells_manager.state_manager
|
|
|
|
|
|
def get_cell_state(cur_cell_name, tgt_cell_name):
|
|
state_manager = get_state_manager(cur_cell_name)
|
|
cell = state_manager.child_cells.get(tgt_cell_name)
|
|
if cell is None:
|
|
cell = state_manager.parent_cells.get(tgt_cell_name)
|
|
return cell
|
|
|
|
|
|
def get_cells_manager(cell_name):
|
|
return _get_cell_stub_info(cell_name).cells_manager
|
|
|
|
|
|
def get_message_runner(cell_name):
|
|
return _get_cell_stub_info(cell_name).cells_manager.msg_runner
|
|
|
|
|
|
def stub_tgt_method(test_case, cell_name, method_name, method):
|
|
msg_runner = get_message_runner(cell_name)
|
|
tgt_msg_methods = msg_runner.methods_by_type['targeted']
|
|
setattr(tgt_msg_methods, method_name, method)
|
|
|
|
|
|
def stub_bcast_method(test_case, cell_name, method_name, method):
|
|
msg_runner = get_message_runner(cell_name)
|
|
tgt_msg_methods = msg_runner.methods_by_type['broadcast']
|
|
setattr(tgt_msg_methods, method_name, method)
|
|
|
|
|
|
def stub_bcast_methods(test_case, method_name, method):
|
|
for cell_name in CELL_NAME_TO_STUB_INFO.keys():
|
|
stub_bcast_method(test_case, cell_name, method_name, method)
|