398 lines
11 KiB
Bash
Executable File
398 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# set -x
|
|
|
|
sudo apt install -y \
|
|
sanoid
|
|
# git \
|
|
# dh-make \
|
|
# libconfig-inifiles-perl \
|
|
|
|
echo "sanoid provides: sanoid, syncoid, findoid in /usr/sbin"
|
|
echo "defaults are in /usr/share/sanoid/sanoid.defaults.conf"
|
|
echo "override them in /etc/sanoid/sanoid.conf"
|
|
|
|
echo "Installed files:"
|
|
cat <<-EOF
|
|
syncoid /usr/sbin/
|
|
sanoid /usr/sbin/
|
|
findoid /usr/sbin/
|
|
sanoid.defaults.conf /usr/share/sanoid/
|
|
debian/sanoid-prune.service /lib/systemd/system
|
|
CHANGELIST /usr/share/doc/sanoid/changelog
|
|
EOF
|
|
|
|
# Cronjob for non-systemd systems: every 15 minutes.
|
|
# If you require a different interval, you will need to disable the
|
|
# timer or the cron job according to your system configuration.
|
|
conf_print_syncoid_cron() {
|
|
cat <<-EOF
|
|
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
|
|
|
*/15 * * * * root [ -f /etc/sanoid/sanoid.conf ] && if [ ! -d /run/systemd/system ]; then TZ=UTC /usr/sbin/sanoid --cron --quiet; fi
|
|
EOF
|
|
}
|
|
conf_print_sanoid_cron > /etc/cron.d/sanoid
|
|
|
|
# Do the same for syncoid for backups.
|
|
conf_print_syncoid_cron() {
|
|
cat <<-EOF
|
|
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
|
|
|
*/15 * * * * root [ -f /etc/sanoid/syncoid.conf ] && if [ ! -d /run/systemd/system ]; then TZ=UTC /usr/sbin/sanoid --cron --quiet; fi
|
|
EOF
|
|
}
|
|
conf_print_syncoid_cron > /etc/cron.d/syncoid
|
|
|
|
# Copied from /usr/shar/doc/sanoid/example.conf
|
|
conf_print_sanoid() {
|
|
cat <<-EOF | sudo tee /etc/sanoid/sanoid.conf
|
|
## name your backup modules with the path to their ZFS dataset - no leading slash.
|
|
#[zpoolname/datasetname]
|
|
# # pick one or more templates - they're defined (and editable) below. Comma separated, processed in order.
|
|
# # in this example, template_demo's daily value overrides template_production's daily value.
|
|
# use_template = production,demo
|
|
#
|
|
# # if you want to, you can override settings in the template directly inside module definitions like this.
|
|
# # in this example, we override the template to only keep 12 hourly and 1 monthly snapshot for this dataset.
|
|
# hourly = 12
|
|
# monthly = 1
|
|
#
|
|
## you can also handle datasets recursively.
|
|
#[zpoolname/parent]
|
|
# use_template = production
|
|
# recursive = yes
|
|
# # if you want sanoid to manage the child datasets but leave this one alone, set process_children_only.
|
|
# process_children_only = yes
|
|
#
|
|
## you can selectively override settings for child datasets which already fall under a recursive definition.
|
|
#[zpoolname/parent/child]
|
|
# # child datasets already initialized won't be wiped out, so if you use a new template, it will
|
|
# # only override the values already set by the parent template, not replace it completely.
|
|
# use_template = demo
|
|
|
|
|
|
# you can also handle datasets recursively in an atomic way without the possibility to override settings for child datasets.
|
|
[zpoolname/parent2]
|
|
use_template = production
|
|
recursive = zfs
|
|
|
|
|
|
|
|
#############################
|
|
# templates below this line #
|
|
#############################
|
|
|
|
# name your templates template_templatename. you can create your own, and use them in your module definitions above.
|
|
|
|
[template_demo]
|
|
daily = 60
|
|
|
|
[template_production]
|
|
frequently = 0
|
|
hourly = 36
|
|
daily = 30
|
|
monthly = 3
|
|
yearly = 0
|
|
autosnap = yes
|
|
autoprune = yes
|
|
|
|
[template_backup]
|
|
autoprune = yes
|
|
frequently = 0
|
|
hourly = 30
|
|
daily = 90
|
|
monthly = 12
|
|
yearly = 0
|
|
|
|
### don't take new snapshots - snapshots on backup
|
|
### datasets are replicated in from source, not
|
|
### generated locally
|
|
autosnap = no
|
|
|
|
### monitor hourlies and dailies, but don't warn or
|
|
### crit until they're over 48h old, since replication
|
|
### is typically daily only
|
|
hourly_warn = 2880
|
|
hourly_crit = 3600
|
|
daily_warn = 48
|
|
daily_crit = 60
|
|
|
|
[template_hotspare]
|
|
autoprune = yes
|
|
frequently = 0
|
|
hourly = 30
|
|
daily = 90
|
|
monthly = 3
|
|
yearly = 0
|
|
|
|
### don't take new snapshots - snapshots on backup
|
|
### datasets are replicated in from source, not
|
|
### generated locally
|
|
autosnap = no
|
|
|
|
### monitor hourlies and dailies, but don't warn or
|
|
### crit until they're over 4h old, since replication
|
|
### is typically hourly only
|
|
hourly_warn = 4h
|
|
hourly_crit = 6h
|
|
daily_warn = 2d
|
|
daily_crit = 4d
|
|
|
|
[template_scripts]
|
|
### information about the snapshot will be supplied as environment variables,
|
|
### see the README.md file for details about what is passed when.
|
|
### run script before snapshot
|
|
pre_snapshot_script = /path/to/script.sh
|
|
### run script after snapshot
|
|
post_snapshot_script = /path/to/script.sh
|
|
### run script before pruning snapshot
|
|
pre_pruning_script = /path/to/script.sh
|
|
### run script after pruning snapshot
|
|
pruning_script = /path/to/script.sh
|
|
### don't take an inconsistent snapshot (skip if pre script fails)
|
|
#no_inconsistent_snapshot = yes
|
|
### run post_snapshot_script when pre_snapshot_script is failing
|
|
#force_post_snapshot_script = yes
|
|
### limit allowed execution time of scripts before continuing (<= 0: infinite)
|
|
script_timeout = 5
|
|
|
|
[template_ignore]
|
|
autoprune = no
|
|
autosnap = no
|
|
monitor = no
|
|
EOF
|
|
}
|
|
conf_print_sanoid > /etc/sanoid/sanoid.conf
|
|
|
|
# Both sanoid and synmcoid are oneshot processes so it makes little sense to
|
|
# provide an init file, cron is just fine. In this case the systemd file is there
|
|
# because systemd decided to manage cron tasks.
|
|
# Generated using:
|
|
# https://raw.githubusercontent.com/akhilvij/systemd-to-sysvinit-converter/master/converter.py
|
|
# python2 converter /usr/src/sanoid-2.2.0/sanoid.service > sanoid
|
|
conf_print_sanoid_init() {
|
|
cat <<-'EOF'
|
|
#!/bin/sh
|
|
### BEGIN INIT INFO
|
|
# Provides: sanoid
|
|
# Required-Start: $syslog $local_fs $remote_fs
|
|
# Required-Stop: $syslog $local_fs $remote_fs
|
|
# Short-Description: Snapshot ZFS filesystems
|
|
### END INIT INFO
|
|
|
|
. /lib/lsb/init-functions
|
|
prog=sanoid
|
|
PIDFILE=/var/run/$prog.pid
|
|
DESC="Snapshot ZFS filesystems"
|
|
start() {
|
|
log_daemon_msg "Starting $DESC" "$prog"
|
|
start_daemon -p $PIDFILE /usr/sbin/sanoid --take-snapshots --verbose
|
|
if [ $? -ne 0 ]; then
|
|
log_end_msg 1
|
|
exit 1
|
|
fi
|
|
if [ $? -eq 0 ]; then
|
|
log_end_msg 0
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
stop() {
|
|
log_daemon_msg "Stopping $DESC" "$prog"
|
|
killproc -p $PIDFILE /usr/sbin/sanoid
|
|
if [ $? -ne 0 ]; then
|
|
log_end_msg 1
|
|
exit 1
|
|
fi
|
|
if [ $? -eq 0 ]; then
|
|
log_end_msg 0
|
|
fi
|
|
}
|
|
|
|
force_reload() {
|
|
stop
|
|
start
|
|
|
|
}
|
|
|
|
case "$1" in
|
|
start)
|
|
start
|
|
;;
|
|
stop)
|
|
stop
|
|
;;
|
|
force-reload)
|
|
force_reload
|
|
;;
|
|
restart)
|
|
stop
|
|
start
|
|
;;
|
|
|
|
*)
|
|
echo "$Usage: $prog {start|stop|force-reload|restart}"
|
|
exit 2
|
|
esac
|
|
EOF
|
|
}
|
|
# conf_print_sanoid-init > /etc/init.d/sanoid
|
|
|
|
# Generated using:
|
|
# https://raw.githubusercontent.com/akhilvij/systemd-to-sysvinit-converter/master/converter.py
|
|
# python2 converter /usr/src/sanoid-2.2.0/sanoid-prune.service > sanoid-prune
|
|
conf_print_sanoid-prune_init() {
|
|
cat <<-'EOF' | sudo tee /etc/init.d/sanoid=prune
|
|
#!/bin/sh
|
|
### BEGIN INIT INFO
|
|
# Provides: sanoid-prune
|
|
# Required-Start: $syslog $local_fs $remote_fs
|
|
# Required-Stop: $syslog $local_fs $remote_fs
|
|
# Short-Description: Prune ZFS snapshots
|
|
### END INIT INFO
|
|
|
|
. /lib/lsb/init-functions
|
|
prog=sanoid-prune
|
|
PIDFILE=/var/run/$prog.pid
|
|
DESC="Prune ZFS snapshots"
|
|
start() {
|
|
log_daemon_msg "Starting $DESC" "$prog"
|
|
start_daemon -p $PIDFILE /usr/sbin/sanoid --prune-snapshots --verbose
|
|
if [ $? -ne 0 ]; then
|
|
log_end_msg 1
|
|
exit 1
|
|
fi
|
|
if [ $? -eq 0 ]; then
|
|
log_end_msg 0
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
stop() {
|
|
log_daemon_msg "Stopping $DESC" "$prog"
|
|
killproc -p $PIDFILE /usr/sbin/sanoid
|
|
if [ $? -ne 0 ]; then
|
|
log_end_msg 1
|
|
exit 1
|
|
fi
|
|
if [ $? -eq 0 ]; then
|
|
log_end_msg 0
|
|
fi
|
|
}
|
|
|
|
force_reload() {
|
|
stop
|
|
start
|
|
|
|
}
|
|
|
|
case "$1" in
|
|
start)
|
|
start
|
|
;;
|
|
stop)
|
|
stop
|
|
;;
|
|
force-reload)
|
|
force_reload
|
|
;;
|
|
restart)
|
|
stop
|
|
start
|
|
;;
|
|
|
|
*)
|
|
echo "$Usage: $prog {start|stop|force-reload|restart}"
|
|
exit 2
|
|
esac
|
|
EOF
|
|
}
|
|
# conf_print_sanoid-prune_init > /etc/init.d/sanoid-prune
|
|
|
|
exit 0
|
|
|
|
# build a debian package from the git repo
|
|
USER="jimsalterjrs"
|
|
PROJECT="sanoid"
|
|
LICENSE="mit"
|
|
SECTION="admin"
|
|
HOMEPAGE="https://openoid.net"
|
|
BUILD_HOME="/var/tmp/sanoid-git_build"
|
|
#VERSION="2.10.0"
|
|
PACKAGE="sanoid"
|
|
VERSION=$(curl "https://api.github.com/repos/${USER}/${PROJECT}/tags?per_page=5" | jq -r '.[0] | .name')
|
|
VERSION=${VERSION:1} # strip the preceding 'v'
|
|
DEBEMAIL="person@company.tld"
|
|
DEBFULLNAME="Testy McTester"
|
|
DESCRIPTION="Policy-driven snapshot management tool for ZFS filesystems."
|
|
LONG_DESCRIPTION="Create, thin, and monitor snapshots and pool health from a single configuration file."
|
|
|
|
RSS_FEED="https://github.com/${USER}/${PROJECT}/releases.atom"
|
|
# xdg-open ${RSS_FEED}
|
|
echo ${RSS_FEED}
|
|
|
|
# Make the BUILD_HOME directory and clone upstream
|
|
mkdir -p ${BUILD_HOME}
|
|
cd ${BUILD_HOME} || exit
|
|
|
|
git clone http://github.com/${USER}/${PROJECT}.git ${PACKAGE}-${VERSION}
|
|
|
|
cd ${PACKAGE}-${VERSION} || exit
|
|
|
|
mkdir -p m4
|
|
|
|
cat <<EOF >.git/gbp.conf
|
|
[DEFAULT]
|
|
# this is the upstream-branch:
|
|
upstream-branch=master
|
|
EOF
|
|
|
|
# debianize the BUILD_HOME directory
|
|
echo ${DEBFULLNAME}
|
|
dh_make \
|
|
--createorig \
|
|
--single \
|
|
--native \
|
|
--copyright ${LICENSE} \
|
|
--yes
|
|
|
|
cp README.rst debian/README
|
|
rm debian/README.source
|
|
|
|
# Customize the debian directory values
|
|
#sed -i 's,^\(Description: \).*,\1'${DESCRIPTION}',' debian/control
|
|
sed -i "s,^\(Description: \).*,\1${DESCRIPTION}," debian/control
|
|
sed -i 's,^\(Section: \).*,\1'${SECTION}',' debian/control
|
|
sed -i "s,^\(Maintainer: \).*,\1'${DEBFULLNAME}\ \<${DEBEMAIL}\>'," debian/control
|
|
sed -i 's,^\(Homepage: \).*,\1'${HOMEPAGE}',' debian/control
|
|
sed -i "s/.*insert\ long.*/${LONG_DESCRIPTION}/" debian/control
|
|
|
|
echo ****************
|
|
cat debian/control
|
|
echo ****************
|
|
|
|
BUILD_OPTIONS=""
|
|
|
|
cat <<EOF >debian/rules
|
|
#!/usr/bin/make -f
|
|
%:
|
|
dh \$@
|
|
|
|
override_dh_auto_configure:
|
|
dh_auto_configure -- ${BUILD_OPTIONS}
|
|
EOF
|
|
|
|
cat <<EOF >debian/watch
|
|
version=4
|
|
opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/${PROJECT}-$1\.tar\.gz/ \
|
|
http://github.com/${USER}/${PROJECT}/tags .*/v?(\d\S+)\.tar\.gz
|
|
EOF
|
|
|
|
cp -a packages/debian/* debian
|
|
|
|
dpkg-buildpackage -us -uc -b
|
|
|
|
echo ${PACKAGE}_${VERSION}_amd64.deb
|
|
|
|
sudo dpkg -i ../${PACKAGE}_${VERSION}_amd64.deb
|