~launchpad-pqm/launchpad/devel

10637.3.1 by Guilherme Salgado
Use the default python version instead of a hard-coded version
1
#!/usr/bin/python
8687.15.4 by Karl Fogel
Add the copyright header block to more files; tweak format in a few files.
2
#
3
# Copyright 2009 Canonical Ltd.  This software is licensed under the
4
# GNU Affero General Public License version 3 (see the file LICENSE).
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
5
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
6
"""
7
Backup one or more PostgreSQL databases.
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
8
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
9
Suitable for use in crontab for daily backups.
10
"""
11
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
12
__metaclass__ = type
13
__all__ = []
14
14612.2.6 by William Grant
utilities
15
from datetime import datetime
16
import logging
17
from optparse import OptionParser
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
18
import os
19
import os.path
20
import stat
21
import subprocess
14612.2.6 by William Grant
utilities
22
import sys
23
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
24
25
MB = float(1024*1024)
26
27
return_code = 0 # Return code of this script. Set to the most recent failed
28
                # system call's return code
29
30
def call(cmd, **kw):
31
    log.debug(' '.join(cmd))
32
    rv = subprocess.call(cmd, **kw)
33
    if rv != 0:
34
        global return_code
35
        return_code = rv
36
    return rv
37
38
def main(options, databases):
6406.2.4 by Stuart Bishop
Syntactic changes on reviewer request
39
    global return_code
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
40
    #Need longer file names if this is used more than daily
41
    #today = datetime.now().strftime('%Y%m%d_%H:%M:%S')
42
    today = datetime.now().strftime('%Y%m%d')
43
44
    backup_dir = options.backup_dir
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
45
46
    # Check for existing files now. Also check later just in case
47
    # there are two copies of this script running or something crazy.
6406.2.3 by Stuart Bishop
Comment
48
    # Better to bomb out now rather than to bomb out later, as later might
49
    # be several hours away.
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
50
    for database in databases:
51
        dest =  os.path.join(backup_dir, '%s.%s.dump' % (database, today))
52
        if os.path.exists(dest):
53
            log.fatal("%s already exists." % dest)
54
            return 1
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
55
 
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
56
    exit_code = 0
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
57
    for database in databases:
58
        dest =  os.path.join(backup_dir, '%s.%s.dump' % (database, today))
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
59
60
        if os.path.exists(dest):
61
            log.fatal("%s already exists." % dest)
62
            return 1
63
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
64
        cmd = [
65
            "/usr/bin/pg_dump",
66
            "-U", "postgres",
67
            "--format=c",
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
68
            "--compress=9",
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
69
            "--blobs",
70
            "--file=%s" % dest,
71
            database,
72
            ]
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
73
6406.2.4 by Stuart Bishop
Syntactic changes on reviewer request
74
        rv = call(cmd, stdin=subprocess.PIPE) # Sets return_code on failure.
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
75
        if rv != 0:
76
            log.critical("Failed to backup %s (%d)" % (database, rv))
77
            continue
78
        size = os.stat(dest)[stat.ST_SIZE]
79
6406.2.1 by Stuart Bishop
Make database backups use builtin gzip compression instead of bzip2 to make dealing with large backups easier
80
        log.info("Backed up %s (%0.2fMB)" % (database, size/MB))
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
81
6406.2.2 by Stuart Bishop
Review feedback
82
    return return_code
1876 by Canonical.com Patch Queue Manager
[r=jamesh] database dump script
83
84
if __name__ == '__main__':
85
    parser = OptionParser(
86
            usage="usage: %prog [options] database [database ..]"
87
            )
88
    parser.add_option("-v", "--verbose", dest="verbose", default=0,
89
            action="count")
90
    parser.add_option("-q", "--quiet", dest="quiet", default=0,
91
            action="count")
92
    parser.add_option("-d", "--dir", dest="backup_dir",
93
            default="/var/lib/postgres/backups")
94
    (options, databases) = parser.parse_args()
95
    if len(databases) == 0:
96
        parser.error("must specify at least one database")
97
    if not os.path.isdir(options.backup_dir):
98
        parser.error(
99
                "Incorrect --dir. %s does not exist or is not a directory" % (
100
                    options.backup_dir
101
                    )
102
                )
103
104
    # Setup our log
105
    log = logging.getLogger('pgbackup')
106
    hdlr = logging.StreamHandler(strm=sys.stderr)
107
    hdlr.setFormatter(logging.Formatter(
108
            fmt='%(asctime)s %(levelname)s %(message)s'
109
            ))
110
    log.addHandler(hdlr)
111
    verbosity = options.verbose - options.quiet
112
    if verbosity > 0:
113
        log.setLevel(logging.DEBUG)
114
    elif verbosity == 0: # Default
115
        log.setLevel(logging.INFO)
116
    elif verbosity == -1:
117
        log.setLevel(logging.WARN)
118
    elif verbosity < -1:
119
        log.setLevel(logging.ERROR)
120
6406.2.2 by Stuart Bishop
Review feedback
121
    sys.exit(main(options, databases))