Browse Source

Oct 30: [FIX] Bug Fixed 'auto_database_backup'

14.0
RisvanaCybro 6 months ago
parent
commit
0d92c2e7f8
  1. 6
      auto_database_backup/__manifest__.py
  2. 5
      auto_database_backup/doc/RELEASE_NOTES.md
  3. 86
      auto_database_backup/models/db_backup_configure.py

6
auto_database_backup/__manifest__.py

@ -21,7 +21,7 @@
############################################################################# #############################################################################
{ {
'name': "Automatic Database Backup", 'name': "Automatic Database Backup",
'version': '14.0.1.0.1', 'version': '14.0.2.0.2',
'summary': 'Generate automatic backup of databases and store to local, ' 'summary': 'Generate automatic backup of databases and store to local, '
'google drive or remote server', 'google drive or remote server',
'description': 'his module has been developed for creating ' 'description': 'his module has been developed for creating '
@ -40,8 +40,8 @@
'wizard/dropbox_auth_code_views.xml' 'wizard/dropbox_auth_code_views.xml'
], ],
'external_dependencies': { 'external_dependencies': {
'python': ['dropbox', 'pyncclient', 'boto3', 'nextcloud-api-wrapper', 'python': ['dropbox', 'pyncclient', 'boto3', 'nextcloud-api-wrapper', 'paramiko']
'paramiko']}, },
'license': 'LGPL-3', 'license': 'LGPL-3',
'images': ['static/description/banner.gif'], 'images': ['static/description/banner.gif'],
'installable': True, 'installable': True,

5
auto_database_backup/doc/RELEASE_NOTES.md

@ -24,3 +24,8 @@
#### Version 14.0.1.0.1 #### Version 14.0.1.0.1
#### ADD #### ADD
- Nextcloud and Amazon S3 integration added. Backup can be stored into Nextcloud and Amazon S3. - Nextcloud and Amazon S3 integration added. Backup can be stored into Nextcloud and Amazon S3.
#### 24.10.2024
#### Version 14.0.2.0.2
#### UPDT
- Fixed the errors while inputting list_db = False in odoo conf file.

86
auto_database_backup/models/db_backup_configure.py

@ -27,7 +27,8 @@ import logging
import os import os
import tempfile import tempfile
from datetime import timedelta from datetime import timedelta
import shutil
import subprocess
import boto3 import boto3
import dropbox import dropbox
import nextcloud_client import nextcloud_client
@ -40,6 +41,7 @@ from werkzeug import urls
import odoo import odoo
from odoo import api, fields, models, _ from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError from odoo.exceptions import UserError, ValidationError
from odoo.tools.misc import find_pg_tool, exec_pg_environ
from odoo.http import request from odoo.http import request
from odoo.service import db from odoo.service import db
@ -675,7 +677,7 @@ class AutoDatabaseBackup(models.Model):
os.makedirs(rec.backup_path) os.makedirs(rec.backup_path)
backup_file = os.path.join(rec.backup_path, backup_filename) backup_file = os.path.join(rec.backup_path, backup_filename)
f = open(backup_file, "wb") f = open(backup_file, "wb")
odoo.service.db.dump_db(rec.db_name, f, rec.backup_format) self.dump_data(rec.db_name, f, rec.backup_format)
f.close() f.close()
# remove older backups # remove older backups
if rec.auto_remove: if rec.auto_remove:
@ -708,7 +710,7 @@ class AutoDatabaseBackup(models.Model):
ftp_server.mkd(rec.ftp_path) ftp_server.mkd(rec.ftp_path)
ftp_server.cwd(rec.ftp_path) ftp_server.cwd(rec.ftp_path)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
ftp_server.storbinary('STOR %s' % backup_filename, ftp_server.storbinary('STOR %s' % backup_filename,
open(temp.name, "rb")) open(temp.name, "rb"))
@ -743,7 +745,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
try: try:
sftp.chdir(rec.sftp_path) sftp.chdir(rec.sftp_path)
@ -779,7 +781,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
try: try:
headers = { headers = {
@ -839,7 +841,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
try: try:
dbx = dropbox.Dropbox( dbx = dropbox.Dropbox(
@ -877,7 +879,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
headers = { headers = {
'Authorization': 'Bearer %s' % rec.onedrive_access_token, 'Authorization': 'Bearer %s' % rec.onedrive_access_token,
@ -989,7 +991,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
backup_file_path = temp.name backup_file_path = temp.name
remote_file_path = f"/{folder_name}/{rec.db_name}_" \ remote_file_path = f"/{folder_name}/{rec.db_name}_" \
@ -1000,7 +1002,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
backup_file_path = temp.name backup_file_path = temp.name
remote_file_path = f"/{folder_name}/{rec.db_name}_" \ remote_file_path = f"/{folder_name}/{rec.db_name}_" \
@ -1060,7 +1062,7 @@ class AutoDatabaseBackup(models.Model):
temp = tempfile.NamedTemporaryFile( temp = tempfile.NamedTemporaryFile(
suffix='.%s' % rec.backup_format) suffix='.%s' % rec.backup_format)
with open(temp.name, "wb+") as tmp: with open(temp.name, "wb+") as tmp:
odoo.service.db.dump_db(rec.db_name, tmp, self.dump_data(rec.db_name, tmp,
rec.backup_format) rec.backup_format)
backup_file_path = temp.name backup_file_path = temp.name
remote_file_path = f"{rec.aws_folder_name}/{rec.db_name}_" \ remote_file_path = f"{rec.aws_folder_name}/{rec.db_name}_" \
@ -1083,3 +1085,67 @@ class AutoDatabaseBackup(models.Model):
if rec.notify_user: if rec.notify_user:
mail_template_failed.send_mail(rec.id, mail_template_failed.send_mail(rec.id,
force_send=True) 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.insert(-1,'--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.insert(-1,'--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

Loading…
Cancel
Save