placement-status: check only consumers in allocation table

Initially, _check_incomplete_consumers was intended to find the case
when consumers are mentioned in allocation but do not exist in the
consumer table. Due to a bug it's possible to have rows in the
consumer table those are not in the allocation table. The second case
it seems was not expected and it can be tricky to automate a cleanup
with zero touch upgrade.

This patch modifies the check such way it counts only consumers
presented in the allocation table.

Related-bug: #1780799
Change-Id: I569043dd9f1c964faf7d4fcbb901a93f9569bf3d
This commit is contained in:
Andrey Volkov 2020-11-17 11:19:44 +03:00 committed by Stephen Finucane
parent 3c51c6413b
commit 3253e2efc0
2 changed files with 19 additions and 7 deletions

View File

@ -59,13 +59,16 @@ class Checks(upgradecheck.UpgradeCommands):
@db_api.placement_context_manager.reader
def _count_missing_consumers(self, ctxt):
# Count the total number of consumers.
num_consumers = ctxt.session.query(models.Consumer).count()
# Count the total number of unique consumers in the allocations table.
num_alloc_consumers = ctxt.session.query(
models.Allocation.consumer_id).group_by(
models.Allocation.consumer_id).count()
return num_alloc_consumers - num_consumers
allocation = models.Allocation.__table__
consumer = models.Consumer.__table__
return ctxt.session.execute(
sa.select([sa.func.count(
sa.distinct(allocation.c.consumer_id))])
.select_from(
allocation.outerjoin(
consumer,
allocation.c.consumer_id == consumer.c.uuid))
.where(consumer.c.id.is_(None))).fetchone()[0]
def _check_incomplete_consumers(self):
"""Allocations created with microversion<1.8 prior to Rocky will not

View File

@ -99,12 +99,21 @@ class CreateIncompleteAllocationsMixin(object):
"""Mixin for test setup to create some allocations with missing consumers
"""
@db_api.placement_context_manager.writer
def _create_leftover_consumer(self, ctx):
ins_stmt = CONSUMER_TBL.insert().values(
uuid=uuids.unknown_consumer,
project_id=999,
user_id=999)
ctx.session.execute(ins_stmt)
@db_api.placement_context_manager.writer
def _create_incomplete_allocations(self, ctx, num_of_consumer_allocs=1):
# Create some allocations with consumers that don't exist in the
# consumers table to represent old allocations that we expect to be
# "cleaned up" with consumers table records that point to the sentinel
# project/user records.
self._create_leftover_consumer(ctx)
c1_missing_uuid = uuids.c1_missing
c2_missing_uuid = uuids.c2_missing
c3_missing_uuid = uuids.c3_missing