| Line 1... |
Line 1... |
| 1 |
#! /usr/bin/env perl
|
1 |
#! /usr/bin/env perl
|
| 2 |
|
2 |
|
| - |
|
3 |
# Test script for ZFS_Utils module
|
| - |
|
4 |
# if run with no parameters, wil do smoke tests of functions (dry-run safe)
|
| - |
|
5 |
# if run with 2 or more parameters, will read snapshot files and process them
|
| - |
|
6 |
# Usage:
|
| - |
|
7 |
# perl test_zfs_utils.pl source_snapshots.txt target_snapshots.txt [dataset_name]
|
| - |
|
8 |
# - source_snapshots.txt: file containing list of source snapshots (one per line)
|
| - |
|
9 |
# - target_snapshots.txt: file containing list of target snapshots (one per line)
|
| - |
|
10 |
# - dataset_name: (optional) dataset name to process; if not provided, will
|
| - |
|
11 |
# attempt to auto-detect from snapshot names
|
| - |
|
12 |
|
| 3 |
use strict;
|
13 |
use strict;
|
| 4 |
use warnings;
|
14 |
use warnings;
|
| 5 |
use FindBin;
|
15 |
use FindBin;
|
| 6 |
use lib "$FindBin::Bin";
|
16 |
use lib "$FindBin::Bin";
|
| 7 |
use lib "$FindBin::Bin/.."; # ensure module path
|
17 |
use lib "$FindBin::Bin/.."; # ensure module path
|
| Line 12... |
Line 22... |
| 12 |
|
22 |
|
| 13 |
$displayLogsOnConsole = 1;
|
23 |
$displayLogsOnConsole = 1;
|
| 14 |
$logFileName = '/tmp/zfs_utils_test.log';
|
24 |
$logFileName = '/tmp/zfs_utils_test.log';
|
| 15 |
unlink $logFileName if -f $logFileName;
|
25 |
unlink $logFileName if -f $logFileName;
|
| 16 |
|
26 |
|
| - |
|
27 |
# Check for command line arguments (source and target snapshot files, and optional dataset)
|
| - |
|
28 |
if (@ARGV >= 2) {
|
| - |
|
29 |
my ($source_file, $target_file, $dataset_filter) = @ARGV;
|
| - |
|
30 |
|
| - |
|
31 |
print "Reading snapshot files from command line:\n";
|
| - |
|
32 |
print " Source: $source_file\n";
|
| - |
|
33 |
print " Target: $target_file\n";
|
| - |
|
34 |
print " Dataset filter: " . ($dataset_filter || "(auto-detect)") . "\n";
|
| - |
|
35 |
|
| - |
|
36 |
# Read source snapshots (all snapshots on source dataset)
|
| - |
|
37 |
open my $src_fh, '<', $source_file or die "Cannot open source file '$source_file': $!";
|
| - |
|
38 |
my @source_snaps = <$src_fh>;
|
| - |
|
39 |
chomp @source_snaps;
|
| - |
|
40 |
close $src_fh;
|
| - |
|
41 |
|
| - |
|
42 |
# Read target snapshots (status - snapshots already on target)
|
| - |
|
43 |
open my $tgt_fh, '<', $target_file or die "Cannot open target file '$target_file': $!";
|
| - |
|
44 |
my @target_snaps = <$tgt_fh>;
|
| - |
|
45 |
chomp @target_snaps;
|
| - |
|
46 |
close $tgt_fh;
|
| - |
|
47 |
|
| - |
|
48 |
print "\nSource snapshots (" . scalar(@source_snaps) . " entries):\n";
|
| - |
|
49 |
if (@source_snaps) {
|
| - |
|
50 |
my $end = @source_snaps > 5 ? 4 : $#source_snaps;
|
| - |
|
51 |
print " $_\n" for @source_snaps[0..$end];
|
| - |
|
52 |
print " ...\n" if @source_snaps > 5;
|
| - |
|
53 |
}
|
| - |
|
54 |
|
| - |
|
55 |
print "\nTarget snapshots (" . scalar(@target_snaps) . " entries):\n";
|
| - |
|
56 |
if (@target_snaps) {
|
| - |
|
57 |
my $end = @target_snaps > 5 ? 4 : $#target_snaps;
|
| - |
|
58 |
print " $_\n" for @target_snaps[0..$end];
|
| - |
|
59 |
print " ...\n" if @target_snaps > 5;
|
| - |
|
60 |
}
|
| - |
|
61 |
|
| - |
|
62 |
# Determine dataset to process and extract parent directories
|
| - |
|
63 |
my $dataset;
|
| - |
|
64 |
my $source_parent = '';
|
| - |
|
65 |
my $target_parent = '';
|
| - |
|
66 |
|
| - |
|
67 |
if ($dataset_filter) {
|
| - |
|
68 |
# Use explicitly provided dataset
|
| - |
|
69 |
$dataset = $dataset_filter;
|
| - |
|
70 |
print "\nUsing provided dataset: $dataset\n";
|
| - |
|
71 |
} else {
|
| - |
|
72 |
# Extract dataset name from first source snapshot
|
| - |
|
73 |
if (@source_snaps && $source_snaps[0] =~ /^([^@]+)@/) {
|
| - |
|
74 |
my $full_path = $1;
|
| - |
|
75 |
# Extract just the dataset name (last component)
|
| - |
|
76 |
$dataset = $full_path;
|
| - |
|
77 |
$dataset =~ s/.*\///;
|
| - |
|
78 |
# Extract parent directory if present
|
| - |
|
79 |
if ($full_path =~ /^(.+)\/[^\/]+$/) {
|
| - |
|
80 |
$source_parent = $1;
|
| - |
|
81 |
}
|
| - |
|
82 |
}
|
| - |
|
83 |
|
| - |
|
84 |
unless ($dataset) {
|
| - |
|
85 |
die "Error: Could not extract dataset name from source snapshots\n";
|
| - |
|
86 |
}
|
| - |
|
87 |
|
| - |
|
88 |
print "\nAuto-detected dataset: $dataset\n";
|
| - |
|
89 |
}
|
| - |
|
90 |
|
| - |
|
91 |
# Extract target parent from first target snapshot if available
|
| - |
|
92 |
if (@target_snaps && $target_snaps[0] =~ /^([^@]+)@/) {
|
| - |
|
93 |
my $full_path = $1;
|
| - |
|
94 |
# Extract parent directory if present
|
| - |
|
95 |
if ($full_path =~ /^(.+)\/[^\/]+$/) {
|
| - |
|
96 |
$target_parent = $1;
|
| - |
|
97 |
}
|
| - |
|
98 |
}
|
| - |
|
99 |
|
| - |
|
100 |
print "Source parent: " . ($source_parent || "(none)") . "\n";
|
| - |
|
101 |
print "Target parent: " . ($target_parent || "(none)") . "\n";
|
| - |
|
102 |
|
| - |
|
103 |
# Process with makeReplicateCommands
|
| - |
|
104 |
my @newstatus;
|
| - |
|
105 |
my $cmds = makeReplicateCommands(\@source_snaps, \@target_snaps, $dataset, $source_parent, $target_parent, \@newstatus);
|
| - |
|
106 |
|
| - |
|
107 |
print "\nGenerated replicate commands:\n";
|
| - |
|
108 |
if (ref($cmds) eq 'HASH') {
|
| - |
|
109 |
for my $fs (sort keys %$cmds) {
|
| - |
|
110 |
print " $fs => $cmds->{$fs}\n";
|
| - |
|
111 |
}
|
| - |
|
112 |
} elsif (ref($cmds) eq 'ARRAY') {
|
| - |
|
113 |
print " (No commands generated - returned empty array)\n";
|
| - |
|
114 |
} else {
|
| - |
|
115 |
print " (Unexpected return type)\n";
|
| - |
|
116 |
}
|
| - |
|
117 |
|
| - |
|
118 |
print "\nNew status entries (" . scalar(@newstatus) . "):\n";
|
| - |
|
119 |
print " $_\n" for @newstatus;
|
| - |
|
120 |
|
| - |
|
121 |
print "\nSnapshot file processing complete.\n";
|
| - |
|
122 |
exit 0;
|
| - |
|
123 |
}
|
| - |
|
124 |
|
| 17 |
print "Running ZFS_Utils smoke tests (dry-run safe)\n";
|
125 |
print "Running ZFS_Utils smoke tests (dry-run safe)\n";
|
| 18 |
|
126 |
|
| 19 |
# 1) runCmd in scalar context
|
127 |
# 1) runCmd in scalar context
|
| 20 |
my $echo_out = runCmd('printf', 'hello_from_runCmd');
|
128 |
my $echo_out = runCmd('printf', 'hello_from_runCmd');
|
| 21 |
print "runCmd scalar output: [$echo_out]\n";
|
129 |
print "runCmd scalar output: [$echo_out]\n";
|
| Line 41... |
Line 149... |
| 41 |
'tank/home@2025-12-07-1d extra',
|
149 |
'tank/home@2025-12-07-1d extra',
|
| 42 |
'tank/data@2025-11-01-7d',
|
150 |
'tank/data@2025-11-01-7d',
|
| 43 |
);
|
151 |
);
|
| 44 |
my @status = ('tank/home@2025-11-30-1d');
|
152 |
my @status = ('tank/home@2025-11-30-1d');
|
| 45 |
my @newstatus;
|
153 |
my @newstatus;
|
| 46 |
my $cmds = makeReplicateCommands(\@snaplines, \@status, \@newstatus);
|
154 |
my $cmds = makeReplicateCommands(\@snaplines, \@status, 'home', 'tank', 'tank', \@newstatus);
|
| 47 |
print "Generated replicate commands:\n";
|
155 |
print "Generated replicate commands:\n";
|
| 48 |
for my $fs (sort keys %$cmds) {
|
156 |
for my $fs (sort keys %$cmds) {
|
| 49 |
print " $fs => $cmds->{$fs}\n";
|
157 |
print " $fs => $cmds->{$fs}\n";
|
| 50 |
}
|
158 |
}
|
| 51 |
print "New status entries: ". join(', ', @newstatus) ."\n";
|
159 |
print "New status entries: ". join(', ', @newstatus) ."\n";
|