Compare commits

...

7 Commits

Author SHA1 Message Date
Kenny Phelps-McKeown eab257db1f
Merge b50e55c17a into 1ae8f26e82 2026-02-18 22:00:39 +01:00
Jim Salter 1ae8f26e82
avoid bug with snapshots named 0
Updated error handling to check for empty string instead of false for snapshot retrieval.
2026-02-18 00:19:37 -05:00
Jim Salter d9fe50b564
Merge pull request #1074 from ifazk/create-bookmark-last-snapshot
Fix bookmark last snapshot sync early exit
2026-02-17 13:04:37 -05:00
Jim Salter d8ff385691
Change comparison from '==' to 'ne' for error checks
Zpool status reports error counts with unit suffixes after the first 999 errors in any given column; as originally written, the monitor-health plugin used strictly numeric comparison checks which would error out when encountering a value like "1.09K" for checksum errors.
2026-02-17 11:53:42 -05:00
Ifaz Kabir 89d3cbcda3 Fix bookmark last snapshot sync early exit 2026-02-17 10:37:28 -05:00
kennypm b50e55c17a full flexibility for naming template 2025-02-22 13:16:34 -05:00
kennypm acbf5daa43 custom name prefix without breaking getsnaps()
custom datestamp format
no name reordering yet as getsnaps() expects leading prefix and trailing snap type
2025-02-22 12:05:59 -05:00
3 changed files with 31 additions and 23 deletions

27
sanoid
View File

