~launchpad-pqm/launchpad/devel

10637.3.7 by Guilherme Salgado
merge devel
1
#!/usr/bin/python -S
8687.15.9 by Karl Fogel
Add the copyright header block to more files (everything under database/).
2
#
3
# Copyright 2009 Canonical Ltd.  This software is licensed under the
4
# GNU Affero General Public License version 3 (see the file LICENSE).
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
5
6
"""Remove the broken Slony-I information from database populated by
7
pg_restore(1).
8
9
When you dump a database using pg_dump(1), the Slony-I install is dumped
10
too. After restoring this dump, you have a non-functional Slony-I
11
installation. If you are recovering the database for disaster recovery
12
purposes, you can keep the current install by repairing it using the
13
slonik(1) command REPAIR CONFIG. In other cases, you need to remove
14
Slony-I from the database (eg. building a staging database, we need
15
to install replication fresh.). This script does this procedure.
16
"""
17
18
__metaclass__ = type
19
__all__ = []
20
21
import _pythonpath
22
23
from optparse import OptionParser
24
import sys
25
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
26
import psycopg2
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
27
28
from canonical.config import config
7178.4.2 by Stuart Bishop
Fix command line argument handling
29
from canonical.database.postgresql import ConnectionString
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
30
from canonical.database.sqlbase import (
31
    connect, quote, ISOLATION_LEVEL_AUTOCOMMIT)
7178.4.2 by Stuart Bishop
Fix command line argument handling
32
from canonical.launchpad.scripts import db_options, logger_options, logger
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
33
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
34
import replication.helpers
35
36
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
37
def main():
38
    parser = OptionParser()
39
    db_options(parser)
40
    logger_options(parser)
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
41
42
    parser.set_defaults(dbuser='slony')
43
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
44
    options, args = parser.parse_args()
45
7178.4.2 by Stuart Bishop
Fix command line argument handling
46
    log = logger(options)
47
13879.1.6 by William Grant
Some more that I missed.
48
    con = connect(isolation=ISOLATION_LEVEL_AUTOCOMMIT)
7178.4.2 by Stuart Bishop
Fix command line argument handling
49
50
    if not replication.helpers.slony_installed(con):
51
        log.info("Slony-I not installed. Nothing to do.")
52
        return 0
53
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
54
    if not repair_with_slonik(log, options, con):
55
        repair_with_drop_schema(log, con)
56
57
    return 0
58
59
60
def repair_with_slonik(log, options, con):
61
    """Attempt to uninstall Slony-I via 'UNINSTALL NODE' per best practice.
62
63
    Returns True on success, False if unable to do so for any reason.
64
    """
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
65
    cur = con.cursor()
66
67
    # Determine the node id the database thinks it is.
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
68
    try:
69
        cmd = "SELECT %s.getlocalnodeid(%s)" % (
70
            replication.helpers.CLUSTER_NAMESPACE,
71
            quote(replication.helpers.CLUSTER_NAMESPACE))
72
        cur.execute(cmd)
73
        node_id = cur.fetchone()[0]
74
        log.debug("Node Id is %d" % node_id)
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
75
76
        # Get a list of set ids in the database.
77
        cur.execute(
78
            "SELECT DISTINCT set_id FROM %s.sl_set"
79
            % replication.helpers.CLUSTER_NAMESPACE)
80
        set_ids = set(row[0] for row in cur.fetchall())
81
        log.debug("Set Ids are %s" % repr(set_ids))
82
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
83
    except psycopg2.InternalError:
84
        # Not enough information to determine node id. Possibly
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
85
        # this is an empty database.
86
        log.debug('Broken or no Slony-I install.')
87
        return False
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
88
7675.395.43 by Stuart Bishop
Update replication scripts to cope with recent ro mode changes
89
    connection_string = ConnectionString(config.database.rw_main_master)
7178.4.2 by Stuart Bishop
Fix command line argument handling
90
    if options.dbname:
91
        connection_string.dbname = options.dbname
92
    if options.dbuser:
93
        connection_string.user = options.dbuser
94
    if options.dbhost:
95
        connection_string.host = options.dbhost
96
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
97
    script = [
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
98
        "cluster name = %s;" % replication.helpers.CLUSTERNAME,
99
        "node %d admin conninfo = '%s';" % (node_id, connection_string),
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
100
        ]
101
    for set_id in set_ids:
102
        script.append(
103
            "repair config (set id=%d, event node=%d, execute only on=%d);"
104
            % (set_id, node_id, node_id))
105
    script.append("uninstall node (id=%d);" % node_id)
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
106
    for line in script:
107
        log.debug(line)
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
108
    script = '\n'.join(script)
109
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
110
    return replication.helpers.execute_slonik(
111
        script, auto_preamble=False, exit_on_fail=False)
112
113
114
def repair_with_drop_schema(log, con):
115
    """
116
    Just drop the _sl schema as it is 'good enough' with Slony-I 1.2.
117
118
    This mechanism fails with Slony added primary keys, but we don't
119
    do that.
120
    """
9795.4.11 by Stuart Bishop
Nicer message
121
    log.info('Fallback mode - dropping _sl schema.')
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
122
    cur = con.cursor()
123
    cur.execute("DROP SCHEMA _sl CASCADE")
124
    return True
125
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
126
127
if __name__ == '__main__':
128
    sys.exit(main())