diff --git a/auto_backup/README.rst b/auto_backup/README.rst index e3957fe7b..1fb8820bd 100644 --- a/auto_backup/README.rst +++ b/auto_backup/README.rst @@ -1,5 +1,5 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: https://www.gnu.org/licenses/agpl :alt: License: AGPL-3 ==================== @@ -13,12 +13,12 @@ Installation Before installing this module, you need to execute:: - pip install pysftp + pip3 install pysftp Configuration ============= -Go to *Settings -> Configuration -> Configure Backup* to +Go to *Settings -> Database Structure -> Automated Backup* to create your configurations for each database that you needed to backups. @@ -70,7 +70,7 @@ manually execute the selected processes. .. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/149/10.0 + :target: https://runbot.odoo-community.org/runbot/149/11.0 Known issues / Roadmap ====================== @@ -87,7 +87,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, -help us smashing it by providing a detailed and welcomed feedback. +help us smash it by providing detailed and welcomed feedback. Credits ======= @@ -99,6 +99,7 @@ Contributors * Alessio Gerace * Jairo Llopis * Dave Lasley +* Andrea Stirpe Maintainer ---------- diff --git a/auto_backup/__init__.py b/auto_backup/__init__.py index 49f944b46..31660d6a9 100644 --- a/auto_backup/__init__.py +++ b/auto_backup/__init__.py @@ -1,7 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2004-2009 Tiny SPRL (). -# © 2015 Agile Business Group -# © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis -# License GPL-3.0 or later (http://www.gnu.org/licenses/gpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import models diff --git a/auto_backup/__manifest__.py b/auto_backup/__manifest__.py index 7060c5e12..8d1da2dcd 100644 --- a/auto_backup/__manifest__.py +++ b/auto_backup/__manifest__.py @@ -1,13 +1,12 @@ -# -*- coding: utf-8 -*- # © 2004-2009 Tiny SPRL (). # © 2015 Agile Business Group # © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis -# License GPL-3.0 or later (http://www.gnu.org/licenses/gpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Database Auto-Backup", "summary": "Backups database", - "version": "10.0.1.0.2", + "version": "11.0.1.0.0", "author": ( "Yenthe Van Ginneken, " "Agile Business Group, " @@ -15,11 +14,11 @@ "LasLabs, " "Odoo Community Association (OCA)" ), - 'license': "AGPL-3", - "website": "http://www.vanroey.be/applications/bedrijfsbeheer/odoo", + "license": "AGPL-3", + "website": "https://github.com/OCA/server-tools/", "category": "Tools", "depends": [ - 'mail', + "mail", ], "data": [ "data/ir_cron.xml", @@ -27,7 +26,6 @@ "security/ir.model.access.csv", "view/db_backup_view.xml", ], - "application": True, "installable": True, "external_dependencies": { "python": ["pysftp"], diff --git a/auto_backup/data/ir_cron.xml b/auto_backup/data/ir_cron.xml index 6b62e364b..9fe1bfb76 100644 --- a/auto_backup/data/ir_cron.xml +++ b/auto_backup/data/ir_cron.xml @@ -1,5 +1,4 @@ - - + @@ -8,11 +7,10 @@ 1 days -1 - - db.backup - action_backup_all + + + code + model.action_backup_all() diff --git a/auto_backup/data/mail_message_subtype.xml b/auto_backup/data/mail_message_subtype.xml index 2dd820f97..a0e8e932b 100644 --- a/auto_backup/data/mail_message_subtype.xml +++ b/auto_backup/data/mail_message_subtype.xml @@ -1,5 +1,4 @@ - - + diff --git a/auto_backup/models/__init__.py b/auto_backup/models/__init__.py index 7c06b2f5a..7486b7dbb 100644 --- a/auto_backup/models/__init__.py +++ b/auto_backup/models/__init__.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2004-2009 Tiny SPRL (). -# © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis -# License AGPL-3.0 or later (http://www.gnu.org/licenses/gpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import db_backup diff --git a/auto_backup/models/db_backup.py b/auto_backup/models/db_backup.py index 7b1ef6e80..464215cfb 100644 --- a/auto_backup/models/db_backup.py +++ b/auto_backup/models/db_backup.py @@ -1,18 +1,19 @@ -# -*- coding: utf-8 -*- # © 2004-2009 Tiny SPRL (). # © 2015 Agile Business Group # © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis -# License AGPL-3.0 or later (http://www.gnu.org/licenses/gpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import logging import os import shutil import traceback from contextlib import contextmanager from datetime import datetime, timedelta from glob import iglob -from odoo import exceptions, models, fields, api, _, tools + +from odoo import _, api, exceptions, fields, models, tools from odoo.service import db -import logging + _logger = logging.getLogger(__name__) try: import pysftp @@ -21,6 +22,7 @@ except ImportError: # pragma: no cover class DbBackup(models.Model): + _description = 'Database Backup' _name = 'db.backup' _inherit = "mail.thread" @@ -31,59 +33,52 @@ class DbBackup(models.Model): ] name = fields.Char( - string="Name", compute="_compute_name", store=True, help="Summary of this backup process", ) folder = fields.Char( default=lambda self: self._default_folder(), - oldname="bkp_dir", help='Absolute path for storing the backups', required=True ) days_to_keep = fields.Integer( - oldname="daystokeep", required=True, default=0, help="Backups older than this will be deleted automatically. " "Set 0 to disable autodeletion.", ) method = fields.Selection( - selection=[("local", "Local disk"), ("sftp", "Remote SFTP server")], + [("local", "Local disk"), ("sftp", "Remote SFTP server")], default="local", help="Choose the storage method for this backup.", ) sftp_host = fields.Char( - string='SFTP Server', - oldname="sftpip", + 'SFTP Server', help=( "The host name or IP address from your remote" " server. For example 192.168.0.1" ) ) sftp_port = fields.Integer( - string="SFTP Port", + "SFTP Port", default=22, - oldname="sftpport", help="The port on the FTP server that accepts SSH/SFTP calls." ) sftp_user = fields.Char( - string='Username in the SFTP Server', - oldname="sftpusername", + 'Username in the SFTP Server', help=( "The username where the SFTP connection " "should be made with. This is the user on the external server." ) ) sftp_password = fields.Char( - string="SFTP Password", - oldname="sftppassword", + "SFTP Password", help="The password for the SFTP connection. If you specify a private " "key file, then this is the password to decrypt it.", ) sftp_private_key = fields.Char( - string="Private key location", + "Private key location", help="Path to the private key file. Only the Odoo user should have " "read permissions for that file.", ) @@ -111,9 +106,9 @@ class DbBackup(models.Model): @api.constrains("folder", "method") def _check_folder(self): """Do not use the filestore or you will backup your backups.""" - for s in self: - if (s.method == "local" and - s.folder.startswith( + for record in self: + if (record.method == "local" and + record.folder.startswith( tools.config.filestore(self.env.cr.dbname))): raise exceptions.ValidationError( _("Do not save backups on your filestore, or you will " @@ -200,10 +195,10 @@ class DbBackup(models.Model): try: _logger.info("Starting database backup: %s", self.name) yield - except: + except Exception: _logger.exception("Database backup failed: %s", self.name) escaped_tb = tools.html_escape(traceback.format_exc()) - self.message_post( + self.message_post( # pylint: disable=translation-required "