@ -17,6 +17,7 @@ use Getopt::Long qw(:config auto_version auto_help);
use Pod::Usage; # pod2usage
use Time::Local; # to parse dates in reverse
use Capture::Tiny ':all';
use POSIX 'strftime';
my %args = (
"configdir" => "/etc/sanoid",
@ -616,7 +617,11 @@ sub take_snapshots {
my @snapshots;
foreach my $type (@types) {
my $snapname = "autosnap_$datestamp{'sortable'}_$type";
my $sortable = strftime($config{$dataset}{'datestamp_format'}, localtime($datestamp{'unix_time'}));
my $snapname = $config{$dataset}{'snapname_format'};
$snapname =~ s/IDENTIFIER/$config{$dataset}{'identifier'}/g;
$snapname =~ s/DATE/$sortable/g;
$snapname =~ s/TYPE/$type/g;
push(@snapshots, $snapname);
}
@ -906,12 +911,13 @@ sub getsnaps {
}
foreach my $snap (@rawsnaps) {
my ($fs,$snapname,$snapdate) = ($snap =~ m/(.*)\@(.*ly)\t*creation\t*(\d*)/);
my ($fs,$snapname,$snapdate) = ($snap =~ m/(.*)\@(.*?)\t*creation\t*(\d*)/);
# avoid pissing off use warnings
if (defined $snapname) {
my ($snaptype) = ($snapname =~ m/.*_(\w*ly)/);
if ($snapname =~ /^autosnap/) {
if ($snapname =~ /$config{$fs}{'identifier'}/) {
my @types = qw(yearly monthly weekly daily hourly frequently);
my ($snaptype) = grep { $snapname =~ /$_/ } @types;
$snaps{$fs}{$snapname}{'ctime'}=$snapdate;
$snaps{$fs}{$snapname}{'type'}=$snaptype;
}
@ -1148,16 +1154,15 @@ sub init {
sub get_date {
my %datestamp;
($datestamp{'sec'},$datestamp{'min'},$datestamp{'hour'},$datestamp{'mday'},$datestamp{'mon'},$datestamp{'year'},$datestamp{'wday'},$datestamp{'yday'},$datestamp{'isdst'}) = localtime(time);
$datestamp{'unix_time'} = time();
($datestamp{'sec'},$datestamp{'min'},$datestamp{'hour'},$datestamp{'mday'},$datestamp{'mon'},$datestamp{'year'},$datestamp{'wday'},$datestamp{'yday'},$datestamp{'isdst'}) = localtime($datestamp{'unix_time'});
$datestamp{'year'} += 1900;
$datestamp{'unix_time'} = (((((((($datestamp{'year'} - 1971) * 365) + $datestamp{'yday'}) * 24) + $datestamp{'hour'}) * 60) + $datestamp{'min'}) * 60) + $datestamp{'sec'};
$datestamp{'sec'} = sprintf ("%02u", $datestamp{'sec'});
$datestamp{'min'} = sprintf ("%02u", $datestamp{'min'});
$datestamp{'hour'} = sprintf ("%02u", $datestamp{'hour'});
$datestamp{'mday'} = sprintf ("%02u", $datestamp{'mday'});
$datestamp{'mon'} = sprintf ("%02u", ($datestamp{'mon'} + 1));
$datestamp{'noseconds'} = "$datestamp{'year'}-$datestamp{'mon'}-$datestamp{'mday'}_$datestamp{'hour'}:$datestamp{'min'}";
$datestamp{'sortable'} = "$datestamp{'noseconds'}:$datestamp{'sec'}";
return %datestamp;
}
@ -1375,9 +1380,9 @@ sub check_zpool() {
# check for io/checksum errors
my @vdeverr = ();
if ($read != 0) { push @vdeverr, "read" };
if ($write != 0) { push @vdeverr, "write" };
if ($cksum != 0) { push @vdeverr, "cksum" };
if ($read ne 0) { push @vdeverr, "read" };
if ($write ne 0) { push @vdeverr, "write" };
if ($cksum ne 0) { push @vdeverr, "cksum" };
if (scalar @vdeverr) {
$dmge=$dmge . "(" . $dev . ":" . join(", ", @vdeverr) . " errors) ";

View File

@ -113,3 +113,9 @@ yearly_crit = 0
# for overriding these values one needs to specify them in a root pool section! ([tank]\n ...)
capacity_warn = 80
capacity_crit = 95
# snapshot name formats can be overridden
identifier = autosnap
# strftime-style format string
datestamp_format = %Y-%m-%d_%H:%M:%S
snapname_format = IDENTIFIER_DATE_TYPE

21
syncoid
View File

@ -431,7 +431,7 @@ sub syncdataset {
if (!defined $args{'no-sync-snap'} && !defined $skipsnapshot) {
# create a new syncoid snapshot on the source filesystem.
$newsyncsnap = newsyncsnap($sourcehost,$sourcefs,$sourceisroot);
if (!$newsyncsnap) {
if ($newsyncsnap eq '') {
# we already whined about the error
return 0;
}
@ -439,7 +439,7 @@ sub syncdataset {
# --include-snaps
if (!snapisincluded($newsyncsnap)) {
$newsyncsnap = getnewestsnapshot($sourcehost,$sourcefs,$sourceisroot);
if ($newsyncsnap eq 0) {
if ($newsyncsnap eq '') {
writelog('WARN', "CRITICAL: no snapshots exist on source $sourcefs, and you asked for --no-sync-snap.");
if ($exitcode < 1) { $exitcode = 1; }
return 0;
@ -448,7 +448,7 @@ sub syncdataset {
} else {
# we don't want sync snapshots created, so use the newest snapshot we can find.
$newsyncsnap = getnewestsnapshot($sourcehost,$sourcefs,$sourceisroot);
if ($newsyncsnap eq 0) {
if ($newsyncsnap eq '') {
writelog('WARN', "CRITICAL: no snapshots exist on source $sourcefs, and you asked for --no-sync-snap.");
if ($exitcode < 1) { $exitcode = 1; }
return 0;
@ -476,13 +476,13 @@ sub syncdataset {
writelog('DEBUG', "target $targetfs does not exist, and --no-stream selected. Finding newest available snapshot on source $sourcefs ...");
}
my $oldestsnap = getoldestsnapshot(\%snaps);
if (! $oldestsnap) {
if ($oldestsnap eq '') {
if (defined ($args{'no-sync-snap'}) ) {
# we already whined about the missing snapshots
return 0;
}
# getoldestsnapshot() returned false, so use new sync snapshot
# getoldestsnapshot() returned null, so use new sync snapshot
writelog('DEBUG', "getoldestsnapshot() returned false, so using $newsyncsnap.");
$oldestsnap = $newsyncsnap;
}
@ -726,11 +726,8 @@ sub syncdataset {
# do a normal replication if bookmarks aren't used or if previous
# bookmark replication was only done to the next oldest snapshot
if (!$bookmark || $nextsnapshot) {
if ($matchingsnap eq $newsyncsnap) {
# edge case: bookmark replication used the latest snapshot
return 0;
}
# edge case: skip repilcation if bookmark replication used the latest snapshot
if ((!$bookmark || $nextsnapshot) && !($matchingsnap eq $newsyncsnap)) {
($exit, $stdout) = syncincremental($sourcehost, $sourcefs, $targethost, $targetfs, $matchingsnap, $newsyncsnap, defined($args{'no-stream'}));
@ -1541,7 +1538,7 @@ sub getoldestsnapshot {
# well, actually we set --no-sync-snap, so no we *didn't* already make one. Whoops.
writelog('CRITICAL', "--no-sync-snap is set, and getoldestsnapshot() could not find any snapshots on source!");
}
return 0;
return '';
}
sub getnewestsnapshot {
@ -1563,7 +1560,7 @@ sub getnewestsnapshot {
writelog('WARN', "--no-sync-snap is set, and getnewestsnapshot() could not find any snapshots on source for current dataset. Continuing.");
if ($exitcode < 2) { $exitcode = 2; }
}
return 0;
return '';
}
sub buildsynccmd {