Use deepcopy when process filters in db api
In db API when we process filters, we didn't use deepcopy. In cases of "tags" and "not-tags" we used pop to get the first tag, filtered out results, and then joined with other tags for later filtering. When we did pop(), the original value was deleted, the key "tags"/"not-tags" remains. In the cell scenario, both single cell(we will query cell0 and the other cell) and multicell, as we have to query all the cells in a loop and the tags list in the filter will keep popping, this will lead to either a HTTP 500 error(popping from an empty list) or incorrect result(when number of tags in the list is larger than cell number, no HTTP 500 will show, but the filter results for each cell will be different as each loop will pop one tag). closes-bug: #1682693 Conflicts: nova/tests/functional/regressions/test_bug_1682693.py NOTE(mriedem): The conflict on the functional regression test is due to I65bdfadd406368775c794ee4d8a16302a8a134bc not being backported to Newton. That was not backported simply because it relies on too many fixtures to stub out a real cells environment that trying to get it to work in Newton is not worth it. This fix is still unit tested which is sufficient. Change-Id: Ia2738dd0c7d1842b68c83d0a9e75e26b2f8d492a (cherry picked from commitc4820305d2
) (cherry picked from commit01ffbdf8be
)
This commit is contained in:
parent
a96092d0e4
commit
6d1ce4cf5c
|
@ -2114,7 +2114,7 @@ def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None,
|
|||
|
||||
# Make a copy of the filters dictionary to use going forward, as we'll
|
||||
# be modifying it and we shouldn't affect the caller's use of it.
|
||||
filters = filters.copy()
|
||||
filters = copy.deepcopy(filters)
|
||||
|
||||
if 'changes-since' in filters:
|
||||
changes_since = timeutils.normalize_time(filters['changes-since'])
|
||||
|
|
|
@ -10241,6 +10241,32 @@ class TestInstanceTagsFiltering(test.TestCase):
|
|||
self._assertEqualInstanceUUIDs([uuids[0], uuids[1], uuids[3], uuids[4],
|
||||
uuids[6], uuids[7]], result)
|
||||
|
||||
def test_instance_get_all_by_filters_not_tags_multiple_cells(self):
|
||||
"""Test added for bug 1682693.
|
||||
|
||||
In cells v2 scenario, db.instance_get_all_by_filters() will
|
||||
be called multiple times to search across all cells. This
|
||||
test tests that filters for all cells remain the same in the
|
||||
loop.
|
||||
"""
|
||||
uuids = self._create_instances(8)
|
||||
|
||||
db.instance_tag_set(self.ctxt, uuids[0], [u't1'])
|
||||
db.instance_tag_set(self.ctxt, uuids[1], [u't2'])
|
||||
db.instance_tag_set(self.ctxt, uuids[2], [u't1', u't2'])
|
||||
db.instance_tag_set(self.ctxt, uuids[3], [u't2', u't3'])
|
||||
db.instance_tag_set(self.ctxt, uuids[4], [u't3'])
|
||||
db.instance_tag_set(self.ctxt, uuids[5], [u't1', u't2', u't3'])
|
||||
db.instance_tag_set(self.ctxt, uuids[6], [u't3', u't4'])
|
||||
db.instance_tag_set(self.ctxt, uuids[7], [])
|
||||
|
||||
filters = {'not-tags': [u't1', u't2']}
|
||||
|
||||
result = db.instance_get_all_by_filters(self.ctxt, filters)
|
||||
|
||||
self._assertEqualInstanceUUIDs([uuids[0], uuids[1], uuids[3], uuids[4],
|
||||
uuids[6], uuids[7]], result)
|
||||
|
||||
def test_instance_get_all_by_filters_not_tags_any(self):
|
||||
uuids = self._create_instances(8)
|
||||
|
||||
|
|
Loading…
Reference in New Issue