def backup_database(full=False): if not os.path.exists(APP_BACKUP_DIR): os.makedirs(APP_BACKUP_DIR) filename = os.path.join(APP_BACKUP_DIR, 'stoq.dump') if not db_settings.dump_database(filename, format='plain'): raise TaskException("Failed to dump the database") backup.backup(APP_BACKUP_DIR, full=full) logger.info("Database backup finished sucessfully")
def restore_database(user_hash, time=None): assert user_hash # If the database doesn't exist, get_default_store will fail try: default_store = get_default_store() except Exception: default_store = None if default_store is not None and db_settings.has_database(): try: default_store.lock_database() except DatabaseError: raise TaskException( "Could not lock database. This means that there are other " "clients connected. Make sure to close every Stoq client " "before updating the database") except Exception: raise TaskException( "Database is empty or in a corrupted state. Fix or drop it " "before trying to proceed with the restore") else: default_store.unlock_database() # FIXME: Windows will not liberate resource for other process to # write to the file. We should write our own TemporaryFile on Stoq # that handles all those cases for us and use here with tempfile.NamedTemporaryFile(delete=False) as f: pass try: if not db_settings.dump_database(f.name): raise TaskException("Failed to dump the database") backup_name = db_settings.restore_database(f.name) logger.info("Created a backup of the current database state on %s", backup_name) finally: os.unlink(f.name) tmp_path = tempfile.mkdtemp() try: restore_path = os.path.join(tmp_path, 'stoq') backup.restore(restore_path, user_hash, time=time) # None will make the default store be closed, which we need # to sucessfully restore the database set_default_store(None) db_settings.clean_database(db_settings.dbname, force=True) db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'), lock_database=True) logger.info("Backup restore finished sucessfully") finally: # get_default_store will recreate it (since we closed it above) get_default_store() shutil.rmtree(tmp_path, ignore_errors=True)
def restore_database(user_hash, time=None): assert user_hash # If the database doesn't exist, get_default_store will fail try: default_store = get_default_store() except Exception: default_store = None if default_store is not None and db_settings.has_database(): try: default_store.lock_database() except DatabaseError: raise TaskException( "Could not lock database. This means that there are other " "clients connected. Make sure to close every Stoq client " "before updating the database") except Exception: raise TaskException( "Database is empty or in a corrupted state. Fix or drop it " "before trying to proceed with the restore") else: default_store.unlock_database() # FIXME: Windows will not liberate resource for other process to # write to the file. We should write our own TemporaryFile on Stoq # that handles all those cases for us and use here with tempfile.NamedTemporaryFile(delete=False) as f: pass try: if not db_settings.dump_database(f.name): raise TaskException("Failed to dump the database") backup_name = db_settings.restore_database(f.name) logger.info("Created a backup of the current database state on %s", backup_name) finally: os.unlink(f.name) tmp_path = tempfile.mkdtemp() try: restore_path = os.path.join(tmp_path, 'stoq') logger.info("restoring database to %s", restore_path) backup.restore(restore_path, user_hash, time=time) # None will make the default store be closed, which we need # to sucessfully restore the database set_default_store(None) db_settings.clean_database(db_settings.dbname, force=True) db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'), lock_database=True) logger.info("Backup restore finished sucessfully") finally: # get_default_store will recreate it (since we closed it above) get_default_store()
def _backup_database(self): temporary = tempfile.mktemp(prefix="stoq-dump-") log.info("Making a backup to %s" % (temporary, )) create_log.info("BACKUP-START:") success = db_settings.dump_database(temporary) if not success: info(_(u'Could not create backup! Aborting.')) info(_(u'Please contact stoq team to inform this problem.\n')) return self._backup = temporary return True
def restore_database(user_hash, time=None): assert user_hash # If the database doesn't exist, get_default_store will fail try: default_store = get_default_store() except Exception: default_store = None if default_store is not None and db_settings.has_database(): try: default_store.lock_database() except DatabaseError: raise TaskException( "Could not lock database. This means that there are other " "clients connected. Make sure to close every Stoq client " "before updating the database") except Exception: raise TaskException( "Database is empty or in a corrupted state. Fix or drop it " "before trying to proceed with the restore") else: default_store.unlock_database() with tempfile.NamedTemporaryFile() as f: if not db_settings.dump_database(f.name): raise TaskException("Failed to dump the database") backup_name = db_settings.restore_database(f.name) logger.info("Created a backup of the current database state on %s", backup_name) tmp_path = tempfile.mkdtemp() try: # None will make the default store be closed, which we need # to sucessfully restore the database set_default_store(None) restore_path = os.path.join(tmp_path, 'stoq') backup.restore(restore_path, user_hash, time=time) db_settings.clean_database(db_settings.dbname, force=True) db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'), lock_database=True) logger.info("Backup restore finished sucessfully") finally: # get_default_store will recreate it (since we closed it above) get_default_store() shutil.rmtree(tmp_path, ignore_errors=True)
def update(self, plugins=True, backup=True): log.info("Upgrading database (plugins=%r, backup=%r)" % ( plugins, backup)) try: log.info("Locking database") self.default_store.lock_database() except DatabaseError: msg = _('Could not lock database. This means there are other clients ' 'connected. Make sure to close every Stoq client ' 'before updating the database') error(msg) # Database migration is actually run in subprocesses, We need to unlock # the tables again and let the upgrade continue log.info("Releasing database lock") self.default_store.unlock_database() sucess = db_settings.test_connection() if not sucess: # FIXME: Improve this message after 1.5 is released msg = _(u'Could not connect to the database using command line ' 'tool! Aborting.') + ' ' msg += _(u'Please, check if you can connect to the database ' 'using:') + ' ' msg += _(u'psql -l -h <server> -p <port> -U <username>') error(msg) return if backup: temporary = tempfile.mktemp(prefix="stoq-dump-") log.info("Making a backup to %s" % (temporary, )) create_log.info("BACKUP-START:") success = db_settings.dump_database(temporary) if not success: info(_(u'Could not create backup! Aborting.')) info(_(u'Please contact stoq team to inform this problem.\n')) return # We have to wrap a try/except statement inside a try/finally to # support python previous to 2.5 version. try: try: super(StoqlibSchemaMigration, self).update() if plugins: self.update_plugins() except Exception: exc = sys.exc_info() tb_str = ''.join(traceback.format_exception(*exc)) collect_traceback(exc, submit=True) create_log.info("ERROR:%s" % (tb_str, )) if backup: log.info("Restoring backup %s" % (temporary, )) create_log.info("RESTORE-START:") new_name = db_settings.restore_database(temporary) create_log.info("RESTORE-DONE:%s" % (new_name, )) return False finally: if backup is True: os.unlink(temporary) log.info("Migration done") return True
def update(self, plugins=True, backup=True): log.info("Upgrading database (plugins=%r, backup=%r)" % (plugins, backup)) try: log.info("Locking database") self.default_store.lock_database() except DatabaseError: msg = _( 'Could not lock database. This means there are other clients ' 'connected. Make sure to close every Stoq client ' 'before updating the database') error(msg) # Database migration is actually run in subprocesses, We need to unlock # the tables again and let the upgrade continue log.info("Releasing database lock") self.default_store.unlock_database() sucess = db_settings.test_connection() if not sucess: # FIXME: Improve this message after 1.5 is released msg = _(u'Could not connect to the database using command line ' 'tool! Aborting.') + ' ' msg += _(u'Please, check if you can connect to the database ' 'using:') + ' ' msg += _(u'psql -l -h <server> -p <port> -U <username>') error(msg) return if backup: temporary = tempfile.mktemp(prefix="stoq-dump-") log.info("Making a backup to %s" % (temporary, )) create_log.info("BACKUP-START:") success = db_settings.dump_database(temporary) if not success: info(_(u'Could not create backup! Aborting.')) info(_(u'Please contact stoq team to inform this problem.\n')) return # We have to wrap a try/except statement inside a try/finally to # support python previous to 2.5 version. try: try: super(StoqlibSchemaMigration, self).update() if plugins: self.update_plugins() except Exception: exc = sys.exc_info() tb_str = ''.join(traceback.format_exception(*exc)) collect_traceback(exc, submit=True) create_log.info("ERROR:%s" % (tb_str, )) if backup: log.info("Restoring backup %s" % (temporary, )) create_log.info("RESTORE-START:") new_name = db_settings.restore_database(temporary) create_log.info("RESTORE-DONE:%s" % (new_name, )) return False finally: if backup is True: os.unlink(temporary) log.info("Migration done") return True