Unverified Commit 734de20c authored by Mattia Rizzolo's avatar Mattia Rizzolo
Browse files

mailman/backup: Use a python script, with which is easier to implement backup rotation

parent 8fa006e9
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@

- name: Backup script
  template:
    src: backup.sh
    dest: /srv/mailman/backup.sh
    src: backup.py
    dest: /srv/mailman/backup.py
    owner: root
    group: root
    mode: 0755
@@ -54,4 +54,4 @@
      job: root
    - env: false
      name: backup
      job: chronic /srv/mailman/backup.sh
      job: chronic /srv/mailman/backup.py
+87 −0
Original line number Diff line number Diff line
#!/usr/bin/python3

#
# {{ ansible_managed }}
#

import os
import re
import sys
import datetime
import tempfile
import subprocess

from pathlib import Path

time_str = '%Y%m%dT%H%M%SZ'
reg = re.compile(r'^backup-rb-lists_(\d{8}T\d{6}Z)\.tar\.xz$')

now = datetime.datetime.now()
now_str = now.strftime(time_str)

backupdir = Path('/srv/mailman/backups/')
if not backupdir.exists():
    backupdir.mkdir()
if not backupdir.is_dir():
    print('backupdir exists but it is not a directory', file=sys.stderr)

bakfile = backupdir / 'backup-rb-lists_{}.tar.xz'.format(now_str)

with tempfile.NamedTemporaryFile(dir=backupdir, delete=False) as f:
    print('Creating the tarball…')
    try:
        subprocess.run(
            ('tar', 'cJf', f.name, '.'),
            cwd='/var/lib/mailman/',
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            check=True,
        )
    except subprocess.CalledProcessError as e:
        print('tar call failed ({}):'.format(e.returncode), file=sys.stderr)
        print(e.stdout.decode('utf-8'), file=sys.stderr)
        os.remove(f.name)
        sys.exit(1)
    try:
        print('Moving backup tarball in place…')
        os.rename(f.name, bakfile)
    except OSError as e:
        print('Failed to rename file in place', file=sys.stderr)
        os.remove(f.name)
        raise e

print('Backup completed!')
print()

# find old backup files
to_keep = []
to_remove = []
for f in backupdir.iterdir():
    if not f.is_file():
        continue
    r = re.match(reg, f.name)
    if not r:
        print(f'Not recognized: {f.name}')
        continue
    old_date = datetime.datetime.strptime(r.group(1), time_str)
    if now - old_date < datetime.timedelta(days=30):
        to_keep.append(f)
        continue
    if old_date.day == 1:
        to_keep.append(f)
        continue
    to_remove.append(f)
# TODO: actually implement removal.


print("rsync to Mattia's place:")
try:
    p = subprocess.check_output(
        ('rsync', '-vr', f'{backupdir}{os.sep}',
         'mattia@savidlin.mapreri.org:/home/mattia/backup-rb-lists/'),
        stderr=subprocess.STDOUT,
    )
except subprocess.CalledProcessError as e:
    print('rsync to mattia failed:', file=sys.stderr)
    print(e.stdout.decode('utf-8'))
    sys.exit(1)

roles/mailman/templates/backup.sh

deleted100644 → 0
+0 −25
Original line number Diff line number Diff line
#!/bin/sh

#
# {{ ansible_managed }}
#

set -eux

d=$(date +%Y%m%dT%H%M%SZ)
backupdir=/srv/mailman/backups

mkdir -pv "$backupdir"

f="$backupdir/backup-rb-lists_${d}.tar.xz"

trap 'rm -fv ${f}.tmp' EXIT

cd /var/lib/mailman
tar cJf "${f}.tmp" .
mv "${f}.tmp" "$f"

trap - EXIT


rsync -v "$f" mattia@savidlin.mapreri.org:/home/mattia/backup-rb-lists/