Browse Source

Include only required fields in ironic node cache

The ironic virt driver maintains a cache of ironic nodes to avoid
continually polling the ironic API.  Code paths requiring a specific
node use a limited set of fields, _NODE_FIELDS, when querying the
ironic API for the node. This reduces the memory footprint required by
the cache, and the network traffic required to populate it. However,
in most cases the cache is populated using a detailed node list
operation in _refresh_cache(), which includes all node fields.

This change specifies _NODE_FIELDS in the node list operation in
_refresh_cache().

We also modify the unit tests to use fake node objects that are
representative of the nodes in the cache.

Change-Id: Id96e7e513f469b87992ddae1431cce714e91ed16
Related-Bug: #1746209
(cherry picked from commit 8bbad196a7)
changes/62/724862/1
Mark Goddard 2 years ago
committed by melanie witt
parent
commit
f5b6dc603c
3 changed files with 181 additions and 165 deletions
  1. +154
    -140
      nova/tests/unit/virt/ironic/test_driver.py
  2. +26
    -24
      nova/tests/unit/virt/ironic/utils.py
  3. +1
    -1
      nova/virt/ironic/driver.py

+ 154
- 140
nova/tests/unit/virt/ironic/test_driver.py View File

@@ -92,6 +92,11 @@ def _get_stats():
return {'cpu_arch': 'x86_64'}


def _get_cached_node(**kw):
"""Return a fake node object representative of objects in the cache."""
return ironic_utils.get_test_node(fields=ironic_driver._NODE_FIELDS, **kw)


def _make_compute_service(hostname):
return objects.Service(host=hostname)

@@ -147,8 +152,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'get_by_instance_uuid')
def test__validate_instance_and_node(self, mock_gbiui):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=self.instance_uuid)
node = _get_cached_node(
uuid=node_uuid, instance_uuid=self.instance_uuid)
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=self.instance_uuid)
mock_gbiui.return_value = node
@@ -173,8 +178,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__wait_for_active_pass(self, fake_validate, fake_refresh):
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=uuidutils.generate_uuid())
node = ironic_utils.get_test_node(
provision_state=ironic_states.DEPLOYING)
node = _get_cached_node(provision_state=ironic_states.DEPLOYING)

fake_validate.return_value = node
self.driver._wait_for_active(instance)
@@ -187,8 +191,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__wait_for_active_done(self, fake_validate, fake_refresh):
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=uuidutils.generate_uuid())
node = ironic_utils.get_test_node(
provision_state=ironic_states.ACTIVE)
node = _get_cached_node(provision_state=ironic_states.ACTIVE)

fake_validate.return_value = node
self.assertRaises(loopingcall.LoopingCallDone,
@@ -219,8 +222,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__wait_for_active_fail(self, fake_validate, fake_refresh):
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=uuidutils.generate_uuid())
node = ironic_utils.get_test_node(
provision_state=ironic_states.DEPLOYFAIL)
node = _get_cached_node(provision_state=ironic_states.DEPLOYFAIL)

fake_validate.return_value = node
self.assertRaises(exception.InstanceDeployFailure,
@@ -257,8 +259,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__wait_for_power_state_pass(self, fake_validate):
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=uuidutils.generate_uuid())
node = ironic_utils.get_test_node(
target_power_state=ironic_states.POWER_OFF)
node = _get_cached_node(target_power_state=ironic_states.POWER_OFF)

fake_validate.return_value = node
self.driver._wait_for_power_state(instance, 'fake message')
@@ -269,8 +270,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__wait_for_power_state_ok(self, fake_validate):
instance = fake_instance.fake_instance_obj(self.ctx,
uuid=uuidutils.generate_uuid())
node = ironic_utils.get_test_node(
target_power_state=ironic_states.NOSTATE)
node = _get_cached_node(target_power_state=ironic_states.NOSTATE)

fake_validate.return_value = node
self.assertRaises(loopingcall.LoopingCallDone,
@@ -281,10 +281,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = uuidutils.generate_uuid()
props = _get_properties()
stats = _get_stats()
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=self.instance_uuid,
properties=props,
resource_class='foo')
node = _get_cached_node(
uuid=node_uuid, instance_uuid=self.instance_uuid,
properties=props, resource_class='foo')

result = self.driver._node_resource(node)

