From f5b6dc603c5f6f72ab35ef21ab9e35ec982e3219 Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Fri, 26 Jan 2018 14:55:34 +0000 Subject: [PATCH] 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 8bbad196a7f6a6e2ea093aeee87dfde2154c9358) --- nova/tests/unit/virt/ironic/test_driver.py | 294 +++++++++++---------- nova/tests/unit/virt/ironic/utils.py | 50 ++-- nova/virt/ironic/driver.py | 2 +- 3 files changed, 181 insertions(+), 165 deletions(-) diff --git a/nova/tests/unit/virt/ironic/test_driver.py b/nova/tests/unit/virt/ironic/test_driver.py index 51224a7a33e9..ec6c2f27f2ad 100644 --- a/nova/tests/unit/virt/ironic/test_driver.py +++ b/nova/tests/unit/virt/ironic/test_driver.py @@ -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) diff --git a/nova/tests/unit/virt/ironic/utils.py b/nova/tests/unit/virt/ironic/utils.py index d34de55b66fe..d98658e658a7 100644 --- a/nova/tests/unit/virt/ironic/utils.py +++ b/nova/tests/unit/virt/ironic/utils.py @@ -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): diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index e53cb7447bdf..d2d5e073601b 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -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