backup-freshness-check: check local and offsite backup

This commit is contained in:
cronekorkn 2023-03-02 18:20:10 +01:00
parent e12e19d5ee
commit f167643980
Signed by: cronekorkn
SSH key fingerprint: SHA256:v0410ZKfuO1QHdgKBsdQNF64xmTxOF8osF1LIqwTcVw
7 changed files with 63 additions and 48 deletions

View file

@ -8,13 +8,13 @@ from datetime import datetime, timedelta
now = datetime.now() now = datetime.now()
two_days_ago = now - timedelta(days=2) two_days_ago = now - timedelta(days=2)
with open('/etc/backup-server.json', 'r') as file: with open('/etc/backup-freshness-check.json', 'r') as file:
conf = json.load(file) config = json.load(file)
local_datasets = check_output(['zfs', 'list', '-H', '-o', 'name']).decode().splitlines() local_datasets = check_output(['zfs', 'list', '-H', '-o', 'name']).decode().splitlines()
errors = set() errors = set()
for dataset in conf['datasets']: for dataset in config['datasets']:
if f'tank/{dataset}' not in local_datasets: if f'tank/{dataset}' not in local_datasets:
errors.add(f'dataset "{dataset}" not present at all') errors.add(f'dataset "{dataset}" not present at all')
continue continue
@ -22,7 +22,7 @@ for dataset in conf['datasets']:
snapshots = [ snapshots = [
snapshot snapshot
for snapshot in check_output(['zfs', 'list', '-H', '-o', 'name', '-t', 'snapshot', f'tank/{dataset}', '-s', 'creation']).decode().splitlines() for snapshot in check_output(['zfs', 'list', '-H', '-o', 'name', '-t', 'snapshot', f'tank/{dataset}', '-s', 'creation']).decode().splitlines()
if '@auto-backup_' in snapshot if f"@{config['prefix']}" in snapshot
] ]
if not snapshots: if not snapshots:
@ -43,3 +43,5 @@ if errors:
for error in errors: for error in errors:
print(error) print(error)
exit(2) exit(2)
else:
print(f"all {len(config['datasets'])} datasets have fresh backups.")

View file

@ -0,0 +1,15 @@
from json import dumps
from bundlewrap.metadata import MetadataJSONEncoder
files = {
'/etc/backup-freshness-check.json': {
'content': dumps({
'prefix': node.metadata.get('backup-freshness-check/prefix'),
'datasets': node.metadata.get('backup-freshness-check/datasets'),
}, indent=4, sort_keys=True, cls=MetadataJSONEncoder),
},
'/usr/lib/nagios/plugins/check_backup_freshness': {
'mode': '0755',
},
}

View file

@ -0,0 +1,36 @@
defaults = {
'backup-freshness-check': {
'server': node.name,
'prefix': 'auto-backup_',
'datasets': {},
},
'monitoring': {
'services': {
'backup freshness': {
'vars.command': '/usr/lib/nagios/plugins/check_backup_freshness',
'check_interval': '6h',
'vars.sudo': True,
},
},
},
}
@metadata_reactor.provides(
'backup-freshness-check/datasets'
)
def backup_freshness_check(metadata):
return {
'backup-freshness-check': {
'datasets': {
f"{other_node.metadata.get('id')}/{dataset}"
for other_node in repo.nodes
if other_node.has_bundle('backup')
and other_node.has_bundle('zfs')
and other_node.metadata.get('backup/server') == metadata.get('backup-freshness-check/server')
for dataset, options in other_node.metadata.get('zfs/datasets').items()
if options.get('backup', True)
and not options.get('mountpoint', None) in [None, 'none']
},
},
}

View file

@ -1,12 +0,0 @@
from json import dumps
from bundlewrap.metadata import MetadataJSONEncoder
files = {
'/etc/backup-server.json': {
'content': dumps(node.metadata.get('backup-receiver'), indent=4, sort_keys=True, cls=MetadataJSONEncoder),
},
'/usr/lib/nagios/plugins/check_backup_freshness': {
'mode': '0755',
},
}

View file

@ -6,18 +6,6 @@ defaults = {
'rsync': {}, 'rsync': {},
}, },
}, },
'backup-receiver': {
'datasets': {},
},
'monitoring': {
'services': {
'backup freshness': {
'vars.command': '/usr/lib/nagios/plugins/check_backup_freshness',
'check_interval': '6h',
'vars.sudo': True,
},
},
},
'users': { 'users': {
'backup-receiver': { 'backup-receiver': {
'authorized_keys': set(), 'authorized_keys': set(),
@ -131,23 +119,3 @@ def backup_authorized_keys(metadata):
}, },
}, },
} }
@metadata_reactor.provides(
'backup-receiver/datasets'
)
def check_datasets(metadata):
return {
'backup-receiver': {
'datasets': {
f"{other_node.metadata.get('id')}/{dataset}"
for other_node in repo.nodes
if other_node.has_bundle('backup')
and other_node.has_bundle('zfs')
and other_node.metadata.get('backup/server') == node.name
for dataset, options in other_node.metadata.get('zfs/datasets').items()
if options.get('backup', True)
and not options.get('mountpoint', None) in [None, 'none']
},
},
}

View file

@ -1,5 +1,6 @@
{ {
'bundles': [ 'bundles': [
'backup-freshness-check',
'backup-server', 'backup-server',
'zfs', 'zfs',
], ],

View file

@ -6,6 +6,7 @@
'raspberry-pi', 'raspberry-pi',
], ],
'bundles': [ 'bundles': [
'backup-freshness-check',
'dm-crypt', 'dm-crypt',
'smartctl', 'smartctl',
'wireguard', 'wireguard',
@ -20,6 +21,10 @@
'gateway4': '192.168.179.1', 'gateway4': '192.168.179.1',
}, },
}, },
'backup-freshness-check': {
'server': 'home.backups',
'prefix': 'auto-mirror_'
},
'users': { 'users': {
'root': { 'root': {
'authorized_users': { 'authorized_users': {