@@ -317,7 +316,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = uuidutils.generate_uuid()
props = _get_properties()
props['cpu_arch'] = 'i386'
node = ironic_utils.get_test_node(uuid=node_uuid, properties=props)
node = _get_cached_node(uuid=node_uuid, properties=props)

result = self.driver._node_resource(node)
self.assertEqual('i686', result['supported_instances'][0][0])
@@ -327,7 +326,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = uuidutils.generate_uuid()
props = _get_properties()
del props['cpu_arch']
node = ironic_utils.get_test_node(uuid=node_uuid, properties=props)
node = _get_cached_node(uuid=node_uuid, properties=props)

result = self.driver._node_resource(node)
self.assertEqual([], result['supported_instances'])
@@ -335,7 +334,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__node_resource_exposes_capabilities(self):
props = _get_properties()
props['capabilities'] = 'test:capability, test2:value2'
node = ironic_utils.get_test_node(properties=props)
node = _get_cached_node(properties=props)
result = self.driver._node_resource(node)
stats = result['stats']
self.assertIsNone(stats.get('capabilities'))
@@ -345,14 +344,14 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__node_resource_no_capabilities(self):
props = _get_properties()
props['capabilities'] = None
node = ironic_utils.get_test_node(properties=props)
node = _get_cached_node(properties=props)
result = self.driver._node_resource(node)
self.assertIsNone(result['stats'].get('capabilities'))

