From 7c2961b489cf4bcb255fc707d286af06c77fbc74 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Jaillet Date: Fri, 7 Apr 2017 16:03:11 +0200 Subject: [PATCH] command: add a delete_tenant command (#15636) --- wcs/ctl/check_hobos.py | 8 +++- wcs/ctl/delete_tenant.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 wcs/ctl/delete_tenant.py diff --git a/wcs/ctl/check_hobos.py b/wcs/ctl/check_hobos.py index a426d1c0..58d651c8 100644 --- a/wcs/ctl/check_hobos.py +++ b/wcs/ctl/check_hobos.py @@ -422,7 +422,13 @@ class CmdCheckHobos(Command): cur.execute('''CREATE DATABASE %s''' % database_name) except psycopg2.Error as e: if e.pgcode == psycopg2.errorcodes.DUPLICATE_DATABASE: - new_database = False + cur.execute("SELECT table_name FROM information_schema.tables \ + WHERE table_schema='public' AND \ + table_type='BASE TABLE'") + tables_names = [x[0] for x in cur.fetchall()] + + if 'wcs_meta' in tables_names : + new_database = False else: print >> sys.stderr, 'failed to create database (%s)' % \ psycopg2.errorcodes.lookup(e.pgcode) diff --git a/wcs/ctl/delete_tenant.py b/wcs/ctl/delete_tenant.py new file mode 100644 index 00000000..7fd644d0 --- /dev/null +++ b/wcs/ctl/delete_tenant.py @@ -0,0 +1,99 @@ +#w.c.s. - web application for online forms +# Copyright (C) 2005-2014 Entr'ouvert +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +import os +import sys +import psycopg2 +import psycopg2.errorcodes +from datetime import datetime +from shutil import rmtree + +from qommon.ctl import Command, make_option + + +class CmdDeleteTenant(Command): + name = 'delete_tenant' + + def __init__(self): + Command.__init__(self, [ + make_option('--force-drop', action='store_true', default=False), + ]) + + def execute(self, base_options, sub_options, args): + import publisher + + publisher.WcsPublisher.configure(self.config) + pub = publisher.WcsPublisher.create_publisher( + register_cron=False, register_tld_names=False) + + hostname = args[0] + pub.app_dir = os.path.join(pub.app_dir, hostname) + pub.set_config() + + postgresql_cfg = {} + for k, v in pub.cfg['postgresql'].items(): + if v and isinstance(v, basestring): + postgresql_cfg[k] = v + + createdb_cfg = pub.cfg['postgresql'].get('createdb-connection-params') + if not createdb_cfg: + createdb_cfg = postgresql_cfg + + try: + pgconn = psycopg2.connect(**createdb_cfg) + except psycopg2.Error as e: + print >> sys.stderr, 'failed to connect to postgresql (%s)' % \ + psycopg2.errorcodes.lookup(e.pgcode) + return + + pgconn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) + cur = pgconn.cursor() + try: + cur.execute("SELECT table_name FROM information_schema.tables \ + WHERE table_schema='public' AND \ + table_type='BASE TABLE'") + + tables_names = [x[0] for x in cur.fetchall()] + + if sub_options.force_drop: + for table_name in tables_names: + cur.execute('DROP TABLE %s CASCADE' % table_name) + rmtree(pub.app_dir) + + else: + deletion_date = datetime.now().strftime('%Y%m%d_%H%M%S_%f') + + for table_name in tables_names: + cur.execute('ALTER TABLE %s RENAME TO removed_%s_%s' % \ + (table_name, deletion_date, table_name)) + os.rename(pub.app_dir, pub.app_dir + '_removed_%s.invalid' % \ + deletion_date) + except psycopg2.Error as e: + if e.pgcode == psycopg2.errorcodes.DUPLICATE_TABLE: + # when tables names are too long, postgresql truncates, which + # can create some duplicates + temp_date = datetime.now().strftime('%Y%m%d_%H%M%S_%f') + cur.execute('ALTER TABLE %s RENAME TO removed_%s_%s' % \ + (table_name, temp_date, table_name)) + else: + print >> sys.stderr, 'failed to alter database %s : (%s)' % \ + (createdb_cfg['database'], psycopg2.errorcodes.lookup(e.pgcode)) + return + + cur.close() + + +CmdDeleteTenant.register() -- 2.11.0