From 7378a8fefd55b9e819fb292f83042d0d9f1cb41e Mon Sep 17 00:00:00 2001 From: tarteo Date: Wed, 6 Dec 2023 15:31:46 +0100 Subject: [PATCH 1/5] [ADD][16.0] fs_storage_backup Run black [ADD] tests [FIX] Tests [FIX] Tests [ADD] Misconfig tests fixup Fixup --- fs_storage_backup/README.rst | 103 ++++ fs_storage_backup/__init__.py | 1 + fs_storage_backup/__manifest__.py | 14 + fs_storage_backup/data/ir_cron_data.xml | 18 + .../data/mail_message_subtype_data.xml | 15 + fs_storage_backup/models/__init__.py | 1 + fs_storage_backup/models/fs_storage.py | 116 +++++ fs_storage_backup/readme/CONFIGURE.md | 7 + fs_storage_backup/readme/CONTRIBUTORS.md | 1 + fs_storage_backup/readme/DESCRIPTION.md | 1 + fs_storage_backup/readme/ROADMAP.md | 1 + fs_storage_backup/readme/USAGE.md | 1 + .../static/description/index.html | 452 ++++++++++++++++++ fs_storage_backup/tests/__init__.py | 1 + fs_storage_backup/tests/test_backup.py | 58 +++ fs_storage_backup/views/fs_storage_view.xml | 35 ++ 16 files changed, 825 insertions(+) create mode 100644 fs_storage_backup/README.rst create mode 100644 fs_storage_backup/__init__.py create mode 100644 fs_storage_backup/__manifest__.py create mode 100644 fs_storage_backup/data/ir_cron_data.xml create mode 100644 fs_storage_backup/data/mail_message_subtype_data.xml create mode 100644 fs_storage_backup/models/__init__.py create mode 100644 fs_storage_backup/models/fs_storage.py create mode 100644 fs_storage_backup/readme/CONFIGURE.md create mode 100644 fs_storage_backup/readme/CONTRIBUTORS.md create mode 100644 fs_storage_backup/readme/DESCRIPTION.md create mode 100644 fs_storage_backup/readme/ROADMAP.md create mode 100644 fs_storage_backup/readme/USAGE.md create mode 100644 fs_storage_backup/static/description/index.html create mode 100644 fs_storage_backup/tests/__init__.py create mode 100644 fs_storage_backup/tests/test_backup.py create mode 100644 fs_storage_backup/views/fs_storage_view.xml diff --git a/fs_storage_backup/README.rst b/fs_storage_backup/README.rst new file mode 100644 index 0000000000..319f2c8f33 --- /dev/null +++ b/fs_storage_backup/README.rst @@ -0,0 +1,103 @@ +========================= +Filesystem Storage Backup +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:58d2fd55ddd0a80685cbd1df4e905793535d2214d39e43e8922b582888e61763 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github + :target: https://github.com/OCA/storage/tree/16.0/fs_storage_backup + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-fs_storage_backup + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +With this module you can configure one or more database backup +locations. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +1. Go to Settings > Technical > FS Storage > FS Storage +2. Select a filesystem you want to use for backups. **NOTE: Make sure + you don't use the filestore as backup location otherwise it's + possible you'll back up the backup** +3. Enable ``Use For Backups`` +4. Follow it (using the chatter) if you want to get notified when a + backup fails +5. To know if the backup is working correctly you can run the scheduled + action (``Backup database and delete old backups``) manually to test + it. + +Usage +===== + +The backup is done automatically by a scheduled action +(``Backup database and delete old backups``). + +Known issues / Roadmap +====================== + +- **Configurable backup frequency**: e.g. backup every 7 days in s3 and + every 4 hours on a FTP server. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Onestein + +Contributors +------------ + +- Dennis Sluijk d.sluijk@onestein.nl (https://onestein.nl) + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/storage `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fs_storage_backup/__init__.py b/fs_storage_backup/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/fs_storage_backup/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/fs_storage_backup/__manifest__.py b/fs_storage_backup/__manifest__.py new file mode 100644 index 0000000000..7b5a0bc64a --- /dev/null +++ b/fs_storage_backup/__manifest__.py @@ -0,0 +1,14 @@ +{ + "name": "Filesystem Storage Backup", + "category": "Technical", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "Onestein, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/storage", + "depends": ["fs_storage", "mail"], + "data": [ + "data/ir_cron_data.xml", + "data/mail_message_subtype_data.xml", + "views/fs_storage_view.xml", + ], +} diff --git a/fs_storage_backup/data/ir_cron_data.xml b/fs_storage_backup/data/ir_cron_data.xml new file mode 100644 index 0000000000..c343f1f3ed --- /dev/null +++ b/fs_storage_backup/data/ir_cron_data.xml @@ -0,0 +1,18 @@ + + + + Backup database and delete old backups + 1 + days + -1 + True + + + code + model.cron_backup_db() + + + diff --git a/fs_storage_backup/data/mail_message_subtype_data.xml b/fs_storage_backup/data/mail_message_subtype_data.xml new file mode 100644 index 0000000000..e56ff2c210 --- /dev/null +++ b/fs_storage_backup/data/mail_message_subtype_data.xml @@ -0,0 +1,15 @@ + + + + Backup Failed + Backup failed + fs.storage + + + + Backup Cleanup Failed + Failed to clean up old backups + fs.storage + + + diff --git a/fs_storage_backup/models/__init__.py b/fs_storage_backup/models/__init__.py new file mode 100644 index 0000000000..349bb0495a --- /dev/null +++ b/fs_storage_backup/models/__init__.py @@ -0,0 +1 @@ +from . import fs_storage diff --git a/fs_storage_backup/models/fs_storage.py b/fs_storage_backup/models/fs_storage.py new file mode 100644 index 0000000000..8a4dcccbfe --- /dev/null +++ b/fs_storage_backup/models/fs_storage.py @@ -0,0 +1,116 @@ +import logging +import traceback +from datetime import timedelta, timezone +from os import path + +from odoo import _, api, fields, models, tools +from odoo.exceptions import ValidationError +from odoo.service import db + +_logger = logging.getLogger(__name__) + + +class FSStorage(models.Model): + _name = "fs.storage" + _inherit = ["fs.storage", "mail.thread"] # Use queue_job_cron instead? + + use_for_backup = fields.Boolean(string="Use For Backups") + backup_include_filestore = fields.Boolean( + string="Include Filestore In Backup", + ) + backup_filename_format = fields.Char( + string="Backup Filename", default="backup-%(db)s-%(dt)s.%(ext)s" + ) + backup_keep_time = fields.Integer(string="Keep backups of (in days)", default=7) + backup_dir = fields.Char(string="Backup Directory", default="backups") + + @property + def _server_env_fields(self): + env_fields = super()._server_env_fields + env_fields.update( + { + "use_for_backup": {}, + "backup_include_filestore": {}, + "backup_filename_format": {"no_default_field": False}, + "backup_keep_time": {"no_default_field": False}, + "backup_dir": {"no_default_field": False}, + } + ) + return env_fields + + @api.constrains("backup_keep_time") + def _constrain_backup_keep_time(self): + if self.backup_keep_time < 1: + raise ValidationError( + _("Keep backups of (in days) must be greater or than 0.") + ) + + def _get_backup_format(self): + self.ensure_one() + return self.backup_include_filestore and "zip" or "dump" + + def _get_backup_path(self): + self.ensure_one() + file_ext = self._get_backup_format() + current_datetime = fields.Datetime.now().strftime("%Y%m%d%H%M%S") + return path.join( + self.backup_dir, + self.backup_filename_format + % {"db": self.env.cr.dbname, "dt": current_datetime, "ext": file_ext}, + ) + + def backup_db(self): + self.ensure_one() + try: + backup_path = self._get_backup_path() + self.fs.makedirs(self.backup_dir, exist_ok=True) + if self.fs.exists(backup_path): + raise Exception("File already exists (%s)." % backup_path) + backup_file = self.fs.open(backup_path, "w") + list_db = tools.config["list_db"] + if not list_db: + tools.config["list_db"] = True + db.dump_db( + self.env.cr.dbname, + backup_file.buffer, + backup_format=self._get_backup_format(), + ) + tools.config["list_db"] = list_db + except Exception as e: + _logger.exception("Database backup failed: %s", e) + self.message_post( + subject=_("Database backup failed"), + body="
%s
" % tools.html_escape(traceback.format_exc()), + subtype_id=self.env.ref( + "fs_storage_backup.message_subtype_backup_failed" + ).id, + ) + + def cleanup_old_backups(self): + self.ensure_one() + expiry_date = fields.Datetime.now() - timedelta(days=self.backup_keep_time) + try: + files = self.fs.ls(self.backup_dir, detail=False) + for file_path in files: + file_dt = self.fs.modified(file_path) + file_dt = file_dt.astimezone(timezone.utc) + file_dt = file_dt.replace(tzinfo=None) + if file_dt < expiry_date: + self.fs.rm(file_path) + except Exception as e: + _logger.exception("Failed to clean up old backups: %s", e) + self.message_post( + subject=_("Failed to clean up old backups"), + body="
%s
" % tools.html_escape(traceback.format_exc()), + subtype_id=self.env.ref( + "fs_storage_backup.message_subtype_cleanup_failed" + ).id, + ) + + @api.model + def cron_backup_db(self): + # use_for_backup is not searchable + storages = self.search([]) + for storage in storages.filtered(lambda s: s.use_for_backup): + storage.backup_db() + storage.cleanup_old_backups() diff --git a/fs_storage_backup/readme/CONFIGURE.md b/fs_storage_backup/readme/CONFIGURE.md new file mode 100644 index 0000000000..8d674feed7 --- /dev/null +++ b/fs_storage_backup/readme/CONFIGURE.md @@ -0,0 +1,7 @@ +1. Go to Settings > Technical > FS Storage > FS Storage +2. Select a filesystem you want to use for backups. + **NOTE: Make sure you don't use the filestore as backup location otherwise it's possible you'll back up the backup** +3. Enable `Use For Backups` +4. Follow it (using the chatter) if you want to get notified when a backup fails +5. To know if the backup is working correctly you can run the scheduled action + (`Backup database and delete old backups`) manually to test it. diff --git a/fs_storage_backup/readme/CONTRIBUTORS.md b/fs_storage_backup/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..8a94e6002f --- /dev/null +++ b/fs_storage_backup/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Dennis Sluijk (https://onestein.nl) diff --git a/fs_storage_backup/readme/DESCRIPTION.md b/fs_storage_backup/readme/DESCRIPTION.md new file mode 100644 index 0000000000..25f1c1b1fa --- /dev/null +++ b/fs_storage_backup/readme/DESCRIPTION.md @@ -0,0 +1 @@ +With this module you can configure one or more database backup locations. \ No newline at end of file diff --git a/fs_storage_backup/readme/ROADMAP.md b/fs_storage_backup/readme/ROADMAP.md new file mode 100644 index 0000000000..9727d47a68 --- /dev/null +++ b/fs_storage_backup/readme/ROADMAP.md @@ -0,0 +1 @@ +- **Configurable backup frequency**: e.g. backup every 7 days in s3 and every 4 hours on a FTP server. \ No newline at end of file diff --git a/fs_storage_backup/readme/USAGE.md b/fs_storage_backup/readme/USAGE.md new file mode 100644 index 0000000000..be546dce1e --- /dev/null +++ b/fs_storage_backup/readme/USAGE.md @@ -0,0 +1 @@ +The backup is done automatically by a scheduled action (`Backup database and delete old backups`). \ No newline at end of file diff --git a/fs_storage_backup/static/description/index.html b/fs_storage_backup/static/description/index.html new file mode 100644 index 0000000000..a53df4721d --- /dev/null +++ b/fs_storage_backup/static/description/index.html @@ -0,0 +1,452 @@ + + + + + + +Filesystem Storage Backup + + + +
+

