New parameters to archive backups
gitea/vn-vmware/pipeline/head This commit looks good
Details
gitea/vn-vmware/pipeline/head This commit looks good
Details
This commit is contained in:
parent
66c97bb570
commit
a39d7db316
11
config.pl
11
config.pl
|
@ -24,7 +24,16 @@ rotation => 'lastMonth',
|
||||||
rotations => {
|
rotations => {
|
||||||
lastMonth => {
|
lastMonth => {
|
||||||
days => 31,
|
days => 31,
|
||||||
count => 31
|
count => 31,
|
||||||
|
archive_regex => '^\d{4}-\d{2}-01'
|
||||||
|
|
||||||
|
# Function used to archive and exclude backups from rotation
|
||||||
|
# https://perldoc.perl.org/Time/Piece.html
|
||||||
|
# https://perldoc.perl.org/Time/Seconds.html
|
||||||
|
archive_fn => sub {
|
||||||
|
my ($backup_time, $now) = @_;
|
||||||
|
return $backup_time->year < $now->year - 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
lastWeek => {
|
lastWeek => {
|
||||||
days => 7
|
days => 7
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vn-vmware (1.1.17) stable; urgency=low
|
vn-vmware (1.1.18) stable; urgency=low
|
||||||
|
|
||||||
* Initial Release.
|
* Initial Release.
|
||||||
|
|
||||||
|
|
76
vn-vmware.pl
76
vn-vmware.pl
|
@ -11,6 +11,7 @@ use VMware::VIExt;
|
||||||
use Time::Piece;
|
use Time::Piece;
|
||||||
use Time::Seconds;
|
use Time::Seconds;
|
||||||
use File::Path;
|
use File::Path;
|
||||||
|
use File::Copy 'move';
|
||||||
use Sys::CPU;
|
use Sys::CPU;
|
||||||
use Term::ANSIColor;
|
use Term::ANSIColor;
|
||||||
use IO::Handle;
|
use IO::Handle;
|
||||||
|
@ -77,6 +78,10 @@ my %opts = (
|
||||||
help => "Number of backups to keep despite the rotation days",
|
help => "Number of backups to keep despite the rotation days",
|
||||||
default => 0
|
default => 0
|
||||||
},
|
},
|
||||||
|
'archive-regex' => {
|
||||||
|
type => "=s",
|
||||||
|
help => "Regular expression used to archive and exclude backups from rotation"
|
||||||
|
},
|
||||||
'dst-name' => {
|
'dst-name' => {
|
||||||
type => "=s",
|
type => "=s",
|
||||||
help => "Name of the new virtual machine"
|
help => "Name of the new virtual machine"
|
||||||
|
@ -159,6 +164,7 @@ my $job = Opts::get_option('job');
|
||||||
my $vm_name = Opts::get_option('vm-name');
|
my $vm_name = Opts::get_option('vm-name');
|
||||||
my $rotation_days = Opts::get_option('rotation-days');
|
my $rotation_days = Opts::get_option('rotation-days');
|
||||||
my $rotation_count = Opts::get_option('rotation-count');
|
my $rotation_count = Opts::get_option('rotation-count');
|
||||||
|
my $archive_regex = Opts::get_option('archive-regex');
|
||||||
my $dst_name = Opts::get_option('dst-name');
|
my $dst_name = Opts::get_option('dst-name');
|
||||||
my $dst_host = Opts::get_option('dst-host');
|
my $dst_host = Opts::get_option('dst-host');
|
||||||
my $dst_datastore = Opts::get_option('dst-datastore');
|
my $dst_datastore = Opts::get_option('dst-datastore');
|
||||||
|
@ -180,6 +186,7 @@ my $log_fh;
|
||||||
my $backup_disks;
|
my $backup_disks;
|
||||||
my $time_pattern = '%Y-%m-%d_%H-%M';
|
my $time_pattern = '%Y-%m-%d_%H-%M';
|
||||||
my $local_backup_dir = $config{local_backup_dir};
|
my $local_backup_dir = $config{local_backup_dir};
|
||||||
|
my $archive_fn = sub { return false; };
|
||||||
|
|
||||||
sub stringify_message {
|
sub stringify_message {
|
||||||
my ($message) = @_;
|
my ($message) = @_;
|
||||||
|
@ -355,6 +362,13 @@ sub backup_job() {
|
||||||
if (exists $rotation_cfg->{days}) {
|
if (exists $rotation_cfg->{days}) {
|
||||||
$rotation_days = $rotation_cfg->{days};
|
$rotation_days = $rotation_cfg->{days};
|
||||||
}
|
}
|
||||||
|
if (exists $rotation_cfg->{archive_regex}) {
|
||||||
|
$archive_regex = $rotation_cfg->{archive_regex};
|
||||||
|
$archive_regex = qr/$archive_regex/;
|
||||||
|
}
|
||||||
|
if (exists $rotation_cfg->{archive_fn}) {
|
||||||
|
$archive_fn = $rotation_cfg->{archive_fn};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open_machine();
|
open_machine();
|
||||||
|
@ -617,29 +631,65 @@ sub rotate_backup() {
|
||||||
log_message "Rotating '$vm_name' backups.";
|
log_message "Rotating '$vm_name' backups.";
|
||||||
|
|
||||||
my $local_dir = "$local_backup_dir/$vm_name";
|
my $local_dir = "$local_backup_dir/$vm_name";
|
||||||
my $regex = qr/\Q$vm_name\E_(\d{4}-\d{2}-\d{2}_\d{2}-\d{2})\.tar\.gz$/;
|
my $regex = qr/^\Q$vm_name\E_(\d{4}-\d{2}-\d{2}_\d{2}-\d{2})\.tar\.gz$/;
|
||||||
|
my $now = Time::Piece->new;
|
||||||
|
|
||||||
|
my @archive_files;
|
||||||
my @delete_files;
|
my @delete_files;
|
||||||
my $file_count = 0;
|
my $file_count = 0;
|
||||||
|
|
||||||
my $rotateTime = Time::Piece->new();
|
my $rotate_time = Time::Piece->new();
|
||||||
$rotateTime -= ONE_DAY * $rotation_days;
|
$rotate_time -= ONE_DAY * $rotation_days;
|
||||||
|
|
||||||
opendir(my $dh, $local_dir);
|
opendir(my $dh, $local_dir);
|
||||||
while (my $file = readdir($dh)) {
|
while (my $file = readdir($dh)) {
|
||||||
my @reResult;
|
my @re_result;
|
||||||
unless (@reResult = $file =~ $regex) {
|
unless (@re_result = $file =~ $regex) {
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
$file_count++;
|
|
||||||
my ($fileMatch) = @reResult;
|
|
||||||
my $fileTime = Time::Piece->strptime($fileMatch, $time_pattern);
|
|
||||||
|
|
||||||
if ($fileTime < $rotateTime) {
|
my ($file_match) = @re_result;
|
||||||
|
my $file_time = Time::Piece->strptime($file_match, $time_pattern);
|
||||||
|
|
||||||
|
my $archive =
|
||||||
|
(defined($archive_regex) && $file_match =~ $archive_regex)
|
||||||
|
|| (defined($archive_fn) && $archive_fn->($file_time, $now));
|
||||||
|
|
||||||
|
if ($archive) {
|
||||||
|
push(@archive_files, $file);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file_count++;
|
||||||
|
|
||||||
|
if ($file_time < $rotate_time) {
|
||||||
push(@delete_files, $file);
|
push(@delete_files, $file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $archive_count = scalar(@archive_files);
|
||||||
|
my $archive_dir = "$local_dir/.archive";
|
||||||
|
|
||||||
|
if ($archive_count > 0) {
|
||||||
|
log_message "Archiving $archive_count backups.";
|
||||||
|
|
||||||
|
unless (-e $archive_dir) {
|
||||||
|
log_message "Creating archive directory: $archive_dir";
|
||||||
|
unless ($test) {
|
||||||
|
mkdir $archive_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $archive_file (@archive_files) {
|
||||||
|
log_message "$archive_file";
|
||||||
|
unless ($test) {
|
||||||
|
move ("$local_dir/$archive_file", "$archive_dir/$archive_file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message "Some backups archived.";
|
||||||
|
}
|
||||||
|
|
||||||
my $delete_count = scalar(@delete_files);
|
my $delete_count = scalar(@delete_files);
|
||||||
my $kept_count = $file_count - $delete_count;
|
my $kept_count = $file_count - $delete_count;
|
||||||
|
|
||||||
|
@ -657,11 +707,11 @@ sub rotate_backup() {
|
||||||
|
|
||||||
log_message "Removing $delete_count detected old backups.";
|
log_message "Removing $delete_count detected old backups.";
|
||||||
|
|
||||||
foreach my $deleteFile (@delete_files) {
|
foreach my $delete_file (@delete_files) {
|
||||||
my $deleteFilePath = "$local_dir/$deleteFile";
|
my $delete_file_path = "$local_dir/$delete_file";
|
||||||
log_message $deleteFilePath;
|
log_message $delete_file_path;
|
||||||
unless ($test) {
|
unless ($test) {
|
||||||
unlink "$deleteFilePath";
|
unlink "$delete_file_path";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue