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