From c1335a72d9ac2b169e0c3ffde522e8e89d50bf17 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Sat, 4 Feb 2023 19:35:43 +0100 Subject: [PATCH] copr: incremental backup to storinator, part 1 These scripts are based on my personal "Don't Delay Backups" project, which is not yet available as a public role. --- inventory/group_vars/copr_aws | 10 +++ playbooks/groups/copr-backend.yml | 2 + roles/rsnapshot-push/defaults/main.yml | 15 ++++ roles/rsnapshot-push/tasks/main.yml | 55 ++++++++++++++ .../templates/client-backup-script.sh.j2 | 8 +++ .../templates/server-daemon.sh.j2 | 57 +++++++++++++++ .../templates/server-rsnapshot.py.j2 | 71 +++++++++++++++++++ 7 files changed, 218 insertions(+) create mode 100644 roles/rsnapshot-push/defaults/main.yml create mode 100644 roles/rsnapshot-push/tasks/main.yml create mode 100644 roles/rsnapshot-push/templates/client-backup-script.sh.j2 create mode 100644 roles/rsnapshot-push/templates/server-daemon.sh.j2 create mode 100644 roles/rsnapshot-push/templates/server-rsnapshot.py.j2 diff --git a/inventory/group_vars/copr_aws b/inventory/group_vars/copr_aws index 8150c7e845..f2413265e0 100644 --- a/inventory/group_vars/copr_aws +++ b/inventory/group_vars/copr_aws @@ -75,3 +75,13 @@ root_auth_users: msuchy frostyx praiskup nikromen aws_cloudfront_distribution: E2PUZIRCXCOXTG nrpe_client_uid: 500 + +rsnapshot_push: + server_host: storinator01.rdu-cc.fedoraproject.org + backup_dir: /srv/nfs/copr-be + timing_plan: copr_be + cases: + copr-be-copr-user: + user: copr + rsync_args: --relative /home/copr/provision + command: rsnapshot_copr_backend diff --git a/playbooks/groups/copr-backend.yml b/playbooks/groups/copr-backend.yml index 8a16048714..a88a2f82be 100644 --- a/playbooks/groups/copr-backend.yml +++ b/playbooks/groups/copr-backend.yml @@ -62,3 +62,5 @@ - copr/backend - role: messaging/base when: copr_messaging + - role: rsnapshot-push + when: env == "production" diff --git a/roles/rsnapshot-push/defaults/main.yml b/roles/rsnapshot-push/defaults/main.yml new file mode 100644 index 0000000000..7d51cd96c5 --- /dev/null +++ b/roles/rsnapshot-push/defaults/main.yml @@ -0,0 +1,15 @@ +--- +rsnapshot_push_defaults: + timing_plans: + normal: + push: [0, 25] + daily: [86400, 10] + weekly: [604800, 4] + monthly: [2592000, 6] + yearly: [31536000, 3] + + # we can't keep monthly increments for too large deltas + copr_be: + # Sunday / Wednesday + push: [0, 3] + biweekly: [1209600, 3] diff --git a/roles/rsnapshot-push/tasks/main.yml b/roles/rsnapshot-push/tasks/main.yml new file mode 100644 index 0000000000..968c7bc8ef --- /dev/null +++ b/roles/rsnapshot-push/tasks/main.yml @@ -0,0 +1,55 @@ +--- +- name: backup script + template: + src: client-backup-script.sh.j2 + dest: /usr/local/bin/"{{ item.value.command }}" + owner: "{{ item.value.user }}" + group: "{{ item.value.user }}" + mode: 0700 + with_dict: + - "{{ rsnapshot_push.cases }}" + tags: rsnapshot_push + +- name: server-side case-specific backup dir + file: + path: "{{ '/'.join([rsnapshot_push.backup_dir, item.key]) }}" + state: directory + owner: "{{ item.value.user }}" + group: "{{ item.value.user }}" + mode: 0700 + delegate_to: "{{ rsnapshot_push.server_host }}" + tags: rsnapshot_push + +- name: server-side custom rsnapshot daemon script + template: + src: server-daemon.sh.j2 + dest: "{{ '/'.join([rsnapshot_push.backup_dir, item.key, 'sync-daemon']) }}" + owner: "{{ item.value.user }}" + group: "{{ item.value.user }}" + mode: 0700 + with_dict: + - "{{ rsnapshot_push.cases }}" + delegate_to: "{{ rsnapshot_push.server_host }}" + tags: rsnapshot_push + +- name: rsnapshot call wrapper + template: + src: server-rsnapshot.py.j2 + dest: "{{ '/'.join([rsnapshot_push.backup_dir, item.key, 'rsnapshot']) }}" + owner: "{{ item.value.user }}" + group: "{{ item.value.user }}" + mode: 0700 + with_dict: + - "{{ rsnapshot_push.cases }}" + delegate_to: "{{ rsnapshot_push.server_host }}" + tags: rsnapshot_push + +- name: backup praiskup data + cron: name="backup documents - {{ item.key }}" + minute="0/5" + hour="*" + user={{ item.value.user }} + job=/usr/local/bin/"{{ item.value.command }}" + with_dict: + - "{{ rsnapshot_push.cases }}" + tags: rsnapshot_push diff --git a/roles/rsnapshot-push/templates/client-backup-script.sh.j2 b/roles/rsnapshot-push/templates/client-backup-script.sh.j2 new file mode 100644 index 0000000000..776d4ffe45 --- /dev/null +++ b/roles/rsnapshot-push/templates/client-backup-script.sh.j2 @@ -0,0 +1,8 @@ +#! /bin/bash + +# the ::push is defined server-side target + +exec rsync -av --xattrs --acls \ + --delete --delete-excluded \ + {{ item.value.rsync_args }} \ + {{ item.value.user }}@{{ rsnapshot_push.server_host }}::push diff --git a/roles/rsnapshot-push/templates/server-daemon.sh.j2 b/roles/rsnapshot-push/templates/server-daemon.sh.j2 new file mode 100644 index 0000000000..acfdb462d2 --- /dev/null +++ b/roles/rsnapshot-push/templates/server-daemon.sh.j2 @@ -0,0 +1,57 @@ +#! /bin/bash + +dirname=$(dirname "$(readlink -f "$0")" ) +rsync_config=$dirname/rsync.conf +rsnapshot_config=$dirname/rsnapshot.conf + +backup=$dirname/backup +sync_to=$backup/.sync +lock="$dirname/.rsync.lock" +mkdir -p "$sync_to" + +cat >"$rsnapshot_config" <"$rsync_config" < delay: + print("running " + ' '.join(cmd)) + subprocess.check_call(cmd) + database[level] = now + else: + print("skipping " + level) + + +def _main(): + database = _get_db() + try: + rotate(database) + finally: + with open(DB, 'w') as fdb: + fdb.write(json.dumps(database)) + + +if __name__ == "__main__": + _main()