def test__node_resource_malformed_capabilities(self):
props = _get_properties()
props['capabilities'] = 'test:capability,:no_key,no_val:'
node = ironic_utils.get_test_node(properties=props)
node = _get_cached_node(properties=props)
result = self.driver._node_resource(node)
stats = result['stats']
self.assertEqual('capability', stats.get('test'))
@@ -361,7 +360,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = uuidutils.generate_uuid()
props = _get_properties()
stats = _get_stats()
node = ironic_utils.get_test_node(
node = _get_cached_node(
uuid=node_uuid,
instance_uuid=None,
power_state=ironic_states.POWER_OFF,
@@ -385,9 +384,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = uuidutils.generate_uuid()
props = _get_properties()
stats = _get_stats()
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=None,
properties=props)
node = _get_cached_node(
uuid=node_uuid, instance_uuid=None, properties=props)

result = self.driver._node_resource(node)
self.assertEqual(0, result['vcpus'])
@@ -407,7 +405,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
props = _get_properties()
stats = _get_stats()
instance_info = _get_instance_info()
node = ironic_utils.get_test_node(
node = _get_cached_node(
uuid=node_uuid,
instance_uuid=uuidutils.generate_uuid(),
provision_state=ironic_states.ACTIVE,
@@ -427,7 +425,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(ironic_driver.LOG, 'warning')
def test__parse_node_properties(self, mock_warning):
props = _get_properties()
node = ironic_utils.get_test_node(
node = _get_cached_node(
uuid=uuidutils.generate_uuid(),
properties=props)
# raw_cpu_arch is included because extra_specs filters do not
@@ -447,7 +445,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
props['memory_mb'] = 'bad-value'
props['local_gb'] = 'bad-value'
props['cpu_arch'] = 'bad-value'
node = ironic_utils.get_test_node(
node = _get_cached_node(
uuid=uuidutils.generate_uuid(),
properties=props)
# raw_cpu_arch is included because extra_specs filters do not
@@ -499,7 +497,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__parse_node_properties_canonicalize_cpu_arch(self, mock_warning):
props = _get_properties()
props['cpu_arch'] = 'amd64'
node = ironic_utils.get_test_node(
node = _get_cached_node(
uuid=uuidutils.generate_uuid(),
properties=props)
# raw_cpu_arch is included because extra_specs filters do not
@@ -610,13 +608,14 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test_node_is_available_empty_cache_empty_list(self, mock_services,
mock_instances, mock_get,
mock_list):
node = ironic_utils.get_test_node()
node = _get_cached_node()
mock_get.return_value = node
mock_list.return_value = []
self.assertTrue(self.driver.node_is_available(node.uuid))
mock_get.assert_called_with(node.uuid,
fields=ironic_driver._NODE_FIELDS)
mock_list.assert_called_with(detail=True, limit=0)
mock_list.assert_called_with(fields=ironic_driver._NODE_FIELDS,
limit=0)

mock_get.side_effect = ironic_exception.NotFound
self.assertFalse(self.driver.node_is_available(node.uuid))
@@ -627,11 +626,12 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(objects.ServiceList, 'get_all_computes_by_hv_type')
def test_node_is_available_empty_cache(self, mock_services, mock_instances,
mock_get, mock_list):
node = ironic_utils.get_test_node()
node = _get_cached_node()
mock_get.return_value = node
mock_list.return_value = [node]
self.assertTrue(self.driver.node_is_available(node.uuid))
mock_list.assert_called_with(detail=True, limit=0)
mock_list.assert_called_with(fields=ironic_driver._NODE_FIELDS,
limit=0)
self.assertEqual(0, mock_get.call_count)

@mock.patch.object(FAKE_CLIENT.node, 'list')
@@ -640,7 +640,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(objects.ServiceList, 'get_all_computes_by_hv_type')
def test_node_is_available_with_cache(self, mock_services, mock_instances,
mock_get, mock_list):
node = ironic_utils.get_test_node()
node = _get_cached_node()
mock_get.return_value = node
mock_list.return_value = [node]
# populate the cache
@@ -689,13 +689,13 @@ class IronicDriverTestCase(test.NoDBTestCase):
'provision_state': ironic_states.DELETED},
]
for n in node_dicts:
node = ironic_utils.get_test_node(**n)
node = _get_cached_node(**n)
self.assertTrue(self.driver._node_resources_unavailable(node))

for ok_state in (ironic_states.AVAILABLE, ironic_states.NOSTATE):
# these are both ok and should present as available as they
# have no instance_uuid
avail_node = ironic_utils.get_test_node(
avail_node = _get_cached_node(
power_state=ironic_states.POWER_OFF,
provision_state=ok_state)
unavailable = self.driver._node_resources_unavailable(avail_node)
@@ -709,10 +709,10 @@ class IronicDriverTestCase(test.NoDBTestCase):
'provision_state': ironic_states.ACTIVE},
]
for n in node_dicts:
node = ironic_utils.get_test_node(**n)
node = _get_cached_node(**n)
self.assertTrue(self.driver._node_resources_used(node))

unused_node = ironic_utils.get_test_node(
unused_node = _get_cached_node(
instance_uuid=None,
provision_state=ironic_states.AVAILABLE)
self.assertFalse(self.driver._node_resources_used(unused_node))
@@ -745,7 +745,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
'power_state': ironic_states.ERROR,
'expected': True},
]
nodes = [ironic_utils.get_test_node(**n) for n in node_dicts]
nodes = [_get_cached_node(**n)
for n in node_dicts]
mock_list.return_value = nodes
available_nodes = self.driver.get_available_nodes()
mock_gi.assert_called_once_with(mock.ANY, CONF.host)
@@ -993,7 +994,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(ironic_driver.IronicDriver, '_node_from_cache')
def test_get_traits_no_traits(self, mock_nfc):
"""Ensure that when the node has no traits, we return no traits."""
node = ironic_utils.get_test_node()
node = _get_cached_node()
mock_nfc.return_value = node
result = self.driver.get_traits(node.uuid)

@@ -1003,7 +1004,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(ironic_driver.IronicDriver, '_node_from_cache')
def test_get_traits_with_traits(self, mock_nfc):
"""Ensure that when the node has traits, we return the traits."""
node = ironic_utils.get_test_node(traits=['trait1', 'trait2'])
node = _get_cached_node(traits=['trait1', 'trait2'])
mock_nfc.return_value = node
result = self.driver.get_traits(node.uuid)

@@ -1018,8 +1019,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(ironic_driver.IronicDriver, '_node_resource')
def test_get_available_resource(self, mock_nr, mock_services,
mock_instances, mock_list, mock_get):
node = ironic_utils.get_test_node()
node_2 = ironic_utils.get_test_node(uuid=uuidutils.generate_uuid())
node = _get_cached_node()
node_2 = _get_cached_node(uuid=uuidutils.generate_uuid())
fake_resource = 'fake-resource'
mock_get.return_value = node
# ensure cache gets populated without the node we want
@@ -1040,7 +1041,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test_get_available_resource_with_cache(self, mock_nr, mock_services,
mock_instances, mock_list,
mock_get):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_resource = 'fake-resource'
mock_list.return_value = [node]
mock_nr.return_value = fake_resource
@@ -1058,9 +1059,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test_get_info(self, mock_gbiu):
properties = {'memory_mb': 512, 'cpus': 2}
power_state = ironic_states.POWER_ON
node = ironic_utils.get_test_node(instance_uuid=self.instance_uuid,
properties=properties,
power_state=power_state)
node = _get_cached_node(
instance_uuid=self.instance_uuid, properties=properties,
power_state=power_state)

mock_gbiu.return_value = node

@@ -1093,7 +1094,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
def _test_spawn(self, mock_sf, mock_aiitn, mock_wait_active,
mock_avti, mock_node, mock_looping, mock_save):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
fake_flavor = objects.Flavor(ephemeral_gb=0)
instance.flavor = fake_flavor
@@ -1163,7 +1164,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_looping, mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
fake_flavor = objects.Flavor(ephemeral_gb=0)
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = fake_flavor
@@ -1185,7 +1186,7 @@ class IronicDriverTestCase(test.NoDBTestCase):

def _test_add_instance_info_to_node(self, mock_update=None,
mock_call=None):
node = ironic_utils.get_test_node(driver='fake')
node = _get_cached_node(driver='fake')
instance = fake_instance.fake_instance_obj(self.ctx,
node=node.uuid)
image_meta = ironic_utils.get_test_image_meta()
@@ -1232,7 +1233,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'update')
def test__add_instance_info_to_node_fail(self, mock_update):
mock_update.side_effect = ironic_exception.BadRequest()
node = ironic_utils.get_test_node(driver='fake')
node = _get_cached_node(driver='fake')
instance = fake_instance.fake_instance_obj(self.ctx,
node=node.uuid)
image_meta = ironic_utils.get_test_image_meta()
@@ -1242,7 +1243,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
node, instance, image_meta, flavor)

def _test_remove_instance_info_from_node(self, mock_update):
node = ironic_utils.get_test_node(driver='fake')
node = _get_cached_node(driver='fake')
instance = fake_instance.fake_instance_obj(self.ctx,
node=node.uuid)
self.driver._remove_instance_info_from_node(node, instance)
@@ -1390,7 +1391,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1418,7 +1419,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_node, mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1450,7 +1451,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_required_by):
mock_required_by.return_value = True
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1482,7 +1483,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_node, mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1510,7 +1511,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_node, mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1540,7 +1541,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor()
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1573,7 +1574,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_required_by):
mock_required_by.return_value = False
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
node = _get_cached_node(driver='fake', uuid=node_uuid)
flavor = ironic_utils.get_test_flavor(ephemeral_gb=1)
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
instance.flavor = flavor
@@ -1594,8 +1595,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
network_info = 'foo'

node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid,
provision_state=state)
node = _get_cached_node(
driver='fake', uuid=node_uuid, provision_state=state)
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)

def fake_set_provision_state(*_):
@@ -1628,8 +1629,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
def test_destroy_trigger_undeploy_fail(self, fake_validate, mock_sps):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid,
provision_state=ironic_states.ACTIVE)
node = _get_cached_node(
driver='fake', uuid=node_uuid,
provision_state=ironic_states.ACTIVE)
fake_validate.return_value = node
instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
@@ -1642,9 +1644,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
def _test__unprovision_instance(self, mock_validate_inst, mock_set_pstate,
state=None):
node = ironic_utils.get_test_node(
driver='fake',
provision_state=state)
node = _get_cached_node(driver='fake', provision_state=state)
instance = fake_instance.fake_instance_obj(self.ctx, node=node.uuid)
mock_validate_inst.return_value = node
self.driver._unprovision(instance, node)
@@ -1663,9 +1663,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
def test__unprovision_fail_max_retries(self, mock_validate_inst,
mock_set_pstate):
CONF.set_default('api_max_retries', default=2, group='ironic')
node = ironic_utils.get_test_node(
driver='fake',
provision_state=ironic_states.ACTIVE)
node = _get_cached_node(
driver='fake', provision_state=ironic_states.ACTIVE)
instance = fake_instance.fake_instance_obj(self.ctx, node=node.uuid)

mock_validate_inst.return_value = node
@@ -1681,7 +1680,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
def test__unprovision_instance_not_found(self, mock_validate_inst,
mock_set_pstate):
node = ironic_utils.get_test_node(
node = _get_cached_node(
driver='fake', provision_state=ironic_states.DELETING)
instance = fake_instance.fake_instance_obj(self.ctx, node=node.uuid)

@@ -1694,8 +1693,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT, 'node')
def test_destroy_unassociate_fail(self, mock_node):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid,
provision_state=ironic_states.ACTIVE)
node = _get_cached_node(
driver='fake', uuid=node_uuid,
provision_state=ironic_states.ACTIVE)
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)

