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"):
|
and hasattr(model_class, "deleted"):
|
||||||
tables.append(model_class.__tablename__)
|
tables.append(model_class.__tablename__)
|
||||||
|
|
||||||
# Reorder the list so the volumes table is last to avoid FK constraints
|
# Reorder the list so the volumes and volume_types tables are last
|
||||||
tables.remove("volumes")
|
# to avoid FK constraints
|
||||||
tables.append("volumes")
|
for table in ("volume_types", "volumes"):
|
||||||
|
tables.remove(table)
|
||||||
|
tables.append(table)
|
||||||
|
|
||||||
for table in tables:
|
for table in tables:
|
||||||
t = Table(table, metadata, autoload=True)
|
t = Table(table, metadata, autoload=True)
|
||||||
LOG.info(_LI('Purging deleted rows older than age=%(age)d days '
|
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
|
# The volume_metadata table has a FK of volume_id
|
||||||
self.vm = sqlalchemyutils.get_table(
|
self.vm = sqlalchemyutils.get_table(
|
||||||
self.engine, "volume_metadata")
|
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 = []
|
self.uuidstrs = []
|
||||||
for unused in range(6):
|
for unused in range(6):
|
||||||
self.uuidstrs.append(uuid.uuid4().hex)
|
self.uuidstrs.append(uuid.uuid4().hex)
|
||||||
@ -53,43 +60,82 @@ class PurgeDeletedTest(test.TestCase):
|
|||||||
self.conn.execute(ins_stmt)
|
self.conn.execute(ins_stmt)
|
||||||
ins_stmt = self.vm.insert().values(volume_id=uuidstr)
|
ins_stmt = self.vm.insert().values(volume_id=uuidstr)
|
||||||
self.conn.execute(ins_stmt)
|
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
|
# Set 4 of them deleted, 2 are 60 days ago, 2 are 20 days ago
|
||||||
old = timeutils.utcnow() - datetime.timedelta(days=20)
|
old = timeutils.utcnow() - datetime.timedelta(days=20)
|
||||||
older = timeutils.utcnow() - datetime.timedelta(days=60)
|
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]))\
|
where(self.volumes.c.id.in_(self.uuidstrs[1:3]))\
|
||||||
.values(deleted_at=old)
|
.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]))\
|
where(self.volumes.c.id.in_(self.uuidstrs[4:6]))\
|
||||||
.values(deleted_at=older)
|
.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]))\
|
where(self.vm.c.volume_id.in_(self.uuidstrs[1:3]))\
|
||||||
.values(deleted_at=old)
|
.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]))\
|
where(self.vm.c.volume_id.in_(self.uuidstrs[4:6]))\
|
||||||
.values(deleted_at=older)
|
.values(deleted_at=older)
|
||||||
self.conn.execute(make_old)
|
|
||||||
self.conn.execute(make_older)
|
make_vol_types_old = self.vol_types.update().\
|
||||||
self.conn.execute(make_meta_old)
|
where(self.vol_types.c.id.in_(self.uuidstrs[1:3]))\
|
||||||
self.conn.execute(make_meta_older)
|
.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):
|
def test_purge_deleted_rows_old(self):
|
||||||
# Purge at 30 days old, should only delete 2 rows
|
# Purge at 30 days old, should only delete 2 rows
|
||||||
db.purge_deleted_rows(self.context, age_in_days=30)
|
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
|
# Verify that we only deleted 2
|
||||||
self.assertEqual(4, rows)
|
self.assertEqual(4, vol_rows)
|
||||||
self.assertEqual(4, meta_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):
|
def test_purge_deleted_rows_older(self):
|
||||||
# Purge at 10 days old now, should delete 2 more rows
|
# Purge at 10 days old now, should delete 2 more rows
|
||||||
db.purge_deleted_rows(self.context, age_in_days=10)
|
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
|
# Verify that we only have 2 rows now
|
||||||
self.assertEqual(2, rows)
|
self.assertEqual(2, vol_rows)
|
||||||
self.assertEqual(2, meta_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):
|
def test_purge_deleted_rows_bad_args(self):
|
||||||
# Test with no age argument
|
# Test with no age argument
|
||||||
|
Loading…
Reference in New Issue
Block a user