Feature #298 - Create environment tarball
[mediagoblin.git] / mediagoblin / gmg_commands / import_export.py
CommitLineData
e86d4f5d
JW
1# GNU MediaGoblin -- federated, autonomous media hosting
2# Copyright (C) 2011 Free Software Foundation, Inc
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17from mediagoblin.gmg_commands import util as commands_util
18from mediagoblin import mg_globals
19from mediagoblin.db import util as db_util
20from mediagoblin.db.open import setup_connection_and_db_from_config
21from mediagoblin.init.config import read_mediagoblin_config
9188f3af 22from mediagoblin import util as mg_util
2a233ae3
JW
23from mediagoblin.storage import BasicFileStorage
24from mediagoblin.init import setup_storage, setup_global_and_app_config
e86d4f5d
JW
25
26import shlex
7219983f 27import shutil
e86d4f5d
JW
28import tarfile
29import subprocess
30import os.path
2a233ae3
JW
31import os
32import re
7219983f
JW
33import sys
34
e86d4f5d
JW
35
36def import_export_parse_setup(subparser):
37 # TODO: Add default
38 subparser.add_argument(
39 'tar_file')
40 subparser.add_argument(
41 '-cf', '--conf_file', default='mediagoblin.ini',
42 help='Config file used to set up environment')
e86d4f5d
JW
43 subparser.add_argument(
44 '--mongodump_path', default='mongodump',
45 help='mongodump binary')
224813d2
JW
46 subparser.add_argument(
47 '--mongorestore_path', default='mongorestore',
48 help='mongorestore binary')
49 subparser.add_argument(
2a233ae3 50 '--cache_path', default='/tmp/mediagoblin/',
9188f3af 51 help='')
e86d4f5d 52
7219983f 53
7219983f
JW
54def _import_media(db, args):
55 """
56 Import media files
57
58 Must be called after _import_database()
59 """
60 print "\n== Importing media ==\n"
61
62 media_cache = BasicFileStorage(
63 args._cache_path['media'])
64
65 # TODO: Add import of queue files
2a233ae3
JW
66 queue_cache = BasicFileStorage(
67 args._cache_path['queue'])
68
7219983f
JW
69 for entry in db.media_entries.find():
70 for name, path in entry['media_files'].items():
71 media_file = mg_globals.public_store.get_file(path, mode='wb')
72 media_file.write(
73 media_cache.get_file(path, mode='rb').read())
74
75 print(media_file)
76 print(entry)
77
78 print "\n== Media imported ==\n"
2a233ae3 79
2a233ae3 80
e86d4f5d 81def _import_database(db, args):
8f12c9b2
JW
82 """
83 Restore mongo database from ___.bson files
84 """
7219983f 85 print "\n== Importing database ==\n"
7219983f 86
8f12c9b2
JW
87 p = subprocess.Popen([
88 args.mongorestore_path,
89 '-d', db.name,
90 os.path.join(args._cache_path['database'], db.name)])
91
92 print p
7219983f
JW
93
94 p.wait()
95
8f12c9b2 96 print "\n== Database imported ==\n"
e86d4f5d 97
7219983f 98
8f12c9b2
JW
99def env_import(args):
100 """
101 Restore mongo database and media files from a tar archive
102 """
103 # args.cache_path += 'mediagoblin-data'
7219983f 104 setup_global_and_app_config(args.conf_file)
8f12c9b2
JW
105
106 # Creates mg_globals.public_store and mg_globals.queue_store
7219983f
JW
107 setup_storage()
108
e86d4f5d
JW
109 config, validation_result = read_mediagoblin_config(args.conf_file)
110 connection, db = setup_connection_and_db_from_config(
111 config['mediagoblin'], use_pymongo=True)
112
224813d2
JW
113 tf = tarfile.open(
114 args.tar_file,
115 mode='r|gz')
9188f3af 116
7219983f
JW
117 tf.extractall(args.cache_path)
118
8f12c9b2
JW
119 args.cache_path += 'mediagoblin-data'
120 args = _setup_paths(args)
121
7219983f
JW
122 # Import database from extracted data
123 _import_database(db, args)
124
125 _import_media(db, args)
126
8f12c9b2 127 # _clean(args)
224813d2 128
2a233ae3 129def _setup_paths(args):
8f12c9b2
JW
130 """
131 Populate ``args`` variable with cache subpaths
132 """
2a233ae3
JW
133 args._cache_path = dict()
134 PATH_MAP = {
135 'media': 'media',
7219983f 136 'queue': 'queue',
2a233ae3 137 'database': 'database'}
7219983f 138
2a233ae3
JW
139 for key, val in PATH_MAP.items():
140 args._cache_path[key] = os.path.join(args.cache_path, val)
141
142 return args
143
7219983f 144
2a233ae3 145def _create_archive(args):
8f12c9b2
JW
146 """
147 Create the tar archive
148 """
2a233ae3 149 print "\n== Compressing to archive ==\n"
7219983f 150
2a233ae3
JW
151 tf = tarfile.open(
152 args.tar_file,
153 mode='w|gz')
2a233ae3 154
7219983f
JW
155 with tf:
156 tf.add(args.cache_path, 'mediagoblin-data/')
157
158 print "\n== Archiving done ==\n"
159
160
161def _clean(args):
8f12c9b2
JW
162 """
163 Remove cache directory
164 """
7219983f 165 shutil.rmtree(args.cache_path)
2a233ae3 166
2a233ae3 167
8f12c9b2
JW
168def _export_check(args):
169 """
170 Run security checks for export command
171 """
7219983f
JW
172 if os.path.exists(args.tar_file):
173 overwrite = raw_input(
174 'The output file already exists. '
175 'Are you **SURE** you want to overwrite it? '
176 '(yes/no)> ')
177 if not overwrite == 'yes':
178 print "Aborting."
2a233ae3 179
7219983f 180 return False
2a233ae3 181
7219983f
JW
182 if os.path.exists(args.cache_path):
183 print 'The cache directory must not exist before you run this script'
184 print 'Cache directory: ', args.cache_path
2a233ae3 185
7219983f 186 return False
2a233ae3 187
7219983f 188 return True
2a233ae3 189
2a233ae3 190
8f12c9b2
JW
191def _export_database(db, args):
192 print "\n== Exporting database ==\n"
193
194 command = '{mongodump_path} -d {database} -o {mongodump_cache}'.format(
195 mongodump_path=args.mongodump_path,
196 database=db.name,
197 mongodump_cache=args._cache_path['database'])
198
199 p = subprocess.Popen([
200 args.mongodump_path,
201 '-d', db.name,
202 '-o', args._cache_path['database']])
203
204 p.wait()
205
206 print "\n== Database exported ==\n"
207
208
209def _export_media(db, args):
210 print "\n== Exporting media ==\n"
211
212 media_cache = BasicFileStorage(
213 args._cache_path['media'])
214
215 # TODO: Add export of queue files
216 queue_cache = BasicFileStorage(
217 args._cache_path['queue'])
218
219 for entry in db.media_entries.find():
220 for name, path in entry['media_files'].items():
221 mc_file = media_cache.get_file(path, mode='wb')
222 mc_file.write(
223 mg_globals.public_store.get_file(path, mode='rb').read())
224
225 print(mc_file)
226 print(entry)
227
228 print "\n== Media exported ==\n"
229
230
e86d4f5d 231def env_export(args):
8f12c9b2
JW
232 """
233 Export database and media files to a tar archive
234 """
2a233ae3
JW
235 args = _setup_paths(args)
236
8f12c9b2 237 if not _export_check(args):
7219983f
JW
238 print "\n== Checks did not pass, exiting ==\n"
239 sys.exit(0)
240
2a233ae3
JW
241 setup_global_and_app_config(args.conf_file)
242 setup_storage()
243
e86d4f5d
JW
244 config, validation_result = read_mediagoblin_config(args.conf_file)
245 connection, db = setup_connection_and_db_from_config(
246 config['mediagoblin'], use_pymongo=True)
247
2a233ae3 248 _export_database(db, args)
e86d4f5d 249
2a233ae3 250 _export_media(db, args)
e86d4f5d 251
2a233ae3 252 _create_archive(args)
7219983f
JW
253
254 _clean(args)