mock_node.get_by_instance_uuid.return_value = node
@@ -1712,7 +1712,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_reboot(self, mock_sp, fake_validate, mock_looping):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]

fake_looping_call = FakeLoopingCall()
@@ -1726,7 +1726,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'inject_nmi')
def test_trigger_crash_dump(self, mock_nmi, fake_validate):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.return_value = node
instance = fake_instance.fake_instance_obj(self.ctx,
node=node.uuid)
@@ -1737,7 +1737,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'inject_nmi')
def test_trigger_crash_dump_error(self, mock_nmi, fake_validate):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.return_value = node
mock_nmi.side_effect = ironic_exception.BadRequest()
instance = fake_instance.fake_instance_obj(self.ctx,
@@ -1750,7 +1750,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_reboot_soft(self, mock_sp, fake_validate, mock_looping):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]

fake_looping_call = FakeLoopingCall()
@@ -1766,7 +1766,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_reboot_soft_not_supported(self, mock_sp, fake_validate,
mock_looping):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]
mock_sp.side_effect = [ironic_exception.BadRequest(), None]

@@ -1783,7 +1783,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_power_on(self, mock_sp, fake_validate, mock_looping):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]

fake_looping_call = FakeLoopingCall()
@@ -1806,7 +1806,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_power_off(self, mock_sp, fake_validate):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]

self._test_power_off()
@@ -1816,9 +1816,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_power_off_soft(self, mock_sp, fake_validate):
node = ironic_utils.get_test_node()
power_off_node = ironic_utils.get_test_node(
power_state=ironic_states.POWER_OFF)
node = _get_cached_node()
power_off_node = _get_cached_node(power_state=ironic_states.POWER_OFF)
fake_validate.side_effect = [node, power_off_node]

self._test_power_off(timeout=30)
@@ -1829,7 +1828,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_power_off_soft_exception(self, mock_sp, fake_validate):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]
mock_sp.side_effect = [ironic_exception.BadRequest(), None]

@@ -1843,7 +1842,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
'_validate_instance_and_node')
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
def test_power_off_soft_not_stopped(self, mock_sp, fake_validate):
node = ironic_utils.get_test_node()
node = _get_cached_node()
fake_validate.side_effect = [node, node]

self._test_power_off(timeout=30)
@@ -1855,7 +1854,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'vif_attach')
def test_plug_vifs_with_port(self, mock_vatt):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)

instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
@@ -1871,7 +1870,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs')
def test_plug_vifs(self, mock__plug_vifs, mock_get):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)

mock_get.return_value = node
instance = fake_instance.fake_instance_obj(self.ctx,
@@ -1886,7 +1885,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'vif_attach')
def test_plug_vifs_multiple_ports(self, mock_vatt):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)
instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
first_vif_id = 'aaaaaaaa-vv11-cccc-dddd-eeeeeeeeeeee'
@@ -1906,7 +1905,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT, 'node')
def test_plug_vifs_failure(self, mock_node):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)
instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
first_vif_id = 'aaaaaaaa-vv11-cccc-dddd-eeeeeeeeeeee'
@@ -1950,7 +1949,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT, 'node')
def test_plug_vifs_already_attached(self, mock_node):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)
instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
first_vif_id = 'aaaaaaaa-vv11-cccc-dddd-eeeeeeeeeeee'
@@ -1968,7 +1967,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT.node, 'vif_attach')
def test_plug_vifs_no_network_info(self, mock_vatt):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)

instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
@@ -1981,7 +1980,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT, 'node')
def test_unplug_vifs(self, mock_node):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)
mock_node.get.return_value = node

instance = fake_instance.fake_instance_obj(self.ctx,
@@ -1998,7 +1997,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
@mock.patch.object(FAKE_CLIENT, 'node')
def test_unplug_vifs_port_not_associated(self, mock_node):
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
node = ironic_utils.get_test_node(uuid=node_uuid)
node = _get_cached_node(uuid=node_uuid)

mock_node.get.return_value = node
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
@@ -2073,9 +2072,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_set_pstate, mock_looping, mock_wait_active,
preserve=False):
node_uuid = uuidutils.generate_uuid()
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=self.instance_uuid,
instance_type_id=5)
node = _get_cached_node(
uuid=node_uuid, instance_uuid=self.instance_uuid,
instance_type_id=5)
mock_get.return_value = node

