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