Import zfs snapshots service as Arch package into git
This commit is contained in:
commit
dfe963e461
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*.src.tar.gz
|
||||
/*.pkg.tar.zst
|
||||
20
PKGBUILD
Normal file
20
PKGBUILD
Normal file
@ -0,0 +1,20 @@
|
||||
# Maintainer: Daniel <daniel.de.clooet@yoursurprise.com>
|
||||
pkgname=zfs-snapshotter
|
||||
pkgver=0.0.1
|
||||
pkgrel=1
|
||||
pkgdesc='Systemd snapshotter tool'
|
||||
|
||||
source=("zfs-daily-snapshot@.timer" "zfs-daily-snapshot@.service" "zfs-snapshot.rb")
|
||||
arch=('x86_64' 'aarch64' 'armv7h')
|
||||
depends=('systemd' 'zfs' 'ruby')
|
||||
|
||||
sha256sums=('SKIP'
|
||||
'SKIP'
|
||||
'SKIP')
|
||||
|
||||
package() {
|
||||
install -Dm755 "${srcdir}/zfs-snapshot.rb" "${pkgdir}/usr/bin/zfs-snapshot.rb"
|
||||
|
||||
install -Dm644 "${srcdir}/zfs-daily-snapshot@.timer" "${pkgdir}/etc/systemd/system/zfs-daily-snapshot@.timer"
|
||||
install -Dm644 "${srcdir}/zfs-daily-snapshot@.service" "${pkgdir}/etc/systemd/system/zfs-daily-snapshot@.service"
|
||||
}
|
||||
9
README.md
Normal file
9
README.md
Normal file
@ -0,0 +1,9 @@
|
||||
# ZFS Snapshotter
|
||||
|
||||
This is my personal opiniated package for automatically creating and cleaning up ZFS snapshots.
|
||||
|
||||
## Usage:
|
||||
- Clone this repository.
|
||||
- Build and install: `$ makepkg -Si`
|
||||
- Enable the systemd timer for your datasets:
|
||||
- Use `-` instead of `/`, due to systemd encoding: `# systemctl enable --now zfs-daily-snapshot@pool-my-dataset.timer`
|
||||
7
zfs-daily-snapshot@.service
Normal file
7
zfs-daily-snapshot@.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Create a ZFS snapshot for %I
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/bin/zfs-snapshot.rb "%I"
|
||||
9
zfs-daily-snapshot@.timer
Normal file
9
zfs-daily-snapshot@.timer
Normal file
@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Create a daily ZFS snapshot for %I
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
76
zfs-snapshot.rb
Normal file
76
zfs-snapshot.rb
Normal file
@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'date'
|
||||
|
||||
SNAPSHOTS_TO_RETAIN = 7
|
||||
SNAPSHOT_FORMAT = "daily-%Y-%m-%d"
|
||||
|
||||
input = ARGV
|
||||
|
||||
def usage
|
||||
puts "Usage: "
|
||||
puts " #{$PROGRAM_NAME} <pool>"
|
||||
|
||||
exit -1
|
||||
end
|
||||
|
||||
def run_command(*cmd)
|
||||
pipe = IO.popen(cmd)
|
||||
stdout = pipe.read
|
||||
puts stdout
|
||||
pipe.close
|
||||
|
||||
return stdout, $?.success?
|
||||
end
|
||||
|
||||
class Array
|
||||
def drop_tail(n)
|
||||
slice(0...(length - n))
|
||||
end
|
||||
end
|
||||
|
||||
class Dataset
|
||||
def initialize(name)
|
||||
_, dataset_exists = run_command("zfs", "list", "-H", name)
|
||||
raise "No such pool: #{name}" unless dataset_exists
|
||||
|
||||
@name = name
|
||||
end
|
||||
|
||||
def has_snapshot(name)
|
||||
_, snapshot_exists = run_command("zfs", "list", "-H", "#{@name}@#{name}")
|
||||
return snapshot_exists
|
||||
end
|
||||
|
||||
def create_snapshot_today
|
||||
current_snapshot_name = Date.today.strftime(SNAPSHOT_FORMAT)
|
||||
raise "Snapshot already created: #{@name}@#{current_snapshot_name}" if has_snapshot(current_snapshot_name)
|
||||
|
||||
_, made_snapshot = run_command("zfs", "snapshot", "#{@name}@#{current_snapshot_name}")
|
||||
raise "Could not create new snapshot #{@name}@#{current_snapshot_name}" unless made_snapshot
|
||||
end
|
||||
|
||||
def get_all_snapshots
|
||||
all_snapshots, could_list_all_snapshot = run_command("zfs", "list", "-t", "snapshot", "-H", @name)
|
||||
raise "Could not list snapshots for #{@name}" unless could_list_all_snapshot
|
||||
|
||||
return all_snapshots.lines.map { |line| line.split("\t").first }.map { |snapshot_name| snapshot_name.split("@").last }
|
||||
end
|
||||
|
||||
def clean_up_old_snapshots
|
||||
snapshots_to_delete = get_all_snapshots.drop_tail(SNAPSHOTS_TO_RETAIN)
|
||||
p snapshots_to_delete
|
||||
|
||||
return if snapshots_to_delete.length == 0
|
||||
|
||||
output, could_delete_old_snapshots = run_command("zfs", "destroy", "#{@name}@#{snapshots_to_delete.first}%#{snapshots_to_delete.last}")
|
||||
raise "Could not delete old snapshots for #{@name}" unless could_delete_old_snapshots
|
||||
end
|
||||
end
|
||||
|
||||
usage unless input.length == 1
|
||||
usage if input[0] == "-h" or input[0] == "--help"
|
||||
|
||||
dataset = Dataset.new input[0]
|
||||
dataset.create_snapshot_today
|
||||
dataset.clean_up_old_snapshots
|
||||
Loading…
Reference in New Issue
Block a user