Fix db purge for volume_types FK constraint
db purge command raises FK constraint while purging volume_types and volume_type_projects deleted rows. Delete volume_type_projects records before deleting volume_types to solve this issue. Change-Id: I46d3c7559c58e979e6227825ed0b2e21158415c2 Closes-Bug: #1589806
This commit is contained in:
parent
1bc0da2034
commit
e9b928d669
|
@ -4453,9 +4453,12 @@ def purge_deleted_rows(context, age_in_days):
|
|||
and hasattr(model_class, "deleted"):
|
||||
tables.append(model_class.__tablename__)
|
||||
|
||||
# Reorder the list so the volumes table is last to avoid FK constraints
|
||||
tables.remove("volumes")
|
||||
tables.append("volumes")
|
||||
# Reorder the list so the volumes and volume_types tables are last
|
||||
# to avoid FK constraints
|
||||
for table in ("volume_types", "volumes"):
|
||||
tables.remove(table)
|
||||
tables.append(table)
|
||||
|
||||
for table in tables:
|
||||
t = Table(table, metadata, autoload=True)
|
||||
LOG.info(_LI('Purging deleted rows older than age=%(age)d days '
|
||||
|
|
|
@ -44,6 +44,13 @@ class PurgeDeletedTest(test.TestCase):
|
|||
# The volume_metadata table has a FK of volume_id
|
||||
self.vm = sqlalchemyutils.get_table(
|
||||
self.engine, "volume_metadata")
|
||||
|
||||
self.vol_types = sqlalchemyutils.get_table(
|
||||
self.engine, "volume_types")
|
||||
# The volume_type_projects table has a FK of volume_type_id
|
||||
self.vol_type_proj = sqlalchemyutils.get_table(
|
||||
self.engine, "volume_type_projects")
|
||||
|
||||
self.uuidstrs = []
|
||||
for unused in range(6):
|
||||
self.uuidstrs.append(uuid.uuid4().hex)
|
||||
|
@ -53,43 +60,82 @@ class PurgeDeletedTest(test.TestCase):
|
|||
self.conn.execute(ins_stmt)
|
||||
ins_stmt = self.vm.insert().values(volume_id=uuidstr)
|
||||
self.conn.execute(ins_stmt)
|
||||
|
||||
ins_stmt = self.vol_types.insert().values(id=uuidstr)
|
||||
self.conn.execute(ins_stmt)
|
||||
ins_stmt = self.vol_type_proj.insert().\
|
||||
values(volume_type_id=uuidstr)
|
||||
self.conn.execute(ins_stmt)
|
||||
|
||||
# Set 4 of them deleted, 2 are 60 days ago, 2 are 20 days ago
|
||||
old = timeutils.utcnow() - datetime.timedelta(days=20)
|
||||
older = timeutils.utcnow() - datetime.timedelta(days=60)
|
||||
make_old = self.volumes.update().\
|
||||
|
||||
make_vol_old = self.volumes.update().\
|
||||
where(self.volumes.c.id.in_(self.uuidstrs[1:3]))\
|
||||
.values(deleted_at=old)
|
||||
make_older = self.volumes.update().\
|
||||
make_vol_older = self.volumes.update().\
|
||||
where(self.volumes.c.id.in_(self.uuidstrs[4:6]))\
|
||||
.values(deleted_at=older)
|
||||
make_meta_old = self.vm.update().\
|
||||
make_vol_meta_old = self.vm.update().\
|
||||
where(self.vm.c.volume_id.in_(self.uuidstrs[1:3]))\
|
||||
.values(deleted_at=old)
|
||||
make_meta_older = self.vm.update().\
|
||||
make_vol_meta_older = self.vm.update().\
|
||||
where(self.vm.c.volume_id.in_(self.uuidstrs[4:6]))\
|
||||
.values(deleted_at=older)
|
||||
self.conn.execute(make_old)
|
||||
self.conn.execute(make_older)
|
||||
self.conn.execute(make_meta_old)
|
||||
self.conn.execute(make_meta_older)
|
||||
|
||||
make_vol_types_old = self.vol_types.update().\
|
||||
where(self.vol_types.c.id.in_(self.uuidstrs[1:3]))\
|
||||
.values(deleted_at=old)
|
||||
make_vol_types_older = self.vol_types.update().\
|
||||
where(self.vol_types.c.id.in_(self.uuidstrs[4:6]))\
|
||||
.values(deleted_at=older)
|
||||
make_vol_type_proj_old = self.vol_type_proj.update().\
|
||||
where(self.vol_type_proj.c.volume_type_id.in_(self.uuidstrs[1:3]))\
|
||||
.values(deleted_at=old)
|
||||
make_vol_type_proj_older = self.vol_type_proj.update().\
|
||||
where(self.vol_type_proj.c.volume_type_id.in_(self.uuidstrs[4:6]))\
|
||||
.values(deleted_at=older)
|
||||
|
||||
self.conn.execute(make_vol_old)
|
||||
self.conn.execute(make_vol_older)
|
||||
self.conn.execute(make_vol_meta_old)
|
||||
self.conn.execute(make_vol_meta_older)
|
||||
|
||||
self.conn.execute(make_vol_types_old)
|
||||
self.conn.execute(make_vol_types_older)
|
||||
self.conn.execute(make_vol_type_proj_old)
|
||||
self.conn.execute(make_vol_type_proj_older)
|
||||
|
||||
def test_purge_deleted_rows_old(self):
|
||||
# Purge at 30 days old, should only delete 2 rows
|
||||
db.purge_deleted_rows(self.context, age_in_days=30)
|
||||
rows = self.session.query(self.volumes).count()
|
||||
meta_rows = self.session.query(self.vm).count()
|
||||
|
||||
vol_rows = self.session.query(self.volumes).count()
|
||||
vol_meta_rows = self.session.query(self.vm).count()
|
||||
vol_type_rows = self.session.query(self.vol_types).count()
|
||||
vol_type_proj_rows = self.session.query(self.vol_type_proj).count()
|
||||
|
||||
# Verify that we only deleted 2
|
||||
self.assertEqual(4, rows)
|
||||
self.assertEqual(4, meta_rows)
|
||||
self.assertEqual(4, vol_rows)
|
||||
self.assertEqual(4, vol_meta_rows)
|
||||
self.assertEqual(4, vol_type_rows)
|
||||
self.assertEqual(4, vol_type_proj_rows)
|
||||
|
||||
def test_purge_deleted_rows_older(self):
|
||||
# Purge at 10 days old now, should delete 2 more rows
|
||||
db.purge_deleted_rows(self.context, age_in_days=10)
|
||||
rows = self.session.query(self.volumes).count()
|
||||
meta_rows = self.session.query(self.vm).count()
|
||||
|
||||
vol_rows = self.session.query(self.volumes).count()
|
||||
vol_meta_rows = self.session.query(self.vm).count()
|
||||
vol_type_rows = self.session.query(self.vol_types).count()
|
||||
vol_type_proj_rows = self.session.query(self.vol_type_proj).count()
|
||||
|
||||
# Verify that we only have 2 rows now
|
||||
self.assertEqual(2, rows)
|
||||
self.assertEqual(2, meta_rows)
|
||||
self.assertEqual(2, vol_rows)
|
||||
self.assertEqual(2, vol_meta_rows)
|
||||
self.assertEqual(2, vol_type_rows)
|
||||
self.assertEqual(2, vol_type_proj_rows)
|
||||
|
||||
def test_purge_deleted_rows_bad_args(self):
|
||||
# Test with no age argument
|
||||
|
|
Loading…
Reference in New Issue