annotate backup-lapp-app @ 0:b4d371b24a5e default tip

Initial Import
author Louis Opter <kalessin@kalessin.fr>
date Thu, 01 Apr 2010 19:18:49 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
1 #!/usr/bin/env python
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
2
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
3 # The MIT License
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
4 #
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
5 # Copyright (c) 2010 Louis Opter <kalessin@kalessin.fr>
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
6 #
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
8 # of this software and associated documentation files (the "Software"), to deal
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
9 # in the Software without restriction, including without limitation the rights
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
11 # copies of the Software, and to permit persons to whom the Software is
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
12 # furnished to do so, subject to the following conditions:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
13 #
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
14 # The above copyright notice and this permission notice shall be included in
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
15 # all copies or substantial portions of the Software.
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
16 #
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
23 # THE SOFTWARE.
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
24
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
25 import errno
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
26 import os
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
27 import shutil
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
28 import subprocess
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
29 import sys
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
30 import tarfile
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
31 import tempfile
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
32
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
33 class TempDir(object):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
34 """Wrap tempfile.mkdtemp to use the with statement"""
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
35
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
36 def __init__(self):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
37 pass
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
38
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
39 def __enter__(self):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
40 self.__path = tempfile.mkdtemp()
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
41 return self.__path
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
42
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
43 def __exit__(self, exc_type, exc_value, traceback):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
44 shutil.rmtree(self.__path)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
45
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
46 def status(message):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
47 print '%s: %s.' % (os.path.basename(sys.argv[0]), message)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
48
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
49 def die(message):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
50 status(message)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
51 status('a log has been recorded in %s' % log_path)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
52 sys.exit(1)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
53
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
54 def dump_db():
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
55 """Use pg_dump to backup the databse into `root'"""
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
56
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
57 dump_path = os.path.join(root, db_name + '.sql')
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
58 with open(dump_path, 'w') as dump:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
59 status('Dumping database to %s' % dump_path)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
60 if subprocess.call(['sudo', '-u', 'postgres', 'pg_dump', db_name],
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
61 stdout=dump, stderr=log) != 0:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
62 die('error while dumping database %s to a temporary directory' % db_name)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
63
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
64 status('Database %s dumped' % db_name)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
65
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
66 def archive():
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
67 """Create a tar bzipped archive of the db dump and the www-dir"""
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
68
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
69 try:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
70 archive = tarfile.open(os.path.join(root, archive_name), 'w:bz2')
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
71 archive.add(os.path.join(root, db_name + '.sql'), db_name + '.sql')
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
72 archive.add(www_dir, os.path.basename(www_dir))
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
73 archive.close()
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
74 except tarfile.TarError, ex:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
75 die('Can\'t create the tar archive %s: %s' % (archive_name, str(ex)))
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
76
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
77 status('Archive %s created' % archive_name)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
78
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
79 def send_archive():
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
80 """Send the tarball using scp or s3cmd"""
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
81
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
82 archive = os.path.join(root, archive_name)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
83 if dest[0:5] == 's3://':
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
84 ret = subprocess.call(['s3cmd', '--acl-private', 'put', archive, dest], stdout=log, stderr=log)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
85 else:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
86 ret = subprocess.call(['scp', archive, dest], stdout=log, stderr=log)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
87
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
88 if ret != 0:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
89 die('error while cpying %s to %s' % (archive_name, dest))
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
90
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
91 status('Archive %s copied to "%s"' % (archive_name, dest))
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
92
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
93 if __name__ == '__main__':
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
94 if len(sys.argv) != 4 or sys.argv[1] == '--help':
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
95 print 'Usage: %s db-name www-dir [[user@]host:]path|s3://bucket/[path]' % os.path.basename(sys.argv[0])
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
96 sys.exit(0)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
97
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
98 # globals
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
99 db_name = sys.argv[1]
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
100 # python basename return '' for a path with an ending slash...
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
101 www_dir = sys.argv[2] != '/' and os.path.join('/var/www', sys.argv[2]) or '/var/www'
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
102 dest = sys.argv[3]
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
103 archive_name = 'backup-lapp-app-%s.tar.bz2' % db_name
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
104 log_path = os.path.join(os.getenv('TMP') or '/tmp/', db_name + '.log')
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
105
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
106 if not os.path.exists(www_dir):
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
107 status('%s: %s' % (www_dir, os.strerror(errno.ENOENT)))
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
108 sys.exit(1)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
109
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
110 with open(log_path, 'w') as log:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
111 with TempDir() as root:
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
112 status('root=%s' % root)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
113 dump_db()
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
114 archive()
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
115 send_archive()
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
116 os.remove(log_path)
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
117
b4d371b24a5e Initial Import
Louis Opter <kalessin@kalessin.fr>
parents:
diff changeset
118 sys.exit(0)