176
183
raise Exception("Couldn't drop database %s: %s" % (db_name, e))
178
185
_logger.info('DROP DB: %s', db_name)
187
fs = openerp.tools.config.filestore(db_name)
188
if os.path.exists(fs):
181
@contextlib.contextmanager
182
def _set_pg_password_in_environment():
192
def _set_pg_password_in_environment(func):
183
193
""" On systems where pg_restore/pg_dump require an explicit
184
194
password (i.e. when not connecting via unix sockets, and most
185
195
importantly on Windows), it is necessary to pass the PG user
186
196
password in the environment or in a special .pgpass file.
188
This context management method handles setting
198
This decorator handles setting
189
199
:envvar:`PGPASSWORD` if it is not already
190
200
set, and removing it afterwards.
192
202
See also http://www.postgresql.org/docs/8.4/static/libpq-envars.html
194
204
.. note:: This is not thread-safe, and should never be enabled for
195
205
SaaS (giving SaaS users the super-admin password is not a good idea
198
if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
201
os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
205
del os.environ['PGPASSWORD']
209
def wrapper(*args, **kwargs):
210
if os.environ.get('PGPASSWORD') or not openerp.tools.config['db_password']:
211
return func(*args, **kwargs)
213
os.environ['PGPASSWORD'] = openerp.tools.config['db_password']
215
return func(*args, **kwargs)
217
del os.environ['PGPASSWORD']
208
220
def exp_dump(db_name):
209
with _set_pg_password_in_environment():
210
cmd = ['pg_dump', '--format=c', '--no-owner']
211
if openerp.tools.config['db_user']:
212
cmd.append('--username=' + openerp.tools.config['db_user'])
213
if openerp.tools.config['db_host']:
214
cmd.append('--host=' + openerp.tools.config['db_host'])
215
if openerp.tools.config['db_port']:
216
cmd.append('--port=' + str(openerp.tools.config['db_port']))
219
stdin, stdout = openerp.tools.exec_pg_command_pipe(*tuple(cmd))
226
'DUMP DB: %s failed! Please verify the configuration of the database password on the server. '
227
'You may need to create a .pgpass file for authentication, or specify `db_password` in the '
228
'server configuration file.\n %s', db_name, data)
229
raise Exception, "Couldn't dump database"
230
_logger.info('DUMP DB successful: %s', db_name)
232
return base64.encodestring(data)
234
def exp_restore(db_name, data):
235
with _set_pg_password_in_environment():
236
if exp_db_exist(db_name):
237
_logger.warning('RESTORE DB: %s already exists', db_name)
238
raise Exception, "Database already exists"
240
_create_empty_database(db_name)
242
cmd = ['pg_restore', '--no-owner']
243
if openerp.tools.config['db_user']:
244
cmd.append('--username=' + openerp.tools.config['db_user'])
245
if openerp.tools.config['db_host']:
246
cmd.append('--host=' + openerp.tools.config['db_host'])
247
if openerp.tools.config['db_port']:
248
cmd.append('--port=' + str(openerp.tools.config['db_port']))
249
cmd.append('--dbname=' + db_name)
252
buf=base64.decodestring(data)
254
tmpfile = (os.environ['TMP'] or 'C:\\') + os.tmpnam()
255
file(tmpfile, 'wb').write(buf)
257
args2.append(tmpfile)
259
stdin, stdout = openerp.tools.exec_pg_command_pipe(*args2)
260
if not os.name == "nt":
261
stdin.write(base64.decodestring(data))
265
raise Exception, "Couldn't restore database"
266
_logger.info('RESTORE DB: %s', db_name)
221
with tempfile.TemporaryFile() as t:
224
return t.read().encode('base64')
226
@_set_pg_password_in_environment
227
def dump_db(db, stream):
228
"""Dump database `db` into file-like object `stream`"""
229
with openerp.tools.osutil.tempdir() as dump_dir:
230
registry = openerp.modules.registry.RegistryManager.get(db)
231
with registry.cursor() as cr:
232
filestore = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
233
if os.path.exists(filestore):
234
shutil.copytree(filestore, os.path.join(dump_dir, 'filestore'))
236
dump_file = os.path.join(dump_dir, 'dump.sql')
237
cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file]
238
if openerp.tools.config['db_user']:
239
cmd.append('--username=' + openerp.tools.config['db_user'])
240
if openerp.tools.config['db_host']:
241
cmd.append('--host=' + openerp.tools.config['db_host'])
242
if openerp.tools.config['db_port']:
243
cmd.append('--port=' + str(openerp.tools.config['db_port']))
246
if openerp.tools.exec_pg_command(*cmd):
247
_logger.error('DUMP DB: %s failed! Please verify the configuration of the database '
248
'password on the server. You may need to create a .pgpass file for '
249
'authentication, or specify `db_password` in the server configuration '
251
raise Exception("Couldn't dump database")
253
openerp.tools.osutil.zip_dir(dump_dir, stream, include_dir=False)
255
_logger.info('DUMP DB successful: %s', db)
257
def exp_restore(db_name, data, copy=False):
258
data_file = tempfile.NamedTemporaryFile(delete=False)
260
data_file.write(data.decode('base64'))
262
restore_db(db_name, data_file.name, copy=copy)
264
os.unlink(data_file.name)
267
@_set_pg_password_in_environment
268
def restore_db(db, dump_file, copy=False):
269
assert isinstance(db, basestring)
271
_logger.warning('RESTORE DB: %s already exists', db)
272
raise Exception("Database already exists")
274
_create_empty_database(db)
276
filestore_path = None
277
with openerp.tools.osutil.tempdir() as dump_dir:
278
if zipfile.is_zipfile(dump_file):
280
with zipfile.ZipFile(dump_file, 'r') as z:
281
# only extract known members!
282
filestore = [m for m in z.namelist() if m.startswith('filestore/')]
283
z.extractall(dump_dir, ['dump.sql'] + filestore)
286
filestore_path = os.path.join(dump_dir, 'filestore')
289
pg_args = ['-q', '-f', os.path.join(dump_dir, 'dump.sql')]
292
# <= 7.0 format (raw pg_dump output)
293
pg_cmd = 'pg_restore'
294
pg_args = ['--no-owner', dump_file]
297
if openerp.tools.config['db_user']:
298
args.append('--username=' + openerp.tools.config['db_user'])
299
if openerp.tools.config['db_host']:
300
args.append('--host=' + openerp.tools.config['db_host'])
301
if openerp.tools.config['db_port']:
302
args.append('--port=' + str(openerp.tools.config['db_port']))
303
args.append('--dbname=' + db)
304
pg_args = args + pg_args
306
if openerp.tools.exec_pg_command(pg_cmd, *pg_args):
307
raise Exception("Couldn't restore database")
309
registry = openerp.modules.registry.RegistryManager.new(db)
310
with registry.cursor() as cr:
312
# if it's a copy of a database, force generation of a new dbuuid
313
registry['ir.config_parameter'].init(cr, force=True)
315
filestore_dest = registry['ir.attachment']._filestore(cr, SUPERUSER_ID)
316
shutil.move(filestore_path, filestore_dest)
318
if openerp.tools.config['unaccent']:
321
cr.execute("CREATE EXTENSION unaccent")
322
except psycopg2.Error:
325
_logger.info('RESTORE DB: %s', db)
270
327
def exp_rename(old_name, new_name):
271
328
openerp.modules.registry.RegistryManager.delete(old_name)