~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
14606.3.5 by William Grant
Reformat
21
import _pythonpath
22
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
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
14605.1.1 by Curtis Hovey
Moved canonical.config to lp.services.
28
from lp.services.config import config
14606.3.1 by William Grant
Merge canonical.database into lp.services.database.
29
from lp.services.database.postgresql import ConnectionString
30
from lp.services.database.sqlbase import (
31
    connect,
32
    ISOLATION_LEVEL_AUTOCOMMIT,
33
    quote,
34
    )
35
from lp.services.scripts import (
36
    db_options,
37
    logger,
38
    logger_options,
39
    )
14606.3.5 by William Grant
Reformat
40
import replication.helpers
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
41
42
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
43
def main():
44
    parser = OptionParser()
45
    db_options(parser)
46
    logger_options(parser)
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
47
48
    parser.set_defaults(dbuser='slony')
49
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
50
    options, args = parser.parse_args()
51
7178.4.2 by Stuart Bishop
Fix command line argument handling
52
    log = logger(options)
53
13879.1.6 by William Grant
Some more that I missed.
54
    con = connect(isolation=ISOLATION_LEVEL_AUTOCOMMIT)
7178.4.2 by Stuart Bishop
Fix command line argument handling
55
56
    if not replication.helpers.slony_installed(con):
57
        log.info("Slony-I not installed. Nothing to do.")
58
        return 0
59
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
60
    if not repair_with_slonik(log, options, con):
61
        repair_with_drop_schema(log, con)
62
63
    return 0
64
65
66
def repair_with_slonik(log, options, con):
67
    """Attempt to uninstall Slony-I via 'UNINSTALL NODE' per best practice.
68
69
    Returns True on success, False if unable to do so for any reason.
70
    """
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
71
    cur = con.cursor()
72
73
    # Determine the node id the database thinks it is.
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
74
    try:
75
        cmd = "SELECT %s.getlocalnodeid(%s)" % (
76
            replication.helpers.CLUSTER_NAMESPACE,
77
            quote(replication.helpers.CLUSTER_NAMESPACE))
78
        cur.execute(cmd)
79
        node_id = cur.fetchone()[0]
80
        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
81
82
        # Get a list of set ids in the database.
83
        cur.execute(
84
            "SELECT DISTINCT set_id FROM %s.sl_set"
85
            % replication.helpers.CLUSTER_NAMESPACE)
86
        set_ids = set(row[0] for row in cur.fetchall())
87
        log.debug("Set Ids are %s" % repr(set_ids))
88
7675.85.2 by Jonathan Lange
Undo revision generated by step 2 of process.
89
    except psycopg2.InternalError:
90
        # 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
91
        # this is an empty database.
92
        log.debug('Broken or no Slony-I install.')
93
        return False
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
94
7675.395.43 by Stuart Bishop
Update replication scripts to cope with recent ro mode changes
95
    connection_string = ConnectionString(config.database.rw_main_master)
7178.4.2 by Stuart Bishop
Fix command line argument handling
96
    if options.dbname:
97
        connection_string.dbname = options.dbname
98
    if options.dbuser:
99
        connection_string.user = options.dbuser
100
    if options.dbhost:
101
        connection_string.host = options.dbhost
102
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
103
    script = [
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
104
        "cluster name = %s;" % replication.helpers.CLUSTERNAME,
105
        "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
106
        ]
107
    for set_id in set_ids:
108
        script.append(
109
            "repair config (set id=%d, event node=%d, execute only on=%d);"
110
            % (set_id, node_id, node_id))
111
    script.append("uninstall node (id=%d);" % node_id)
7178.4.3 by Stuart Bishop
Don't hardcode slony cluster name in script
112
    for line in script:
113
        log.debug(line)
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
114
    script = '\n'.join(script)
115
9795.4.9 by Stuart Bishop
Make repair-restored-db.py more robust and fix database restore ordering for staging and dogfood
116
    return replication.helpers.execute_slonik(
117
        script, auto_preamble=False, exit_on_fail=False)
118
119
120
def repair_with_drop_schema(log, con):
121
    """
122
    Just drop the _sl schema as it is 'good enough' with Slony-I 1.2.
123
124
    This mechanism fails with Slony added primary keys, but we don't
125
    do that.
126
    """
9795.4.11 by Stuart Bishop
Nicer message
127
    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
128
    cur = con.cursor()
129
    cur.execute("DROP SCHEMA _sl CASCADE")
130
    return True
131
7178.4.1 by Stuart Bishop
Script to repair a db built from a slony node dump
132
133
if __name__ == '__main__':
134
    sys.exit(main())