Make nova-manage cell_v2 discover_hosts tests use DBs

This refactors the discover_hosts tests to work with database fixtures
to more realistically test the commands. Recently, a bug was masked
because of mocking of the database APIs.

Related-Bug: #1650694

Change-Id: I6cb45beacce46c6f39861e7ca86be3bd09047b67
This commit is contained in:
melanie witt 2016-12-17 06:00:43 +00:00
parent 93a9aaa1cf
commit 446d9fed5f
2 changed files with 89 additions and 80 deletions

View File

@ -521,6 +521,21 @@ class MatchType(object):
return "<MatchType:" + str(self.wanttype) + ">"
class MatchObjPrims(object):
"""Matches objects with equal primitives."""
def __init__(self, want_obj):
self.want_obj = want_obj
def __eq__(self, other):
return objects_base.obj_equal_prims(other, self.want_obj)
def __ne__(self, other):
return not other == self.want_obj
def __repr__(self):
return '<MatchObjPrims:' + str(self.want_obj) + '>'
class ContainKeyValue(object):
"""Checks whether a key/value pair is in a dict parameter.

View File

@ -1268,7 +1268,7 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
for i in range(num):
nodes.append(objects.ComputeNode(ctxt,
uuid=uuidutils.generate_uuid(),
host='fake',
host='host%s' % i,
vcpus=1,
memory_mb=1,
local_gb=1,
@ -1281,117 +1281,111 @@ class CellV2CommandsTestCase(test.NoDBTestCase):
return nodes
@mock.patch.object(context, 'target_cell')
@mock.patch.object(objects, 'HostMapping')
@mock.patch.object(objects.ComputeNodeList, 'get_all')
@mock.patch.object(objects.CellMappingList, 'get_all')
@mock.patch.object(objects.CellMapping, 'get_by_uuid')
def test_discover_hosts_single_cell(self, mock_cell_mapping_get_by_uuid,
mock_cell_mapping_get_all,
mock_compute_get_all,
mock_host_mapping, mock_target_cell):
host_mock = mock.MagicMock()
mock_host_mapping.return_value = host_mock
exc = exception.HostMappingNotFound(name='fake')
mock_host_mapping.get_by_host.side_effect = exc
def test_discover_hosts_single_cell(self, mock_cell_mapping_get_all,
mock_target_cell):
ctxt = context.RequestContext()
compute_nodes = self._return_compute_nodes(ctxt)
mock_compute_get_all.return_value = objects.ComputeNodeList(
objects=compute_nodes)
for compute_node in compute_nodes:
compute_node.create()
cell_mapping = objects.CellMapping(uuid=uuidutils.generate_uuid())
mock_cell_mapping_get_by_uuid.return_value = cell_mapping
cell_mapping = objects.CellMapping(context=ctxt,
uuid=uuidutils.generate_uuid(),
database_connection='fake:///db',
transport_url='fake:///mq')
cell_mapping.create()
self.commands.discover_hosts(cell_uuid=cell_mapping.uuid)
# Check that the host mappings were created
for i, compute_node in enumerate(compute_nodes):
host_mapping = objects.HostMapping.get_by_host(ctxt,
compute_node.host)
self.assertEqual('host%s' % i, host_mapping.host)
mock_target_cell.assert_called_once_with(
test.MatchType(context.RequestContext), cell_mapping)
host_mock.create.assert_called_once()
mock_host_mapping.assert_called_once_with(
test.MatchType(context.RequestContext), host='fake',
cell_mapping=cell_mapping)
test.MatchType(context.RequestContext),
test.MatchObjPrims(cell_mapping))
mock_cell_mapping_get_all.assert_not_called()
@mock.patch.object(context, 'target_cell')
@mock.patch.object(objects, 'HostMapping')
@mock.patch.object(objects.ComputeNodeList, 'get_all')
@mock.patch.object(objects.CellMappingList, 'get_all')
@mock.patch.object(objects.CellMapping, 'get_by_uuid')
def test_discover_hosts_single_cell_no_new_hosts(
self, mock_cell_mapping_get_by_uuid, mock_cell_mapping_get_all,
mock_compute_get_all, mock_host_mapping, mock_target_cell):
host_mock = mock.MagicMock()
mock_host_mapping.return_value = host_mock
self, mock_cell_mapping_get_all, mock_target_cell):
ctxt = context.RequestContext()
# Create some compute nodes and matching host mappings
cell_mapping = objects.CellMapping(context=ctxt,
uuid=uuidutils.generate_uuid(),
database_connection='fake:///db',
transport_url='fake:///mq')
cell_mapping.create()
compute_nodes = self._return_compute_nodes(ctxt)
mock_compute_get_all.return_value = objects.ComputeNodeList(
objects=compute_nodes)
for compute_node in compute_nodes:
compute_node.create()
host_mapping = objects.HostMapping(context=ctxt,
host=compute_node.host,
cell_mapping=cell_mapping)
host_mapping.create()
cell_mapping = objects.CellMapping(uuid=uuidutils.generate_uuid())
mock_cell_mapping_get_by_uuid.return_value = cell_mapping
self.commands.discover_hosts(cell_uuid=cell_mapping.uuid)
with mock.patch('nova.objects.HostMapping.create') as mock_create:
self.commands.discover_hosts(cell_uuid=cell_mapping.uuid)
mock_create.assert_not_called()
mock_target_cell.assert_called_once_with(
test.MatchType(context.RequestContext), cell_mapping)
mock_host_mapping.assert_not_called()
test.MatchType(context.RequestContext),
test.MatchObjPrims(cell_mapping))
mock_cell_mapping_get_all.assert_not_called()
@mock.patch.object(context, 'target_cell')
@mock.patch.object(objects, 'HostMapping')
@mock.patch.object(objects.ComputeNodeList, 'get_all')
@mock.patch.object(objects.CellMappingList, 'get_all')
@mock.patch.object(objects.CellMapping, 'get_by_uuid')
def test_discover_hosts_multiple_cells(self, mock_cell_mapping_get_by_uuid,
mock_cell_mapping_get_all,
mock_compute_get_all,
mock_host_mapping,
mock_target_cell):
host_mock = mock.MagicMock()
mock_host_mapping.return_value = host_mock
exc = exception.HostMappingNotFound(name='fake')
mock_host_mapping.get_by_host.side_effect = exc
def test_discover_hosts_multiple_cells(self,
mock_cell_mapping_get_by_uuid):
# Create in-memory databases for cell1 and cell2 to let target_cell
# run for real. We want one compute node in cell1's db and the other
# compute node in cell2's db.
cell_dbs = nova_fixtures.CellDatabases()
cell_dbs.add_cell_database('fake:///db1')
cell_dbs.add_cell_database('fake:///db2')
self.useFixture(cell_dbs)
ctxt = context.RequestContext()
compute_nodes = self._return_compute_nodes(ctxt, num=2)
mock_compute_get_all.side_effect = (
objects.ComputeNodeList(objects=compute_nodes[1:]),
objects.ComputeNodeList(objects=compute_nodes[:1]))
cell_mapping0 = objects.CellMapping(
uuid=objects.CellMapping.CELL0_UUID)
cell_mapping1 = objects.CellMapping(uuid=uuidutils.generate_uuid())
cell_mapping2 = objects.CellMapping(uuid=uuidutils.generate_uuid())
mock_cell_mapping_get_all.return_value = objects.CellMappingList(
objects=[cell_mapping0, cell_mapping1, cell_mapping2])
context=ctxt,
uuid=objects.CellMapping.CELL0_UUID,
database_connection='fake:///db0',
transport_url='none:///')
cell_mapping0.create()
cell_mapping1 = objects.CellMapping(context=ctxt,
uuid=uuidutils.generate_uuid(),
database_connection='fake:///db1',
transport_url='fake:///mq1')
cell_mapping1.create()
cell_mapping2 = objects.CellMapping(context=ctxt,
uuid=uuidutils.generate_uuid(),
database_connection='fake:///db2',
transport_url='fake:///mq2')
cell_mapping2.create()
compute_nodes = self._return_compute_nodes(ctxt, num=2)
# Create the first compute node in cell1's db
with context.target_cell(ctxt, cell_mapping1):
compute_nodes[0].create()
# Create the first compute node in cell2's db
with context.target_cell(ctxt, cell_mapping2):
compute_nodes[1].create()
self.commands.discover_hosts()
self.assertEqual(2, mock_target_cell.call_count)
target_calls = [mock.call(test.MatchType(context.RequestContext),
cell_mapping1),
mock.call(test.MatchType(context.RequestContext),
cell_mapping2)]
self.assertEqual(target_calls, mock_target_cell.call_args_list)
self.assertEqual(2, host_mock.create.call_count)
self.assertEqual(2, mock_host_mapping.call_count)
host_mapping_calls = [mock.call(test.MatchType(context.RequestContext),
host=compute_nodes[0].host,
cell_mapping=cell_mapping1),
mock.call(test.MatchType(context.RequestContext),
host=compute_nodes[1].host,
cell_mapping=cell_mapping2)]
self.assertEqual(host_mapping_calls, mock_host_mapping.call_args_list)
# Check that the host mappings were created
for i, compute_node in enumerate(compute_nodes):
host_mapping = objects.HostMapping.get_by_host(ctxt,
compute_node.host)
self.assertEqual('host%s' % i, host_mapping.host)
mock_cell_mapping_get_by_uuid.assert_not_called()
mock_cell_mapping_get_all.assert_called_once_with(
test.MatchType(context.RequestContext))
def test_validate_transport_url_in_conf(self):
from_conf = 'fake://user:pass@host:port/'