From c80cf0bc78fbbee02a8a3b75599f502e7815ea14 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Fri, 10 May 2024 07:36:57 +0200 Subject: [PATCH 1/4] issue #9 : recover from backup task started --- defaults/main.yml | 11 ++++++++ tasks/main.yml | 12 ++++++++ tasks/recover.yml | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 tasks/recover.yml diff --git a/defaults/main.yml b/defaults/main.yml index 98d019f..62a698c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -57,4 +57,15 @@ openproject_backup_cron: minute: 15 job: "{{ openproject_backup_command }}" +# recover from backup +openproject_recover_from_backup: false + +# expects the files in /var/db/openproject/backup/ +openproject_recover_from_backup_dir: /var/db/openproject/backup/ + +# set this to a defined timestamp, i.e. 20240508065009 +# if 0, we will consider the lates fond in +# /var/db/openproject/backup/ +openproject_recover_from_backup_timestamp: 0 + # vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2 smartindent nu ft=yaml diff --git a/tasks/main.yml b/tasks/main.yml index 16c7913..06f1f88 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -87,4 +87,16 @@ minute: "{{ openproject_backup_cron.minute }}" job: "{{ openproject_backup_cron.job }}" +- name: run recover task + ansible.builtin.include_tasks: + file: recover.yml + apply: + tags: + - recover + - openproject-recover + - openproject_recover_from_backup + when: + - openproject_recover_from_backup is defined + - openproject_recover_from_backup | bool + # vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2 smartindent nu ft=yaml diff --git a/tasks/recover.yml b/tasks/recover.yml new file mode 100644 index 0000000..717c477 --- /dev/null +++ b/tasks/recover.yml @@ -0,0 +1,70 @@ +--- +- name: determine lates timestamp # noqa key-order + block: + - name: get files from {{ openproject_recover_from_backup_dir }} + ansible.builtin.find: + paths: "{{ openproject_recover_from_backup_dir }}" + recurse: false + file_type: file + patterns: conf-*.tar.gz + register: _find_conf + + - name: get latest conf file + ansible.builtin.set_fact: + openproject_recover_from_backup_timestamp: "{{ (_find_conf.files | sort(attribute='ctime') | last).path | regex_replace('.*/conf-', '') | replace('.tar.gz', '') }}" + when: _find_conf.matched | int > 0 + + - name: debug determined timestamp + ansible.builtin.debug: + var: openproject_recover_from_backup_timestamp + verbosity: 1 + + when: openproject_recover_from_backup_timestamp | default(0) | int == 0 + +- name: assert we have a timestamp + ansible.builtin.assert: + that: + - openproject_recover_from_backup_timestamp | int > 0 + +- name: find backup files + ansible.builtin.find: + paths: "{{ openproject_recover_from_backup_dir }}" + recurse: false + file_type: file + patterns: + - "*-{{ openproject_recover_from_backup_timestamp }}.tar.gz" + - "postgresql-dump-{{ openproject_recover_from_backup_timestamp }}.pgdump" + register: _find_backup_files + +- name: extract filenames + ansible.builtin.set_fact: + _files_to_process: "{{ _find_backup_files.files | map(attribute='path') }}" + +- name: debug _files_to_process + ansible.builtin.debug: + var: _files_to_process + verbosity: 1 + +- name: define required files + ansible.builtin.set_fact: + _required_postgresql: "{{ [openproject_recover_from_backup_dir, 'postgresql-dump-' ~ openproject_recover_from_backup_timestamp ~ '.pgdump'] | path_join }}" + _required_conf: "{{ [openproject_recover_from_backup_dir, 'conf-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" + _required_attachments: "{{ [openproject_recover_from_backup_dir, 'attachments-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" + +- name: debug required files + ansible.builtin.debug: + var: item + verbosity: 1 + with_items: + - "{{ _required_postgresql }}" + - "{{ _required_conf }}" + - "{{ _required_attachments }}" + +- name: assert important files are present + ansible.builtin.assert: + that: + - item in _files_to_process + with_items: + - "{{ _required_postgresql }}" + - "{{ _required_conf }}" + - "{{ _required_attachments }}" From 4d7dafa97be3139c0a80642638f0d2f3764b16bb Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Fri, 10 May 2024 08:12:58 +0200 Subject: [PATCH 2/4] issue #9 : recover from backup task started --- tasks/recover.yml | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tasks/recover.yml b/tasks/recover.yml index 717c477..d5f3a52 100644 --- a/tasks/recover.yml +++ b/tasks/recover.yml @@ -51,6 +51,11 @@ _required_conf: "{{ [openproject_recover_from_backup_dir, 'conf-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" _required_attachments: "{{ [openproject_recover_from_backup_dir, 'attachments-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" +- name: define optioonal files + ansible.builtin.set_fact: + _optional_svn: "{{ [openproject_recover_from_backup_dir, 'svn-repositories-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" + _optional_git: "{{ [openproject_recover_from_backup_dir, 'git-repositories-' ~ openproject_recover_from_backup_timestamp ~ '.tar.gz'] | path_join }}" + - name: debug required files ansible.builtin.debug: var: item @@ -60,6 +65,14 @@ - "{{ _required_conf }}" - "{{ _required_attachments }}" +- name: debug optional files + ansible.builtin.debug: + var: item + verbosity: 1 + with_items: + - "{{ _optional_svn }}" + - "{{ _optional_git }}" + - name: assert important files are present ansible.builtin.assert: that: @@ -68,3 +81,46 @@ - "{{ _required_postgresql }}" - "{{ _required_conf }}" - "{{ _required_attachments }}" + +- name: register DATABASE_URL # noqa no-changed-when + ansible.builtin.command: openproject config:get DATABASE_URL + register: _database_url + +- name: debug DATABASE_URL + ansible.builtin.debug: + var: _database_url + verbosity: 1 + +- name: ensure openproject service is stopped + ansible.builtin.service: + name: openproject + state: stopped + +- name: restoring config # noqa command-instead-of-module no-changed-when + ansible.builtin.command: + cmd: "tar xzf {{ _required_conf }} -C /etc/openproject" + +- name: restoring attachments # noqa command-instead-of-module no-changed-when + ansible.builtin.command: + cmd: "tar xzf {{ _required_attachments }} -C /var/db/openproject/files" + +- name: restoring svn repositories # noqa command-instead-of-module no-changed-when + ansible.builtin.command: + cmd: "tar xzf {{ _optional_svn }} -C /var/db/openproject/svn" + when: _optional_svn in _files_to_process + +- name: restoring git repositories # noqa command-instead-of-module no-changed-when + ansible.builtin.command: + cmd: "tar xzf {{ _optional_git }} -C /var/db/openproject/git" + when: _optional_git in _files_to_process + +# TODO remove and recreate the db using community.general.postgresql_db + +- name: restoring database # noqa no-changed-when + ansible.builtin.command: + cmd: "pg_restore --clean --if-exists --dbname {{ _database_url.stdout }} {{ _required_postgresql }}" + +- name: ensure openproject service is started + ansible.builtin.service: + name: openproject + state: started From 33ff11c5ee578f06f358edf674d64ba0c3c95ea8 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Wed, 15 May 2024 20:37:00 +0200 Subject: [PATCH 3/4] issue #9 - run handlers before starting recover --- tasks/main.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasks/main.yml b/tasks/main.yml index 06f1f88..c5517d0 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -87,6 +87,11 @@ minute: "{{ openproject_backup_cron.minute }}" job: "{{ openproject_backup_cron.job }}" +- name: run all notified handlers + ansible.builtin.meta: flush_handlers + tags: + - always + - name: run recover task ansible.builtin.include_tasks: file: recover.yml From be7b95ffd6020cf7af9116fd4fa9ec1db4c1b984 Mon Sep 17 00:00:00 2001 From: Klaus Zerwes Date: Wed, 15 May 2024 20:37:30 +0200 Subject: [PATCH 4/4] issue #9 - recover fixes --- defaults/main.yml | 3 +++ tasks/recover.yml | 28 +++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 62a698c..f208b4c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -68,4 +68,7 @@ openproject_recover_from_backup_dir: /var/db/openproject/backup/ # /var/db/openproject/backup/ openproject_recover_from_backup_timestamp: 0 +# db restore option +openproject_recover_from_backup_dbrestorargs: "--no-owner" + # vim: tabstop=2 expandtab shiftwidth=2 softtabstop=2 smartindent nu ft=yaml diff --git a/tasks/recover.yml b/tasks/recover.yml index d5f3a52..3b6b3c4 100644 --- a/tasks/recover.yml +++ b/tasks/recover.yml @@ -100,15 +100,41 @@ ansible.builtin.command: cmd: "tar xzf {{ _required_conf }} -C /etc/openproject" +- name: ensure file directory exists + ansible.builtin.file: + path: /var/db/openproject/files + state: directory + owner: openproject + group: openproject + mode: '0755' + - name: restoring attachments # noqa command-instead-of-module no-changed-when ansible.builtin.command: cmd: "tar xzf {{ _required_attachments }} -C /var/db/openproject/files" +- name: ensure svn directory exists + ansible.builtin.file: + path: /var/db/openproject/svn + state: directory + owner: openproject + group: openproject + mode: '0755' + when: _optional_svn in _files_to_process + - name: restoring svn repositories # noqa command-instead-of-module no-changed-when ansible.builtin.command: cmd: "tar xzf {{ _optional_svn }} -C /var/db/openproject/svn" when: _optional_svn in _files_to_process +- name: ensure git directory exists + ansible.builtin.file: + path: /var/db/openproject/git + state: directory + owner: openproject + group: openproject + mode: '0755' + when: _optional_git in _files_to_process + - name: restoring git repositories # noqa command-instead-of-module no-changed-when ansible.builtin.command: cmd: "tar xzf {{ _optional_git }} -C /var/db/openproject/git" @@ -118,7 +144,7 @@ - name: restoring database # noqa no-changed-when ansible.builtin.command: - cmd: "pg_restore --clean --if-exists --dbname {{ _database_url.stdout }} {{ _required_postgresql }}" + cmd: "pg_restore --clean --if-exists {{ openproject_recover_from_backup_dbrestorargs }} --dbname {{ _database_url.stdout }} {{ _required_postgresql }}" - name: ensure openproject service is started ansible.builtin.service: