Skip to content

Commit

Permalink
Update resources once in update_available_resource
Browse files Browse the repository at this point in the history
This change ensures that resources are updated only once per
update_available_resource() call.

Compute resources were previously updated during host
object initialization and at the end of
update_available_resource(). It could cause inconsistencies
in resource tracking between compute host and DB for couple
of second when final _update() at the end of
update_available_resource() is being called.

For example: nova-api shows that host uses 10GB of RAM, but
in fact its 12GB because DB doesn't have resources that belongs
to shutdown instance.

Because of that fact nova-scheduler (CachingScheduler) could
choose (based on imcomplete information) host which is already full.

For more informations please see realted bug: #1729621

Change-Id: I120a98cc4c11772f24099081ef3ac44a50daf71d
Closes-Bug: #1729621
  • Loading branch information
Maciej Józefczyk authored and Eric Fried committed Aug 6, 2018
1 parent f9ad40d commit c9b74bc
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 6 deletions.
3 changes: 0 additions & 3 deletions nova/compute/resource_tracker.py
Expand Up @@ -561,7 +561,6 @@ def _init_compute_node(self, context, resources):
cn = self.compute_nodes[nodename]
self._copy_resources(cn, resources)
self._setup_pci_tracker(context, cn, resources)
self._update(context, cn)
return

# now try to get the compute node record from the
Expand All @@ -571,7 +570,6 @@ def _init_compute_node(self, context, resources):
self.compute_nodes[nodename] = cn
self._copy_resources(cn, resources)
self._setup_pci_tracker(context, cn, resources)
self._update(context, cn)
return

if self._check_for_nodes_rebalance(context, resources, nodename):
Expand All @@ -590,7 +588,6 @@ def _init_compute_node(self, context, resources):
{'host': self.host, 'node': nodename, 'uuid': cn.uuid})

self._setup_pci_tracker(context, cn, resources)
self._update(context, cn)

def _setup_pci_tracker(self, context, compute_node, resources):
if not self.pci_tracker:
Expand Down
14 changes: 11 additions & 3 deletions nova/tests/unit/compute/test_resource_tracker.py
Expand Up @@ -573,6 +573,7 @@ def test_no_instances_no_migrations_no_reserved(self, get_mock, migr_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
Expand Down Expand Up @@ -613,6 +614,7 @@ def test_no_instances_no_migrations_reserved_disk_ram_and_cpu(
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.compute.utils.is_volume_backed_instance')
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
Expand Down Expand Up @@ -662,6 +664,7 @@ def test_some_instances_no_migrations(self, get_mock, migr_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
Expand Down Expand Up @@ -725,6 +728,7 @@ def test_orphaned_instances_no_migrations(self, get_mock, migr_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
Expand Down Expand Up @@ -787,6 +791,7 @@ def test_no_instances_source_migration(self, get_mock, get_inst_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
Expand Down Expand Up @@ -846,6 +851,7 @@ def test_no_instances_dest_migration(self, get_mock, get_inst_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
return_value=objects.InstancePCIRequests(requests=[]))
Expand Down Expand Up @@ -902,6 +908,7 @@ def test_no_instances_dest_evacuation(self, get_mock, get_inst_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()

@mock.patch('nova.compute.utils.is_volume_backed_instance')
@mock.patch('nova.objects.InstancePCIRequests.get_by_instance',
Expand Down Expand Up @@ -973,6 +980,7 @@ def test_some_instances_source_and_dest_migration(self, get_mock,
actual_resources = update_mock.call_args[0][1]
self.assertTrue(obj_base.obj_equal_prims(expected_resources,
actual_resources))
update_mock.assert_called_once()


class TestInitComputeNode(BaseTestCase):
Expand All @@ -998,7 +1006,7 @@ def test_no_op_init_compute_node(self, update_mock, get_mock, service_mock,
self.assertFalse(get_mock.called)
self.assertFalse(create_mock.called)
self.assertTrue(pci_mock.called)
self.assertTrue(update_mock.called)
self.assertFalse(update_mock.called)

@mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
return_value=objects.PciDeviceList())
Expand All @@ -1022,7 +1030,7 @@ def fake_get_node(_ctx, host, node):
get_mock.assert_called_once_with(mock.sentinel.ctx, _HOSTNAME,
_NODENAME)
self.assertFalse(create_mock.called)
self.assertTrue(update_mock.called)
self.assertFalse(update_mock.called)

@mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
@mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
Expand Down Expand Up @@ -1187,7 +1195,7 @@ def set_cn_id():
self.assertTrue(obj_base.obj_equal_prims(expected_compute, cn))
pci_tracker_mock.assert_called_once_with(mock.sentinel.ctx,
42)
self.assertTrue(update_mock.called)
self.assertFalse(update_mock.called)

@mock.patch('nova.objects.ComputeNodeList.get_by_hypervisor')
@mock.patch('nova.objects.PciDeviceList.get_by_compute_node',
Expand Down

0 comments on commit c9b74bc

Please sign in to comment.