Updated and improved, now autosnapshots according to policy via cron.

This commit is contained in:
cyteen 2026-03-11 01:46:57 +00:00
parent 04d2d424af
commit 60e606d4b5
1 changed files with 75 additions and 59 deletions

View File

@ -41,7 +41,7 @@ conf_print_syncoid_cron() {
*/15 * * * * root [ -f /etc/sanoid/syncoid.conf ] && if [ ! -d /run/systemd/system ]; then TZ=UTC /usr/sbin/syncoid --cron --quiet; fi */15 * * * * root [ -f /etc/sanoid/syncoid.conf ] && if [ ! -d /run/systemd/system ]; then TZ=UTC /usr/sbin/syncoid --cron --quiet; fi
EOF EOF
} }
conf_print_syncoid_cron | sudo tee /etc/cron.d/syncoid # conf_print_syncoid_cron | sudo tee /etc/cron.d/syncoid
# Copied from /usr/share/doc/sanoid/example.conf # Copied from /usr/share/doc/sanoid/example.conf
sudo mkdir -p /etc/sanoid/ sudo mkdir -p /etc/sanoid/
@ -50,16 +50,15 @@ conf_print_sanoid() {
cat <<-EOF cat <<-EOF
[rpool/docker] [rpool/docker]
use_template = ignore use_template = ignore
recursive = yes
[rpool/archive] [rpool/archive]
use_template = ignore use_template = ignore
recursive = yes
[rpool/swap]
use_template = ignore
[rpool/tmp] [rpool/tmp]
use_template = ignore use_template = ignore
recursive = yes
[rpool/ROOT/devuan-1] [rpool/ROOT/devuan-1]
use_template = root use_template = root
@ -72,12 +71,14 @@ conf_print_sanoid() {
# rpool/ROOT/devuan-1/var # rpool/ROOT/devuan-1/var
# rpool/ROOT/devuan-1/var_lib # rpool/ROOT/devuan-1/var_lib
# Specific override for Virtual Machines to use scripts
[rpool/ROOT/devuan-1/var_lib_virt] [rpool/ROOT/devuan-1/var_lib_virt]
use_template = root use_template = root
# Custom script to freeze VMs before snapshotting recursive = no
pre_snapshot_script = /usr/local/bin/virt-freeze-all.sh pre_snapshot_script = /usr/local/bin/virt-freeze-all.sh
post_snapshot_script = /usr/local/bin/virt-thaw-all.sh post_snapshot_script = /usr/local/bin/virt-thaw-all.sh
# -- User Data --
[rpool/home] [rpool/home]
use_template = production use_template = production
recursive = yes recursive = yes
@ -89,11 +90,6 @@ conf_print_sanoid() {
# templates below this line # # 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] [template_production]
frequently = 0 frequently = 0
hourly = 36 hourly = 36
@ -103,6 +99,20 @@ conf_print_sanoid() {
autosnap = yes autosnap = yes
autoprune = yes autoprune = yes
[template_root]
# Root changes fast; shorter history often suffices
hourly = 24
daily = 7
monthly = 1
yearly = 0
autosnap = yes
autoprune = yes
[template_ignore]
autoprune = no
autosnap = no
monitor = no
[template_backup] [template_backup]
autoprune = yes autoprune = yes
frequently = 0 frequently = 0
@ -162,20 +172,6 @@ conf_print_sanoid() {
#force_post_snapshot_script = yes #force_post_snapshot_script = yes
### limit allowed execution time of scripts before continuing (<= 0: infinite) ### limit allowed execution time of scripts before continuing (<= 0: infinite)
script_timeout = 5 script_timeout = 5
[template_root]
# Root changes fast; shorter history often suffices
hourly = 24
daily = 7
monthly = 1
yearly = 0
autosnap = yes
autoprune = yes
[template_ignore]
autoprune = no
autosnap = no
monitor = no
EOF EOF
} }
conf_print_sanoid | sudo tee /etc/sanoid/sanoid.conf conf_print_sanoid | sudo tee /etc/sanoid/sanoid.conf
@ -193,6 +189,8 @@ conf_print_sanoid_init() {
# Provides: sanoid # Provides: sanoid
# Required-Start: $syslog $local_fs $remote_fs # Required-Start: $syslog $local_fs $remote_fs
# Required-Stop: $syslog $local_fs $remote_fs # Required-Stop: $syslog $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Snapshot ZFS filesystems # Short-Description: Snapshot ZFS filesystems
### END INIT INFO ### END INIT INFO
@ -251,8 +249,9 @@ conf_print_sanoid_init() {
esac esac
EOF EOF
} }
conf_print_sanoid_init | sudo tee /etc/init.d/sanoid # Sandoid doesn't ran as a daemon it runs vi cron
sudo chmod +x /etc/init.d/sanoid # conf_print_sanoid_init | sudo tee /etc/init.d/sanoid
# sudo chmod +x /etc/init.d/sanoid
# Generated using: # Generated using:
# https://raw.githubusercontent.com/akhilvij/systemd-to-sysvinit-converter/master/converter.py # https://raw.githubusercontent.com/akhilvij/systemd-to-sysvinit-converter/master/converter.py
@ -323,8 +322,9 @@ conf_print_sanoid-prune_init() {
esac esac
EOF EOF
} }
conf_print_sanoid-prune_init | sudo tee /etc/init.d/sanoid-prune # Sandoid doesn't ran as a daemon it runs vi cron
sudo chmod +x /etc/init.d/sanoid-prune # conf_print_sanoid-prune_init | sudo tee /etc/init.d/sanoid-prune
# sudo chmod +x /etc/init.d/sanoid-prune
# Give sudo access to virsh or is part of the libvirt group. # Give sudo access to virsh or is part of the libvirt group.
# qemu-guest-agent must be running in the vm # qemu-guest-agent must be running in the vm
@ -341,19 +341,27 @@ if [ -z "$VM_NAME" ]; then
fi fi
# Check if the VM is running # Check if the VM is running
STATE=$(virsh domstate "$VM_NAME") STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
if [ "$STATE" != "running" ]; then if [ "$STATE" != "running" ]; then
echo "VM $VM_NAME is not running. Skipping freeze." echo "VM $VM_NAME is not running or does not exist. Skipping freeze."
exit 0 exit 0
fi fi
echo "Freezing filesystems for $VM_NAME..." echo "Freezing filesystems for $VM_NAME..."
virsh qemu-agent-command "$VM_NAME" '{"execute":"guest-fsfreeze-freeze"}' # domfsfreeze returns the number of frozen filesystems on success
if virsh domfsfreeze "$VM_NAME" > /dev/null; then
echo "Successfully frozen $VM_NAME."
else
echo "Error: Failed to freeze $VM_NAME. Ensure qemu-guest-agent is active."
exit 1
fi
EOF EOF
} }
conf_print_virt_freeze | sudo tee /usr/local/bin/virt-freeze.sh conf_print_virt_freeze | sudo tee /usr/local/bin/virt-freeze.sh
sudo chmod +x /usr/local/bin/virt-freeze.sh sudo chmod +x /usr/local/bin/virt-freeze.sh
#---
conf_print_virt_unfreeze() { conf_print_virt_unfreeze() {
cat <<'EOF' cat <<'EOF'
#!/bin/sh #!/bin/sh
@ -367,26 +375,34 @@ if [ -z "$VM_NAME" ]; then
fi fi
# Check if the VM is running # Check if the VM is running
STATE=$(virsh domstate "$VM_NAME") STATE=$(virsh domstate "$VM_NAME" 2>/dev/null)
if [ "$STATE" != "running" ]; then if [ "$STATE" != "running" ]; then
echo "VM $VM_NAME is not running. Skipping unfreeze." echo "VM $VM_NAME is not running. Skipping unfreeze."
exit 0 exit 0
fi fi
echo "Thawing filesystems for $VM_NAME..." echo "Thawing filesystems for $VM_NAME..."
virsh qemu-agent-command "$VM_NAME" '{"execute":"guest-fsfreeze-thaw"}' # domfsthaw returns the number of thawed filesystems on success
if virsh domfsthaw "$VM_NAME" > /dev/null; then
echo "Successfully thawed $VM_NAME."
else
echo "Error: Failed to thaw $VM_NAME."
exit 1
fi
EOF EOF
} }
conf_print_virt_unfreeze | sudo tee /usr/local/bin/virt-unfreeze.sh conf_print_virt_unfreeze | sudo tee /usr/local/bin/virt-unfreeze.sh
sudo chmod +x /usr/local/bin/virt-unfreeze.sh sudo chmod +x /usr/local/bin/virt-unfreeze.sh
conf_print_virt_thaw-all() { #---
conf_print_virt_thaw_all() {
cat <<'EOF' cat <<'EOF'
#!/bin/sh #!/bin/bash
# /usr/local/bin/virt-thaw-all.sh # /usr/local/bin/virt-thaw-all.sh
# 1. Get a list of all running VM names # 1. Get running VM names, filtering out empty lines with awk
RUNNING_VMS=$(virsh list --state-running --name) RUNNING_VMS=$(virsh list --state-running --name | awk 'NF')
if [ -z "$RUNNING_VMS" ]; then if [ -z "$RUNNING_VMS" ]; then
echo "No running VMs found." echo "No running VMs found."
@ -397,30 +413,31 @@ fi
for VM_NAME in $RUNNING_VMS; do for VM_NAME in $RUNNING_VMS; do
echo "Processing $VM_NAME..." echo "Processing $VM_NAME..."
# Execute the thaw command via QEMU guest agent # Use the native thaw command.
# Note: This requires the guest-agent to be installed/running inside the VM # It handles the guest agent communication for you.
RESPONSE=$(virsh qemu-agent-command "$VM_NAME" '{"execute":"guest-fsfreeze-thaw"}' 2>&1) if virsh domfsthaw "$VM_NAME" > /dev/null 2>&1; then
if [ $? -eq 0 ]; then
echo "Successfully thawed $VM_NAME." echo "Successfully thawed $VM_NAME."
else else
echo "Error thawing $VM_NAME: $RESPONSE" # If native fails, we capture the error for the user
ERROR=$(virsh domfsthaw "$VM_NAME" 2>&1)
echo "Error thawing $VM_NAME: $ERROR"
fi fi
done done
echo "Finished processing all VMs." echo "Finished processing all VMs."
EOF EOF
} }
conf_print_virt_thaw-all | sudo tee /usr/local/bin/virt-thaw-all.sh conf_print_virt_thaw_all | sudo tee /usr/local/bin/virt-thaw-all.sh
sudo chmod +x /usr/local/bin/virt-thaw-all.sh sudo chmod +x /usr/local/bin/virt-thaw-all.sh
#---
conf_print_virt_freeze-all() { conf_print_virt_freeze-all() {
cat <<'EOF' cat <<'EOF'
#!/bin/sh #!/bin/bash
# /usr/local/bin/virt-freeze-all.sh
# 1. Get a list of all running VM names # 1. Get running VM names, filtering out empty lines
RUNNING_VMS=$(virsh list --state-running --name) RUNNING_VMS=$(virsh list --state-running --name | awk 'NF')
if [ -z "$RUNNING_VMS" ]; then if [ -z "$RUNNING_VMS" ]; then
echo "No running VMs found." echo "No running VMs found."
@ -429,17 +446,14 @@ fi
# 2. Loop through each running VM # 2. Loop through each running VM
for VM_NAME in $RUNNING_VMS; do for VM_NAME in $RUNNING_VMS; do
echo "Processing $VM_NAME..." echo "Attempting to freeze $VM_NAME..."
# Execute the freeze command via QEMU guest agent # Using the native virsh command is generally cleaner
# This flushes disk buffers and halts I/O # It returns the number of frozen filesystems on success
RESPONSE=$(virsh qemu-agent-command "$VM_NAME" '{"execute":"guest-fsfreeze-freeze"}' 2>&1) if virsh domfsfreeze "$VM_NAME" > /dev/null 2>&1; then
echo "Successfully frozen $VM_NAME."
if [ $? -eq 0 ]; then
# The response usually contains the number of filesystems frozen
echo "Successfully frozen $VM_NAME. Details: $RESPONSE"
else else
echo "Error freezing $VM_NAME: $RESPONSE" echo "Error: Could not freeze $VM_NAME. Check if QEMU Guest Agent is running."
fi fi
done done
@ -449,6 +463,8 @@ EOF
conf_print_virt_freeze-all | sudo tee /usr/local/bin/virt-freeze-all.sh conf_print_virt_freeze-all | sudo tee /usr/local/bin/virt-freeze-all.sh
sudo chmod +x /usr/local/bin/virt-freeze-all.sh sudo chmod +x /usr/local/bin/virt-freeze-all.sh
#---
# exit 0 # exit 0
# #
# # build a debian package from the git repo # # build a debian package from the git repo