From 59439059ed818eb8476a8c61683a02770fe9f821 Mon Sep 17 00:00:00 2001 From: Cedric LECOMTE Date: Wed, 30 Mar 2016 15:18:22 +0000 Subject: [PATCH] Archive instance_actions and instance_actions_event This try to handle the soft-delete of instance_actions and instance_actions_event before the archive of deleted rows. So in this way theses tables will be archived like others. Change-Id: Ia0fe130a35a6c9bb16a940f3f4cea6b1aaee9668 Partial-Bug: #1183523 --- nova/db/sqlalchemy/api.py | 29 ++++++++++++++++++++++++ nova/tests/functional/db/test_archive.py | 12 +++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index fd983861a946..2936cd2d3ebd 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -6470,6 +6470,35 @@ def _archive_deleted_rows_for_table(tablename, max_rows): # database's limit of maximum parameter in one SQL statement. deleted_column = table.c.deleted columns = [c.name for c in table.c] + + # NOTE(clecomte): Tables instance_actions and instances_actions_events + # have to be manage differently so we soft-delete them here to let + # the archive work the same for all tables + if tablename == "instance_actions": + instances = models.BASE.metadata.tables["instances"] + deleted_instances = sql.select([instances.c.uuid]).\ + where(instances.c.deleted != instances.c.deleted.default.arg) + update_statement = table.update().values(deleted=table.c.id).\ + where(table.c.instance_uuid.in_(deleted_instances)) + + conn.execute(update_statement) + + elif tablename == "instance_actions_events": + # NOTE(clecomte): we have to grab all the relation from + # instances because instance_actions_events rely on + # action_id and not uuid + instances = models.BASE.metadata.tables["instances"] + instance_actions = models.BASE.metadata.tables["instance_actions"] + deleted_instances = sql.select([instances.c.uuid]).\ + where(instances.c.deleted != instances.c.deleted.default.arg) + deleted_actions = sql.select([instance_actions.c.id]).\ + where(instance_actions.c.instance_uuid.in_(deleted_instances)) + + update_statement = table.update().values(deleted=table.c.id).\ + where(table.c.action_id.in_(deleted_actions)) + + conn.execute(update_statement) + insert = shadow_table.insert(inline=True).\ from_select(columns, sql.select([table], diff --git a/nova/tests/functional/db/test_archive.py b/nova/tests/functional/db/test_archive.py index 8876676e8696..8d482c42b7c2 100644 --- a/nova/tests/functional/db/test_archive.py +++ b/nova/tests/functional/db/test_archive.py @@ -96,9 +96,9 @@ class TestDatabaseArchive(test_servers.ServersTestBase): self.assertIn('instance_system_metadata', results) self.assertEqual(len(instance.system_metadata), results['instance_system_metadata']) - # FIXME(mriedem): we fail to archive instances because of a fkey - # referential constraint error with instance_actions not being deleted - self.assertNotIn('instances', results) - # FIXME(mriedem): instance_actions aren't soft deleted so they aren't - # archived, which we need to fix. - self.assertNotIn('instance_actions', results) + # Verify that instances rows are dropped + self.assertIn('instances', results) + # Verify that instance_actions and actions_event are dropped + # by the archive + self.assertIn('instance_actions', results) + self.assertIn('instance_actions_events', results)