image_meta = ironic_utils.get_test_image_meta()
@@ -2148,9 +2147,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_required_by,
mock_configdrive):
node_uuid = uuidutils.generate_uuid()
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=self.instance_uuid,
instance_type_id=5)
node = _get_cached_node(
uuid=node_uuid, instance_uuid=self.instance_uuid,
instance_type_id=5)
mock_get.return_value = node
mock_required_by.return_value = True
mock_configdrive.side_effect = exception.NovaException()
@@ -2183,9 +2182,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
mock_add_instance_info, mock_set_pstate,
mock_required_by, mock_configdrive):
node_uuid = uuidutils.generate_uuid()
node = ironic_utils.get_test_node(uuid=node_uuid,
instance_uuid=self.instance_uuid,
instance_type_id=5)
node = _get_cached_node(
uuid=node_uuid, instance_uuid=self.instance_uuid,
instance_type_id=5)
mock_get.return_value = node
mock_required_by.return_value = False

@@ -2420,12 +2419,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node2_uuid,
host=hostname,
flavor=fake_flavor2)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class="first",
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2474,12 +2475,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node2_uuid,
host=hostname,
flavor=fake_flavor2)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class="first",
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2529,12 +2532,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node2_uuid,
host=hostname,
flavor=fake_flavor2)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class=None,
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2587,12 +2592,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node2_uuid,
host=hostname,
flavor=fake_flavor2)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class="first",
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2639,12 +2646,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node2_uuid,
host=hostname,
flavor=fake_flavor2)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class="first",
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2698,12 +2707,14 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
node=node3_uuid,
host=hostname,
flavor=fake_flavor3)
node1 = ironic_utils.get_test_node(uuid=node1_uuid,
node1 = _get_cached_node(
uuid=node1_uuid,
instance_uuid=inst1.uuid,
instance_type_id=1,
resource_class="first",
network_interface="flat")
node2 = ironic_utils.get_test_node(uuid=node2_uuid,
node2 = _get_cached_node(
uuid=node2_uuid,
instance_uuid=inst2.uuid,
instance_type_id=2,
resource_class="second",
@@ -2757,7 +2768,8 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
@mock.patch.object(ironic_driver.IronicDriver, '_node_from_cache')
def test_pike_flavor_migration_already_migrated(self, mock_node_from_cache,
mock_normalize):
node1 = ironic_utils.get_test_node(uuid=uuids.node1,
node1 = _get_cached_node(
uuid=uuids.node1,
instance_uuid=uuids.instance,
instance_type_id=1,
resource_class="first",
@@ -2781,7 +2793,7 @@ class IronicDriverGenerateConfigDriveTestCase(test.NoDBTestCase):
self.driver.virtapi = fake.FakeVirtAPI()
self.ctx = nova_context.get_admin_context()
node_uuid = uuidutils.generate_uuid()
self.node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
self.node = _get_cached_node(driver='fake', uuid=node_uuid)
self.instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)
self.network_info = utils.get_test_network_info()
@@ -3000,19 +3012,20 @@ class NodeCacheTestCase(test.NoDBTestCase):

mock_hash_ring.assert_called_once_with(mock.ANY)
mock_instances.assert_called_once_with(mock.ANY, self.host)
mock_nodes.assert_called_once_with(detail=True, limit=0)
mock_nodes.assert_called_once_with(fields=ironic_driver._NODE_FIELDS,
limit=0)
self.assertIsNotNone(self.driver.node_cache_time)

def test__refresh_cache(self):
# normal operation, one compute service
instances = []
nodes = [
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
]
hosts = [self.host, self.host, self.host]

@@ -3025,12 +3038,12 @@ class NodeCacheTestCase(test.NoDBTestCase):
# normal operation, many compute services
instances = []
nodes = [
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
]
hosts = [self.host, 'host2', 'host3']

@@ -3044,12 +3057,12 @@ class NodeCacheTestCase(test.NoDBTestCase):
# map to us
instances = [uuidutils.generate_uuid()]
nodes = [
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=instances[0]),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=instances[0]),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
]
# only two calls, having the instance will short-circuit the first node
hosts = [{self.host}, {self.host}]
@@ -3064,12 +3077,13 @@ class NodeCacheTestCase(test.NoDBTestCase):
# an instance for, even if it maps to us
instances = []
nodes = [
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
_get_cached_node(
uuid=uuidutils.generate_uuid(),
instance_uuid=uuidutils.generate_uuid()),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
ironic_utils.get_test_node(uuid=uuidutils.generate_uuid(),
instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
_get_cached_node(
uuid=uuidutils.generate_uuid(), instance_uuid=None),
]
hosts = [self.host, self.host]

@@ -3091,7 +3105,7 @@ class IronicDriverConsoleTestCase(test.NoDBTestCase):
self.driver = ironic_driver.IronicDriver(fake.FakeVirtAPI())
self.ctx = nova_context.get_admin_context()
node_uuid = uuidutils.generate_uuid()
self.node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid)
self.node = _get_cached_node(driver='fake', uuid=node_uuid)
self.instance = fake_instance.fake_instance_obj(self.ctx,
node=node_uuid)



+ 26
- 24
nova/tests/unit/virt/ironic/utils.py View File

@@ -26,32 +26,34 @@ def get_test_validation(**kw):
'storage': kw.get('storage', {'result': True})})()


