]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
DB models and migration scripts for soft delete
authorLiang Chen <cbjchen@cn.ibm.com>
Thu, 25 Jul 2013 09:45:45 +0000 (17:45 +0800)
committerLiang Chen <cbjchen@cn.ibm.com>
Tue, 6 Aug 2013 14:57:17 +0000 (22:57 +0800)
Only apply soft-delete on stack table for now. event, user_creds
and raw_template records will remain unchanged after stack
deletion, and those 'deleted' data can be cleaned up by the
purge_delete command provided in follow patch.

blueprint event-persistence

Change-Id: I173cc6037615ff252968297981c36e51cb9d3fd3

heat/db/sqlalchemy/migrate_repo/versions/022_stack_event_soft_delete.py [new file with mode: 0644]
heat/db/sqlalchemy/models.py

diff --git a/heat/db/sqlalchemy/migrate_repo/versions/022_stack_event_soft_delete.py b/heat/db/sqlalchemy/migrate_repo/versions/022_stack_event_soft_delete.py
new file mode 100644 (file)
index 0000000..7fa31af
--- /dev/null
@@ -0,0 +1,52 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import sqlalchemy
+
+
+def upgrade(migrate_engine):
+    meta = sqlalchemy.MetaData(bind=migrate_engine)
+
+    stack = sqlalchemy.Table('stack', meta, autoload=True)
+    sqlalchemy.Column('deleted_at', sqlalchemy.DateTime).create(stack)
+
+
+def downgrade(migrate_engine):
+    meta = sqlalchemy.MetaData()
+    meta.bind = migrate_engine
+
+    stack = sqlalchemy.Table('stack', meta, autoload=True)
+    event = sqlalchemy.Table('event', meta, autoload=True)
+    user_creds = sqlalchemy.Table('user_creds', meta, autoload=True)
+    raw_template = sqlalchemy.Table('raw_template', meta, autoload=True)
+
+    # Remove soft deleted data
+    not_deleted = None
+    stmt = sqlalchemy.select([stack.c.id,
+                              stack.c.raw_template_id,
+                              stack.c.user_creds_id]).\
+        where(stack.c.deleted_at != not_deleted)
+    deleted_stacks = migrate_engine.execute(stmt)
+    for s in deleted_stacks:
+        event_del = event.delete().where(event.c.stack_id == s[0])
+        migrate_engine.execute(event_del)
+        stack_del = stack.delete().where(stack.c.id == s[0])
+        migrate_engine.execute(stack_del)
+        raw_template_del = raw_template.delete().\
+            where(raw_template.c.id == s[1])
+        migrate_engine.execute(raw_template_del)
+        user_creds_del = user_creds.delete().where(user_creds.c.id == s[2])
+        migrate_engine.execute(user_creds_del)
+
+    stack.c.deleted_at.drop()
index 2928b9147c8c3f8e4fce93787644ad8ce9df7bea..2a44da7dc87a02d320adabee28e26e51283646b4 100644 (file)
@@ -137,6 +137,15 @@ class HeatBase(object):
         return local.iteritems()
 
 
+class SoftDelete(object):
+    deleted_at = sqlalchemy.Column(sqlalchemy.DateTime)
+
+    def soft_delete(self, session=None):
+        """Mark this object as deleted."""
+        self.update_and_save({'deleted_at': timeutils.utcnow()},
+                             session=session)
+
+
 class RawTemplate(BASE, HeatBase):
     """Represents an unparsed template which should be in JSON format."""
 
@@ -145,7 +154,7 @@ class RawTemplate(BASE, HeatBase):
     template = sqlalchemy.Column(Json)
 
 
-class Stack(BASE, HeatBase):
+class Stack(BASE, HeatBase, SoftDelete):
     """Represents a stack created by the heat engine."""
 
     __tablename__ = 'stack'