backup-freshness-check: check local and offsite backup
This commit is contained in:
parent
e12e19d5ee
commit
f167643980
7 changed files with 63 additions and 48 deletions
|
@ -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.")
|
15
bundles/backup-freshness-check/items.py
Normal file
15
bundles/backup-freshness-check/items.py
Normal 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',
|
||||||
|
},
|
||||||
|
}
|
36
bundles/backup-freshness-check/metadata.py
Normal file
36
bundles/backup-freshness-check/metadata.py
Normal 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']
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -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',
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -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']
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
'bundles': [
|
'bundles': [
|
||||||
|
'backup-freshness-check',
|
||||||
'backup-server',
|
'backup-server',
|
||||||
'zfs',
|
'zfs',
|
||||||
],
|
],
|
||||||
|
|
|
@ -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': {
|
||||||
|
|
Loading…
Reference in a new issue