%s

%s
" % ( _("Database backup failed."), escaped_tb), @@ -242,23 +237,25 @@ class DbBackup(models.Model): """Log a possible cleanup failure.""" self.ensure_one() try: - _logger.info("Starting cleanup process after database backup: %s", - self.name) + _logger.info( + "Starting cleanup process after database backup: %s", + self.name) yield - except: + except Exception: _logger.exception("Cleanup of old database backups failed: %s") escaped_tb = tools.html_escape(traceback.format_exc()) - self.message_post( + self.message_post( # pylint: disable=translation-required "

%s

%s
" % ( _("Cleanup of old database backups failed."), escaped_tb), subtype=self.env.ref("auto_backup.failure")) else: - _logger.info("Cleanup of old database backups succeeded: %s", - self.name) + _logger.info( + "Cleanup of old database backups succeeded: %s", + self.name) - @api.model - def filename(self, when): + @staticmethod + def filename(when): """Generate a file name for a backup. :param datetime.datetime when: diff --git a/auto_backup/tests/__init__.py b/auto_backup/tests/__init__.py index e803c71af..0bf2c8649 100644 --- a/auto_backup/tests/__init__.py +++ b/auto_backup/tests/__init__.py @@ -1,7 +1,3 @@ -# -*- coding: utf-8 -*- -# © 2015 Agile Business Group -# © 2015 Alessio Gerace -# © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import test_db_backup diff --git a/auto_backup/tests/test_db_backup.py b/auto_backup/tests/test_db_backup.py index 91305a0aa..eac650c9b 100644 --- a/auto_backup/tests/test_db_backup.py +++ b/auto_backup/tests/test_db_backup.py @@ -1,18 +1,17 @@ -# -*- coding: utf-8 -*- # © 2015 Agile Business Group # © 2015 Alessio Gerace # © 2016 Grupo ESOC Ingeniería de Servicios, S.L.U. - Jairo Llopis # Copyright 2016 LasLabs Inc. -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import os -import mock - -from datetime import datetime from contextlib import contextmanager +from datetime import datetime, timedelta + +import mock -from odoo.tests import common from odoo import exceptions, tools +from odoo.tests import common try: import pysftp @@ -127,6 +126,23 @@ class TestDbBackup(common.TransactionCase): if f >= filename] self.assertEqual(1, len(generated_backup)) + def test_action_backup_local_cleanup(self): + """ Backup local database and cleanup old databases """ + rec_id = self.new_record('local') + rec_id.days_to_keep = 1 + old_date = datetime.now() - timedelta(days=3) + filename = rec_id.filename(old_date) + rec_id.action_backup() + generated_backup = [f for f in os.listdir(rec_id.folder) + if f >= filename] + self.assertEqual(2, len(generated_backup)) + + filename = rec_id.filename(datetime.now()) + rec_id.action_backup() + generated_backup = [f for f in os.listdir(rec_id.folder) + if f >= filename] + self.assertEqual(1, len(generated_backup)) + def test_action_backup_sftp_mkdirs(self): """ It should create remote dirs """ rec_id = self.new_record() diff --git a/auto_backup/view/db_backup_view.xml b/auto_backup/view/db_backup_view.xml index 23731135e..42f826feb 100644 --- a/auto_backup/view/db_backup_view.xml +++ b/auto_backup/view/db_backup_view.xml @@ -1,14 +1,16 @@ - + - - Automated Backups + db.backup - form
-

- +
+
+
+

+
@@ -47,27 +49,23 @@ - - Automated Backups + db.backup - tree - - - - + + + + - - Automated Backups + db.backup - search - - - + + + @@ -86,22 +84,11 @@ Execute backup(s) - - - object.action_backup() - - - - - Execute backup(s) - - - action + ir.actions.server - db.backup - client_action_multi + + code + records.action_backup() diff --git a/requirements.txt b/requirements.txt index a9a1eff29..0c7442de7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ checksumdir raven +pysftp