]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Provide a way to clean up soft deleted data
authorLiang Chen <cbjchen@cn.ibm.com>
Fri, 26 Jul 2013 13:39:09 +0000 (21:39 +0800)
committerLiang Chen <cbjchen@cn.ibm.com>
Thu, 8 Aug 2013 15:39:13 +0000 (23:39 +0800)
Add a purge_deleted command to heat-manage. The command takes an
'age' argument, and removes all database records that have been soft
deleted for more than 'age' days. Default to 90.

blueprint event-persistence

Change-Id: I8a62108a907b4e709c91a93a1f7db6c702cec6b5

heat/cmd/manage.py
heat/db/sqlalchemy/api.py
heat/db/utils.py

index 9834f506bf07fdb465ced58d1f1cd61736f5d2c1..d3852fb4b5dd3f4199d6876f7b30fbe749340850 100644 (file)
@@ -24,6 +24,7 @@ from oslo.config import cfg
 
 from heat.db import api as db_api
 from heat.db import migration
+from heat.db import utils
 from heat.openstack.common import log
 from heat import version
 
@@ -44,6 +45,13 @@ def do_db_sync():
     migration.db_sync(CONF.command.version)
 
 
+def purge_deleted():
+    """
+    Remove database records that have been previously soft deleted
+    """
+    utils.purge_deleted(CONF.command.age)
+
+
 def add_command_parsers(subparsers):
     parser = subparsers.add_parser('db_version')
     parser.set_defaults(func=do_db_version)
@@ -53,6 +61,9 @@ def add_command_parsers(subparsers):
     parser.add_argument('version', nargs='?')
     parser.add_argument('current_version', nargs='?')
 
+    parser = subparsers.add_parser('purge_deleted')
+    parser.set_defaults(func=purge_deleted)
+    parser.add_argument('age', nargs='?')
 
 command_opt = cfg.SubCommandOpt('command',
                                 title='Commands',
index dd1b91c9bfcaf0a569551ba3336a2bb932bd79a1..aa4f40494631ad3b01cb61bb1103efad5b4a4a25 100644 (file)
 #    under the License.
 
 '''Implementation of SQLAlchemy backend.'''
+from datetime import datetime
+from datetime import timedelta
+
+import sqlalchemy
 from sqlalchemy.orm.session import Session
 
+from heat.openstack.common.gettextutils import _
+
 from heat.common import crypt
 from heat.common import exception
 from heat.db.sqlalchemy import models
+from heat.db.sqlalchemy.session import get_engine
 from heat.db.sqlalchemy.session import get_session
 
 
@@ -388,3 +395,42 @@ def watch_data_delete(context, watch_name):
     for d in ds:
         session.delete(d)
     session.flush()
+
+
+def purge_deleted(age):
+    if age is not None:
+        try:
+            age = int(age)
+        except ValueError:
+            raise exception.Error(_("age should be an integer"))
+        if age < 0:
+            raise exception.Error(_("age should be a positive integer"))
+    else:
+        age = 90
+
+    time_line = datetime.now() - timedelta(days=age)
+    engine = get_engine()
+    meta = sqlalchemy.MetaData()
+    meta.bind = engine
+
+    stack = sqlalchemy.Table('stack', meta, autoload=True)
+    event = sqlalchemy.Table('event', meta, autoload=True)
+    raw_template = sqlalchemy.Table('raw_template', meta, autoload=True)
+    user_creds = sqlalchemy.Table('user_creds', meta, autoload=True)
+
+    stmt = sqlalchemy.select([stack.c.id,
+                              stack.c.raw_template_id,
+                              stack.c.user_creds_id]).\
+        where(stack.c.deleted_at < time_line)
+    deleted_stacks = engine.execute(stmt)
+
+    for s in deleted_stacks:
+        event_del = event.delete().where(event.c.stack_id == s[0])
+        engine.execute(event_del)
+        stack_del = stack.delete().where(stack.c.id == s[0])
+        engine.execute(stack_del)
+        raw_template_del = raw_template.delete().\
+            where(raw_template.c.id == s[1])
+        engine.execute(raw_template_del)
+        user_creds_del = user_creds.delete().where(user_creds.c.id == s[2])
+        engine.execute(user_creds_del)
index d494b9271fd808e759b6ce9b9a317642c8553a53..245042611a192364651fafb7ed847754a1def4d7 100644 (file)
@@ -39,3 +39,11 @@ class LazyPluggable(object):
     def __getattr__(self, key):
         backend = self.__get_backend()
         return getattr(backend, key)
+
+
+IMPL = LazyPluggable('db_backend',
+                     sqlalchemy='heat.db.sqlalchemy.api')
+
+
+def purge_deleted(age):
+    IMPL.purge_deleted(age)