Filesystem Storage Backup

+ + +

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

With this module you can configure one or more database backup +locations.

+

Table of contents

+ +
+

Configuration

+
    +
  1. Go to Settings > Technical > FS Storage > FS Storage
  2. +
  3. Select a filesystem you want to use for backups. NOTE: Make sure +you don’t use the filestore as backup location otherwise it’s +possible you’ll back up the backup
  4. +
  5. Enable Use For Backups
  6. +
  7. Follow it (using the chatter) if you want to get notified when a +backup fails
  8. +
  9. To know if the backup is working correctly you can run the scheduled +action (Backup database and delete old backups) manually to test +it.
  10. +
+
+
+

Usage

+

The backup is done automatically by a scheduled action +(Backup database and delete old backups).

+
+
+

Known issues / Roadmap

+
    +
  • Configurable backup frequency: e.g. backup every 7 days in s3 and +every 4 hours on a FTP server.
  • +
+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Onestein
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/storage project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/fs_storage_backup/tests/__init__.py b/fs_storage_backup/tests/__init__.py new file mode 100644 index 0000000000..8b6238c52d --- /dev/null +++ b/fs_storage_backup/tests/__init__.py @@ -0,0 +1 @@ +from . import test_backup diff --git a/fs_storage_backup/tests/test_backup.py b/fs_storage_backup/tests/test_backup.py new file mode 100644 index 0000000000..b6662dafd1 --- /dev/null +++ b/fs_storage_backup/tests/test_backup.py @@ -0,0 +1,58 @@ +from odoo.tests.common import TransactionCase + + +class TestBackup(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.fs_storage = cls.env.ref("fs_storage.default_fs_storage") + cls.fs_storage.use_for_backup = True + cls.fs_storage.backup_dir = "backups" + cls.fs_storage.backup_filename_format = "backup-%(db)s-%(dt)s.%(ext)s" + cls.fs_storage.backup_keep_time = 7 + + def test_with_filestore(self): + self.fs_storage.backup_include_filestore = True + old_counts = {} + for fs_storage in self.env["fs.storage"].search( + [("use_for_backup", "=", True)] + ): + fs_storage.fs.makedirs(fs_storage.backup_dir, exist_ok=True) + old_counts[fs_storage.id] = len( + fs_storage.fs.ls(fs_storage.backup_dir, detail=False) + ) + self.env["fs.storage"].cron_backup_db() # Backup all locations + for fs_storage in self.env["fs.storage"].search( + [("use_for_backup", "=", True)] + ): + new_count = len(fs_storage.fs.ls(fs_storage.backup_dir, detail=False)) + self.assertEqual(old_counts[fs_storage.id] + 1, new_count) + + def test_without_filestore(self): + self.fs_storage.fs.makedirs(self.fs_storage.backup_dir, exist_ok=True) + files = self.fs_storage.fs.ls(self.fs_storage.backup_dir, detail=False) + old_count = len(list(filter(lambda f: f.endswith(".dump"), files))) + self.fs_storage.backup_include_filestore = False + self.fs_storage.backup_db() + files = self.fs_storage.fs.ls(self.fs_storage.backup_dir, detail=False) + new_count = len(list(filter(lambda f: f.endswith(".dump"), files))) + self.assertEqual(old_count + 1, new_count) + + def test_cleanup_no_dir(self): + self.fs_storage.backup_dir = "backups123" + with self.assertLogs(level="ERROR"): + self.fs_storage.cleanup_old_backups() + + def test_no_connection(self): + fs_storage = self.env["fs.storage"].create( + { + "name": "FTP", + "code": "ftp", + "protocol": "ftp", + "directory_path": ".", + "options": '{"host": "host", "port": 21}', # Non existent host + "use_for_backup": True, + } + ) + with self.assertLogs(level="ERROR"): + fs_storage.backup_db() diff --git a/fs_storage_backup/views/fs_storage_view.xml b/fs_storage_backup/views/fs_storage_view.xml new file mode 100644 index 0000000000..398ab2f0c9 --- /dev/null +++ b/fs_storage_backup/views/fs_storage_view.xml @@ -0,0 +1,35 @@ + + + + + fs.storage + + + + + + + + + + +
+ + +
+
+
+
+
From 8775acf3391d80d14b04501a00bb889c2a9a35f9 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 3 Apr 2025 14:12:21 +0000 Subject: [PATCH 2/5] [UPD] Update fs_storage_backup.pot --- fs_storage_backup/i18n/fs_storage_backup.pot | 177 +++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 fs_storage_backup/i18n/fs_storage_backup.pot diff --git a/fs_storage_backup/i18n/fs_storage_backup.pot b/fs_storage_backup/i18n/fs_storage_backup.pot new file mode 100644 index 0000000000..15799348b4 --- /dev/null +++ b/fs_storage_backup/i18n/fs_storage_backup.pot @@ -0,0 +1,177 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fs_storage_backup +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,name:fs_storage_backup.message_subtype_cleanup_failed +msgid "Backup Cleanup Failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_dir +msgid "Backup Directory" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,name:fs_storage_backup.message_subtype_backup_failed +msgid "Backup Failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_filename_format +msgid "Backup Filename" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.actions.server,name:fs_storage_backup.cron_backup_db_ir_actions_server +#: model:ir.cron,cron_name:fs_storage_backup.cron_backup_db +msgid "Backup database and delete old backups" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,description:fs_storage_backup.message_subtype_backup_failed +msgid "Backup failed" +msgstr "" + +#. module: fs_storage_backup +#: model_terms:ir.ui.view,arch_db:fs_storage_backup.fs_storage_form_view +msgid "Backups" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#, python-format +msgid "Database backup failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model,name:fs_storage_backup.model_fs_storage +msgid "FS Storage" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#: model:mail.message.subtype,description:fs_storage_backup.message_subtype_cleanup_failed +#, python-format +msgid "Failed to clean up old backups" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__has_message +msgid "Has Message" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_include_filestore +msgid "Include Filestore In Backup" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_keep_time +msgid "Keep backups of (in days)" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#, python-format +msgid "Keep backups of (in days) must be greater or than 0." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_ids +msgid "Messages" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_needaction_counter +msgid "Number of messages requiring action" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__use_for_backup +msgid "Use For Backups" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__website_message_ids +msgid "Website communication history" +msgstr "" From 3950d23c6fb3208ef58baf9104ef73f2aa848189 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 3 Apr 2025 14:15:13 +0000 Subject: [PATCH 3/5] [BOT] post-merge updates --- fs_storage_backup/README.rst | 8 ++++---- fs_storage_backup/__manifest__.py | 2 +- fs_storage_backup/static/description/icon.png | Bin 0 -> 10254 bytes fs_storage_backup/static/description/index.html | 14 ++++++++------ 4 files changed, 13 insertions(+), 11 deletions(-) create mode 100644 fs_storage_backup/static/description/icon.png diff --git a/fs_storage_backup/README.rst b/fs_storage_backup/README.rst index 319f2c8f33..0e1f8b9463 100644 --- a/fs_storage_backup/README.rst +++ b/fs_storage_backup/README.rst @@ -7,7 +7,7 @@ Filesystem Storage Backup !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:58d2fd55ddd0a80685cbd1df4e905793535d2214d39e43e8922b582888e61763 + !! source digest: sha256:3292ef4f97f5dcf8a5364cba204599da2169dd30020b9b488ddb72885f85f85b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -59,8 +59,8 @@ The backup is done automatically by a scheduled action Known issues / Roadmap ====================== -- **Configurable backup frequency**: e.g. backup every 7 days in s3 and - every 4 hours on a FTP server. +- **Configurable backup frequency**: e.g. backup every 7 days in s3 and + every 4 hours on a FTP server. Bug Tracker =========== @@ -83,7 +83,7 @@ Authors Contributors ------------ -- Dennis Sluijk d.sluijk@onestein.nl (https://onestein.nl) +- Dennis Sluijk d.sluijk@onestein.nl (https://onestein.nl) Maintainers ----------- diff --git a/fs_storage_backup/__manifest__.py b/fs_storage_backup/__manifest__.py index 7b5a0bc64a..4f1acec351 100644 --- a/fs_storage_backup/__manifest__.py +++ b/fs_storage_backup/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Filesystem Storage Backup", "category": "Technical", - "version": "16.0.1.0.0", + "version": "16.0.1.0.1", "license": "AGPL-3", "author": "Onestein, Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/fs_storage_backup/static/description/icon.png b/fs_storage_backup/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 @@ -9,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -367,7 +367,7 @@

Filesystem Storage Backup

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:58d2fd55ddd0a80685cbd1df4e905793535d2214d39e43e8922b582888e61763 +!! source digest: sha256:3292ef4f97f5dcf8a5364cba204599da2169dd30020b9b488ddb72885f85f85b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

With this module you can configure one or more database backup @@ -439,7 +439,9 @@

Contributors

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

From f18ed7aab2cbef23417202cc524bf887ebb0bf92 Mon Sep 17 00:00:00 2001 From: mymage Date: Sat, 5 Apr 2025 13:49:22 +0000 Subject: [PATCH 4/5] Added translation using Weblate (Italian) --- fs_storage_backup/i18n/it.po | 178 +++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 fs_storage_backup/i18n/it.po diff --git a/fs_storage_backup/i18n/it.po b/fs_storage_backup/i18n/it.po new file mode 100644 index 0000000000..e571d295b1 --- /dev/null +++ b/fs_storage_backup/i18n/it.po @@ -0,0 +1,178 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * fs_storage_backup +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,name:fs_storage_backup.message_subtype_cleanup_failed +msgid "Backup Cleanup Failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_dir +msgid "Backup Directory" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,name:fs_storage_backup.message_subtype_backup_failed +msgid "Backup Failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_filename_format +msgid "Backup Filename" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.actions.server,name:fs_storage_backup.cron_backup_db_ir_actions_server +#: model:ir.cron,cron_name:fs_storage_backup.cron_backup_db +msgid "Backup database and delete old backups" +msgstr "" + +#. module: fs_storage_backup +#: model:mail.message.subtype,description:fs_storage_backup.message_subtype_backup_failed +msgid "Backup failed" +msgstr "" + +#. module: fs_storage_backup +#: model_terms:ir.ui.view,arch_db:fs_storage_backup.fs_storage_form_view +msgid "Backups" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#, python-format +msgid "Database backup failed" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model,name:fs_storage_backup.model_fs_storage +msgid "FS Storage" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#: model:mail.message.subtype,description:fs_storage_backup.message_subtype_cleanup_failed +#, python-format +msgid "Failed to clean up old backups" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__has_message +msgid "Has Message" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_include_filestore +msgid "Include Filestore In Backup" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__backup_keep_time +msgid "Keep backups of (in days)" +msgstr "" + +#. module: fs_storage_backup +#. odoo-python +#: code:addons/fs_storage_backup/models/fs_storage.py:0 +#, python-format +msgid "Keep backups of (in days) must be greater or than 0." +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_ids +msgid "Messages" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__message_has_error_counter +msgid "Number of errors" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_needaction_counter +msgid "Number of messages requiring action" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__use_for_backup +msgid "Use For Backups" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,field_description:fs_storage_backup.field_fs_storage__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: fs_storage_backup +#: model:ir.model.fields,help:fs_storage_backup.field_fs_storage__website_message_ids +msgid "Website communication history" +msgstr "" From d1accbf8998d430cc7a3bb5cfebd3dfed9c63be9 Mon Sep 17 00:00:00 2001 From: tarteo Date: Wed, 7 May 2025 15:20:31 +0200 Subject: [PATCH 5/5] [MIG] fs_storage_backup: Migration to 18.0 fs_storage_backup: Use body_is_html in post_message Update tests to new demo data Fixup tests --- fs_storage_backup/README.rst | 10 ++++---- fs_storage_backup/__manifest__.py | 2 +- fs_storage_backup/data/ir_cron_data.xml | 2 -- fs_storage_backup/models/fs_storage.py | 10 +++++--- fs_storage_backup/pyproject.toml | 3 +++ .../static/description/index.html | 6 ++--- fs_storage_backup/tests/test_backup.py | 13 +++++----- fs_storage_backup/views/fs_storage_view.xml | 25 ++++--------------- 8 files changed, 29 insertions(+), 42 deletions(-) create mode 100644 fs_storage_backup/pyproject.toml diff --git a/fs_storage_backup/README.rst b/fs_storage_backup/README.rst index 0e1f8b9463..29b792d90a 100644 --- a/fs_storage_backup/README.rst +++ b/fs_storage_backup/README.rst @@ -17,13 +17,13 @@ Filesystem Storage Backup :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github - :target: https://github.com/OCA/storage/tree/16.0/fs_storage_backup + :target: https://github.com/OCA/storage/tree/18.0/fs_storage_backup :alt: OCA/storage .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-fs_storage_backup + :target: https://translation.odoo-community.org/projects/storage-18-0/storage-18-0-fs_storage_backup :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -68,7 +68,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 to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -98,6 +98,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/storage `_ project on GitHub. +This module is part of the `OCA/storage `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fs_storage_backup/__manifest__.py b/fs_storage_backup/__manifest__.py index 4f1acec351..7e8ffb9a33 100644 --- a/fs_storage_backup/__manifest__.py +++ b/fs_storage_backup/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Filesystem Storage Backup", "category": "Technical", - "version": "16.0.1.0.1", + "version": "18.0.1.0.0", "license": "AGPL-3", "author": "Onestein, Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/fs_storage_backup/data/ir_cron_data.xml b/fs_storage_backup/data/ir_cron_data.xml index c343f1f3ed..caa841405e 100644 --- a/fs_storage_backup/data/ir_cron_data.xml +++ b/fs_storage_backup/data/ir_cron_data.xml @@ -4,9 +4,7 @@ Backup database and delete old backups 1 days - -1 True - code model.cron_backup_db() diff --git a/fs_storage_backup/models/fs_storage.py b/fs_storage_backup/models/fs_storage.py index 8a4dcccbfe..f7a26350ea 100644 --- a/fs_storage_backup/models/fs_storage.py +++ b/fs_storage_backup/models/fs_storage.py @@ -12,7 +12,7 @@ class FSStorage(models.Model): _name = "fs.storage" - _inherit = ["fs.storage", "mail.thread"] # Use queue_job_cron instead? + _inherit = ["fs.storage", "mail.thread"] use_for_backup = fields.Boolean(string="Use For Backups") backup_include_filestore = fields.Boolean( @@ -65,7 +65,7 @@ def backup_db(self): backup_path = self._get_backup_path() self.fs.makedirs(self.backup_dir, exist_ok=True) if self.fs.exists(backup_path): - raise Exception("File already exists (%s)." % backup_path) + raise Exception(f"File already exists ({backup_path}).") backup_file = self.fs.open(backup_path, "w") list_db = tools.config["list_db"] if not list_db: @@ -80,7 +80,8 @@ def backup_db(self): _logger.exception("Database backup failed: %s", e) self.message_post( subject=_("Database backup failed"), - body="
%s
" % tools.html_escape(traceback.format_exc()), + body=f"
{tools.html_escape(traceback.format_exc())}
", + body_is_html=True, subtype_id=self.env.ref( "fs_storage_backup.message_subtype_backup_failed" ).id, @@ -101,7 +102,8 @@ def cleanup_old_backups(self): _logger.exception("Failed to clean up old backups: %s", e) self.message_post( subject=_("Failed to clean up old backups"), - body="
%s
" % tools.html_escape(traceback.format_exc()), + body=f"
{tools.html_escape(traceback.format_exc())}
", + body_is_html=True, subtype_id=self.env.ref( "fs_storage_backup.message_subtype_cleanup_failed" ).id, diff --git a/fs_storage_backup/pyproject.toml b/fs_storage_backup/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/fs_storage_backup/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fs_storage_backup/static/description/index.html b/fs_storage_backup/static/description/index.html index e526d670f9..81453ac1df 100644 --- a/fs_storage_backup/static/description/index.html +++ b/fs_storage_backup/static/description/index.html @@ -369,7 +369,7 @@

Filesystem Storage Backup

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:3292ef4f97f5dcf8a5364cba204599da2169dd30020b9b488ddb72885f85f85b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

With this module you can configure one or more database backup locations.

Table of contents

@@ -419,7 +419,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 to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -445,7 +445,7 @@

Maintainers

OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

-

This module is part of the OCA/storage project on GitHub.

+

This module is part of the OCA/storage project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/fs_storage_backup/tests/test_backup.py b/fs_storage_backup/tests/test_backup.py index b6662dafd1..c6321ac238 100644 --- a/fs_storage_backup/tests/test_backup.py +++ b/fs_storage_backup/tests/test_backup.py @@ -5,7 +5,7 @@ class TestBackup(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.fs_storage = cls.env.ref("fs_storage.default_fs_storage") + cls.fs_storage = cls.env.ref("fs_storage.fs_storage_demo") cls.fs_storage.use_for_backup = True cls.fs_storage.backup_dir = "backups" cls.fs_storage.backup_filename_format = "backup-%(db)s-%(dt)s.%(ext)s" @@ -14,17 +14,16 @@ def setUpClass(cls): def test_with_filestore(self): self.fs_storage.backup_include_filestore = True old_counts = {} - for fs_storage in self.env["fs.storage"].search( - [("use_for_backup", "=", True)] - ): + backup_locations = ( + self.env["fs.storage"].search([]).filtered(lambda r: r.use_for_backup) + ) + for fs_storage in backup_locations: fs_storage.fs.makedirs(fs_storage.backup_dir, exist_ok=True) old_counts[fs_storage.id] = len( fs_storage.fs.ls(fs_storage.backup_dir, detail=False) ) self.env["fs.storage"].cron_backup_db() # Backup all locations - for fs_storage in self.env["fs.storage"].search( - [("use_for_backup", "=", True)] - ): + for fs_storage in backup_locations: new_count = len(fs_storage.fs.ls(fs_storage.backup_dir, detail=False)) self.assertEqual(old_counts[fs_storage.id] + 1, new_count) diff --git a/fs_storage_backup/views/fs_storage_view.xml b/fs_storage_backup/views/fs_storage_view.xml index 398ab2f0c9..d0e7994bec 100644 --- a/fs_storage_backup/views/fs_storage_view.xml +++ b/fs_storage_backup/views/fs_storage_view.xml @@ -7,28 +7,13 @@ - - - - + + + + -
- - -
+