ProviderTree.has_inventory_changed for new fields

The has_inventory_changed method of ProviderTree is deliberately not
automatically reporting True if the incoming record is "sparse" - that
is, for a given resource class, it only contains a subset of the keys in
the existing record.  For example, the caller may want to know if the
total has changed, but doesn't care about the other fields, so may ask:

ptree.has_inventory_changed(uuid, {'VCPU': {'total': 3}, ...})

...and has_inventory_changed will only compare the 'total' field.

However, we were doing the same if the incoming record contained fields
that were *not* in the existing record.  For example, if the current
inventory was:

{ 'VCPU': {
      'total': 8,
      'min_unit': 1,
      'max_unit': 8,
      'step_size': 1,
  }
}

...and the new inventory was:

{ 'VCPU': {
      'total': 8,
      'min_unit': 1,
      'max_unit': 8,
      'step_size': 1,
      'allocation_ratio': 16.0,  # <== new
      'reserved': 1,             # <== new
  }
}

...the presence of the new fields was *not* enough to trigger a True
response.

This is problematic because we currently expect to be able to add
specifically these fields - allocation_ratio and reserved - to an
inventory record if they are not present (see [1]).

With this change set, we add a condition to automatically return True
(inventory *has* changed) whenever the incoming (new) record contains
fields absent from the existing record.

[1] 050e9202f6/nova/compute/resource_tracker.py (L83-L125)

Partial-Bug: #1771728
Change-Id: I80dd6d08322bcedc8535f04baf2e96473f5e3aeb
This commit is contained in:
Eric Fried 2018-05-17 14:07:15 -05:00
parent 549e5a2226
commit b864d08eaf
2 changed files with 15 additions and 4 deletions

View File

@ -128,12 +128,17 @@ class _Provider(object):
return True
for key, cur_rec in cur.items():
new_rec = new[key]
# If the new record contains new fields (e.g. we're adding on
# `reserved` or `allocation_ratio`) we want to make sure to pick
# them up
if set(new_rec) - set(cur_rec):
return True
for rec_key, cur_val in cur_rec.items():
if rec_key not in new_rec:
# Deliberately don't want to compare missing keys in the
# inventory record. For instance, we will be passing in
# fields like allocation_ratio in the current dict but the
# resource tracker may only pass in the total field. We
# *new* inventory record. For instance, we will be passing
# in fields like allocation_ratio in the current dict but
# the resource tracker may only pass in the total field. We
# want to return that inventory didn't change when the
# total field values are the same even if the
# allocation_ratio field is missing from the new record.

View File

@ -440,7 +440,6 @@ class TestProviderTree(test.NoDBTestCase):
cn_inv = {
'VCPU': {
'total': 8,
'reserved': 0,
'min_unit': 1,
'max_unit': 8,
'step_size': 1,
@ -500,6 +499,13 @@ class TestProviderTree(test.NoDBTestCase):
self.assertTrue(pt.update_inventory(cn.uuid, cn_inv,
generation=rp_gen))
# ...but *adding* a key in the new record *should* result in changes
# being recorded
cn_inv['VCPU']['reserved'] = 0
self.assertTrue(pt.has_inventory_changed(cn.uuid, cn_inv))
self.assertTrue(pt.update_inventory(cn.uuid, cn_inv,
generation=rp_gen))
def test_have_traits_changed_no_existing_rp(self):
pt = self._pt_with_cns()
self.assertRaises(