def get_test_node(**kw):
return type('node', (object,),
{'uuid': kw.get('uuid', 'eeeeeeee-dddd-cccc-bbbb-aaaaaaaaaaaa'),
'chassis_uuid': kw.get('chassis_uuid'),
'power_state': kw.get('power_state',
def get_test_node(fields=None, **kw):
node = {'uuid': kw.get('uuid', 'eeeeeeee-dddd-cccc-bbbb-aaaaaaaaaaaa'),
'chassis_uuid': kw.get('chassis_uuid'),
'power_state': kw.get('power_state',
ironic_states.NOSTATE),
'target_power_state': kw.get('target_power_state',
ironic_states.NOSTATE),
'provision_state': kw.get('provision_state',
ironic_states.NOSTATE),
'target_power_state': kw.get('target_power_state',
'target_provision_state': kw.get('target_provision_state',
ironic_states.NOSTATE),
'provision_state': kw.get('provision_state',
ironic_states.NOSTATE),
'target_provision_state': kw.get('target_provision_state',
ironic_states.NOSTATE),
'last_error': kw.get('last_error'),
'instance_uuid': kw.get('instance_uuid'),
'instance_info': kw.get('instance_info'),
'driver': kw.get('driver', 'fake'),
'driver_info': kw.get('driver_info', {}),
'properties': kw.get('properties', {}),
'reservation': kw.get('reservation'),
'maintenance': kw.get('maintenance', False),
'network_interface': kw.get('network_interface'),
'resource_class': kw.get('resource_class'),
'traits': kw.get('traits', []),
'extra': kw.get('extra', {}),
'updated_at': kw.get('created_at'),
'created_at': kw.get('updated_at')})()
'last_error': kw.get('last_error'),
'instance_uuid': kw.get('instance_uuid'),
'instance_info': kw.get('instance_info'),
'driver': kw.get('driver', 'fake'),
'driver_info': kw.get('driver_info', {}),
'properties': kw.get('properties', {}),
'reservation': kw.get('reservation'),
'maintenance': kw.get('maintenance', False),
'network_interface': kw.get('network_interface'),
'resource_class': kw.get('resource_class'),
'traits': kw.get('traits', []),
'extra': kw.get('extra', {}),
'updated_at': kw.get('created_at'),
'created_at': kw.get('updated_at')}
if fields is not None:
node = {key: value for key, value in node.items() if key in fields}
return type('node', (object,), node)()


def get_test_port(**kw):


+ 1
- 1
nova/virt/ironic/driver.py View File

@@ -703,7 +703,7 @@ class IronicDriver(virt_driver.ComputeDriver):
instances = objects.InstanceList.get_uuids_by_host(ctxt, CONF.host)
node_cache = {}

for node in self._get_node_list(detail=True, limit=0):
for node in self._get_node_list(fields=_NODE_FIELDS, limit=0):
# NOTE(jroll): we always manage the nodes for instances we manage
if node.instance_uuid in instances:
node_cache[node.uuid] = node


Loading…
Cancel
Save