From 3589bd460f39cc8e05363c6723b3d0027361b6f5 Mon Sep 17 00:00:00 2001 From: AjmalCybro Date: Thu, 18 Apr 2024 12:29:44 +0530 Subject: [PATCH] Apr 18 [IMP] : Updated list_db false issue --- auto_database_backup/__manifest__.py | 2 +- auto_database_backup/doc/RELEASE_NOTES.md | 10 +- .../models/db_backup_configure.py | 103 ++++++++++++++---- 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/auto_database_backup/__manifest__.py b/auto_database_backup/__manifest__.py index 7dbdb9fec..a7fbad51e 100644 --- a/auto_database_backup/__manifest__.py +++ b/auto_database_backup/__manifest__.py @@ -22,7 +22,7 @@ { 'name': "Automatic Database Backup To Local Server, Remote Server," "Google Drive, Dropbox, Onedrive, Nextcloud and Amazon S3", - 'version': '16.0.4.0.1', + 'version': '16.0.5.0.1', 'live_test_url': 'https://youtu.be/Q2yMZyYjuTI', 'category': 'Extra Tools', 'summary': 'Odoo Database Backup, Automatic Backup, Database Backup, Automatic Backup,Database auto-backup, odoo backup' diff --git a/auto_database_backup/doc/RELEASE_NOTES.md b/auto_database_backup/doc/RELEASE_NOTES.md index 53105e805..f7fc959ce 100644 --- a/auto_database_backup/doc/RELEASE_NOTES.md +++ b/auto_database_backup/doc/RELEASE_NOTES.md @@ -28,4 +28,12 @@ #### Version 16.0.4.0.1 #### UPDT -- Fixed internal server error in Onedrive and Google Drive integration. \ No newline at end of file +- Fixed internal server error in Onedrive and Google Drive integration. + +## Module + +#### 18.04.2024 +#### Version 16.0.5.0.1 +#### UPDT + +- Fixed the error while inputting list_db = False in odoo conf file. diff --git a/auto_database_backup/models/db_backup_configure.py b/auto_database_backup/models/db_backup_configure.py index 1337a23ae..51fc62f6c 100644 --- a/auto_database_backup/models/db_backup_configure.py +++ b/auto_database_backup/models/db_backup_configure.py @@ -29,6 +29,8 @@ import nextcloud_client import os import paramiko import requests +import shutil +import subprocess import tempfile import odoo from datetime import timedelta @@ -39,6 +41,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import UserError, ValidationError from odoo.http import request from odoo.service import db +from odoo.tools import find_pg_tool, exec_pg_environ _logger = logging.getLogger(__name__) ONEDRIVE_SCOPE = ['offline_access openid Files.ReadWrite.All'] @@ -119,7 +122,7 @@ class DbBackupConfigure(models.Model): help='Folder id of the drive') notify_user = fields.Boolean(string='Notify User', help='Send an email notification to user when' - 'the backup operation is successful' + 'the backup operation is successful ' 'or failed') user_id = fields.Many2one('res.users', string='User', help='Name of the user') @@ -619,8 +622,8 @@ class DbBackupConfigure(models.Model): os.makedirs(rec.backup_path) backup_file = os.path.join(rec.backup_path, backup_filename) - f = open(backup_file, "wb") - odoo.service.db.dump_db(rec.db_name, f, rec.backup_format) + f = open(backup_file, 'wb') + self.dump_data(rec.db_name, f, rec.backup_format) f.close() # Remove older backups if rec.auto_remove: @@ -632,8 +635,7 @@ class DbBackupConfigure(models.Model): if backup_duration.days >= rec.days_to_remove: os.remove(file) if rec.notify_user: - mail_template_success.send_mail(rec.id, - force_send=True) + mail_template_success.send_mail(rec.id, force_send=True) except Exception as e: rec.generated_exception = e _logger.info('FTP Exception: %s', e) @@ -654,8 +656,7 @@ class DbBackupConfigure(models.Model): ftp_server.mkd(rec.ftp_path) ftp_server.cwd(rec.ftp_path) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) ftp_server.storbinary('STOR %s' % backup_filename, open(temp.name, "rb")) if rec.auto_remove: @@ -690,8 +691,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) try: sftp.chdir(rec.sftp_path) except IOError as e: @@ -727,8 +727,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) try: headers = { "Authorization": "Bearer %s" % rec.gdrive_access_token} @@ -787,8 +786,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) try: dbx = dropbox.Dropbox( app_key=rec.dropbox_client_key, @@ -822,8 +820,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) headers = { 'Authorization': 'Bearer %s' % rec.onedrive_access_token, 'Content-Type': 'application/json'} @@ -918,8 +915,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) backup_file_path = temp.name remote_file_path = f"/{folder_name}/{rec.db_name}_" \ f"{backup_time}.{rec.backup_format}" @@ -929,8 +925,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) backup_file_path = temp.name remote_file_path = f"/{folder_name}/{rec.db_name}_" \ f"{backup_time}.{rec.backup_format}" @@ -989,8 +984,7 @@ class DbBackupConfigure(models.Model): temp = tempfile.NamedTemporaryFile( suffix='.%s' % rec.backup_format) with open(temp.name, "wb+") as tmp: - odoo.service.db.dump_db(rec.db_name, tmp, - rec.backup_format) + self.dump_data(rec.db_name, tmp, rec.backup_format) backup_file_path = temp.name remote_file_path = f"{rec.aws_folder_name}/{rec.db_name}_" \ f"{backup_time}.{rec.backup_format}" @@ -1012,3 +1006,70 @@ class DbBackupConfigure(models.Model): if rec.notify_user: mail_template_failed.send_mail(rec.id, force_send=True) + + def dump_data(self, db_name, stream, backup_format): + """Dump database `db` into file-like object `stream` if stream is None + return a file object with the dump. """ + + cron_user_id = self.env.ref( + 'auto_database_backup.ir_cron_auto_db_backup').user_id.id + if cron_user_id != self.env.user.id: + _logger.error( + 'Unauthorized database operation. Backups should only be available from the cron job.') + raise ValidationError( + "Unauthorized database operation. Backups should only be available from the cron job.") + + _logger.info('DUMP DB: %s format %s', db_name, backup_format) + cmd = [find_pg_tool('pg_dump'), '--no-owner', db_name] + env = exec_pg_environ() + if backup_format == 'zip': + with tempfile.TemporaryDirectory() as dump_dir: + filestore = odoo.tools.config.filestore(db_name) + cmd.append('--file=' + os.path.join(dump_dir, 'dump.sql')) + subprocess.run(cmd, env=env, stdout=subprocess.DEVNULL, + stderr=subprocess.STDOUT, check=True) + if os.path.exists(filestore): + shutil.copytree(filestore, + os.path.join(dump_dir, 'filestore')) + with open(os.path.join(dump_dir, 'manifest.json'), 'w') as fh: + db = odoo.sql_db.db_connect(db_name) + with db.cursor() as cr: + json.dump(self._dump_db_manifest(cr), fh, indent=4) + if stream: + odoo.tools.osutil.zip_dir(dump_dir, stream, + include_dir=False, + fnct_sort=lambda + file_name: file_name != 'dump.sql') + else: + t = tempfile.TemporaryFile() + odoo.tools.osutil.zip_dir(dump_dir, t, include_dir=False, + fnct_sort=lambda + file_name: file_name != 'dump.sql') + t.seek(0) + return t + else: + cmd.append('--format=c') + process = subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE) + stdout, _ = process.communicate() + if stream: + stream.write(stdout) + else: + return stdout + + def _dump_db_manifest(self, cr): + """ This function generates a manifest dictionary for database dump.""" + pg_version = "%d.%d" % divmod(cr._obj.connection.server_version / 100, + 100) + cr.execute( + "SELECT name, latest_version FROM ir_module_module WHERE state = 'installed'") + modules = dict(cr.fetchall()) + manifest = { + 'odoo_dump': '1', + 'db_name': cr.dbname, + 'version': odoo.release.version, + 'version_info': odoo.release.version_info, + 'major_version': odoo.release.major_version, + 'pg_version': pg_version, + 'modules': modules, + } + return manifest