Test mode, backup only specific disks, default rotation
gitea/vn-vmware/master This commit looks good
Details
gitea/vn-vmware/master This commit looks good
Details
This commit is contained in:
parent
748d6387be
commit
6c9b098c62
|
@ -1 +1,2 @@
|
|||
config.my.pl
|
||||
config.my.pl
|
||||
visdkrc
|
|
@ -15,7 +15,7 @@ pipeline {
|
|||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
sh 'printenv'
|
||||
setEnv()
|
||||
}
|
||||
}
|
||||
stage('Deploy') {
|
||||
|
@ -30,27 +30,7 @@ pipeline {
|
|||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
if (!env.GIT_COMMITTER_EMAIL) {
|
||||
env.COMMITTER_EMAIL = sh(
|
||||
script: 'git --no-pager show -s --format="%ae"',
|
||||
returnStdout: true
|
||||
).trim()
|
||||
} else {
|
||||
env.COMMITTER_EMAIL = env.GIT_COMMITTER_EMAIL;
|
||||
}
|
||||
|
||||
if (!env.COMMITTER_EMAIL) return
|
||||
try {
|
||||
mail(
|
||||
to: env.COMMITTER_EMAIL,
|
||||
subject: "Pipeline: ${env.JOB_NAME} (${env.BUILD_NUMBER}): ${currentBuild.currentResult}",
|
||||
body: "Check status at ${env.BUILD_URL}"
|
||||
)
|
||||
} catch (e) {
|
||||
echo e.toString()
|
||||
}
|
||||
}
|
||||
sendEmail()
|
||||
}
|
||||
}
|
||||
}
|
35
config.pl
35
config.pl
|
@ -17,19 +17,40 @@ local_backup_dir => '/mnt/vm-backups',
|
|||
# Number of processes used by pigz to compress backups
|
||||
pigz_processes => 1,
|
||||
|
||||
# Backup jobs
|
||||
backup_jobs => {
|
||||
schedule1 => {
|
||||
machines => ['test'],
|
||||
rotation => 'lastMonth'
|
||||
}
|
||||
},
|
||||
# The default rotation to use if none is specified on job
|
||||
rotation => 'lastMonth',
|
||||
|
||||
# Backup rotation configuration
|
||||
rotations => {
|
||||
lastMonth => {
|
||||
days => 31,
|
||||
count => 31
|
||||
},
|
||||
lastWeek => {
|
||||
days => 7
|
||||
},
|
||||
lastYear => {
|
||||
days => 365
|
||||
}
|
||||
},
|
||||
|
||||
# Backup jobs
|
||||
backup_jobs => {
|
||||
fooJob => {
|
||||
machines => ['foo'],
|
||||
rotation => 'lastYear'
|
||||
},
|
||||
barJob => {
|
||||
machines => [{
|
||||
name => 'bar',
|
||||
disks => 'bar.vmdk'
|
||||
}]
|
||||
},
|
||||
bazJob => {
|
||||
machines => [{
|
||||
name => 'baz',
|
||||
rotation => 'lastWeek'
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vn-vmware (1.1.13) stable; urgency=low
|
||||
vn-vmware (1.1.14) stable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
MAILFROM="vn-vmware@domain.local"
|
||||
MAILTO="sysadmin@domain.local"
|
||||
|
||||
00 04 * * tue-fri root vn-vmware.pl --operation test
|
||||
00 04 * * tue-fri root vn-vmware.pl --operation none
|
||||
|
|
281
vn-vmware.pl
281
vn-vmware.pl
|
@ -55,7 +55,7 @@ foreach my $vi_config_file (@vi_config_files) {
|
|||
my %opts = (
|
||||
'operation' => {
|
||||
type => "=s",
|
||||
help => "Operation to perform: backup-job, clone-job, backup, rotate, clone, snapshot, migrate, test",
|
||||
help => "Operation to perform: none, backup-job, clone-job, backup, rotate, clone, snapshot, migrate",
|
||||
required => true
|
||||
},
|
||||
'job' => {
|
||||
|
@ -132,6 +132,11 @@ my %opts = (
|
|||
help => "Whether to power on machine after operation",
|
||||
default => 1
|
||||
},
|
||||
'test' => {
|
||||
type => "",
|
||||
help => "Test mode, don't perform actions",
|
||||
default => 0
|
||||
},
|
||||
'snapshot-name' => {
|
||||
type => "=s",
|
||||
help => "Name of the snapshot",
|
||||
|
@ -155,7 +160,7 @@ my $vm_name = Opts::get_option('vm-name');
|
|||
my $rotation_days = Opts::get_option('rotation-days');
|
||||
my $rotation_count = Opts::get_option('rotation-count');
|
||||
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 $memory = Opts::get_option('memory');
|
||||
my $num_cpus = Opts::get_option('num-cpus');
|
||||
|
@ -166,11 +171,13 @@ my $mem_reservation = Opts::get_option('mem-reservation');
|
|||
my $cpu_reservation = Opts::get_option('cpu-reservation');
|
||||
my $overwrite = Opts::option_is_set('overwrite');
|
||||
my $poweron = Opts::option_is_set('poweron');
|
||||
my $test = Opts::option_is_set('test');
|
||||
my $snapshot_name = Opts::get_option('snapshot-name');
|
||||
my $snapshot_desc = Opts::get_option('snapshot-desc');
|
||||
|
||||
my $vm;
|
||||
my $log_fh;
|
||||
my $backup_disks;
|
||||
my $time_pattern = '%Y-%m-%d_%H-%M';
|
||||
my $local_backup_dir = $config{local_backup_dir};
|
||||
|
||||
|
@ -226,6 +233,10 @@ if ($log_fh) {
|
|||
}
|
||||
|
||||
sub main {
|
||||
if ($test) {
|
||||
log_message "Test mode enabled, all actions will be simulated.";
|
||||
}
|
||||
|
||||
Util::connect();
|
||||
log_message "Connected to $server.";
|
||||
|
||||
|
@ -270,8 +281,8 @@ sub main {
|
|||
open_machine();
|
||||
migrate_machine();
|
||||
}
|
||||
when ('test') {
|
||||
test_operation();
|
||||
when ('none') {
|
||||
no_operation();
|
||||
}
|
||||
default {
|
||||
die "Unknown operation '$operation'.";
|
||||
|
@ -301,29 +312,44 @@ sub backup_job() {
|
|||
log_message "Backup job '$job' started.";
|
||||
|
||||
my $backup_job = $config{backup_jobs}{$job};
|
||||
|
||||
if (exists $backup_job->{rotation}) {
|
||||
my $rotation_name = $backup_job->{rotation};
|
||||
|
||||
unless (exists $config{rotations}{$rotation_name}) {
|
||||
die "Rotation '$rotation_name' not defined.";
|
||||
}
|
||||
|
||||
my $rotation_cfg = $config{rotations}{$rotation_name};
|
||||
|
||||
if (exists $rotation_cfg->{count}) {
|
||||
$rotation_count = $rotation_cfg->{count};
|
||||
}
|
||||
if (exists $rotation_cfg->{days}) {
|
||||
$rotation_days = $rotation_cfg->{days};
|
||||
}
|
||||
}
|
||||
|
||||
my @machines = @{$backup_job->{machines}};
|
||||
|
||||
foreach my $machine (@machines) {
|
||||
eval {
|
||||
$vm_name = $machine;
|
||||
my $rotation_name;
|
||||
|
||||
if (exists $backup_job->{rotation}) {
|
||||
$rotation_name = $backup_job->{rotation};
|
||||
} elsif (exists $config{rotation}) {
|
||||
$rotation_name = $config{rotation};
|
||||
}
|
||||
|
||||
if (ref($machine) eq 'HASH') {
|
||||
$vm_name = $machine->{name};
|
||||
$backup_disks = $machine->{disks};
|
||||
|
||||
if (exists $machine->{rotation}) {
|
||||
$rotation_name = $machine->{rotation};
|
||||
}
|
||||
} else {
|
||||
$vm_name = $machine;
|
||||
}
|
||||
|
||||
if (defined ($rotation_name)) {
|
||||
unless (exists $config{rotations}{$rotation_name}) {
|
||||
die "Rotation '$rotation_name' not defined.";
|
||||
}
|
||||
|
||||
my $rotation_cfg = $config{rotations}{$rotation_name};
|
||||
|
||||
if (exists $rotation_cfg->{count}) {
|
||||
$rotation_count = $rotation_cfg->{count};
|
||||
}
|
||||
if (exists $rotation_cfg->{days}) {
|
||||
$rotation_days = $rotation_cfg->{days};
|
||||
}
|
||||
}
|
||||
|
||||
open_machine();
|
||||
backup_machine();
|
||||
rotate_backup();
|
||||
|
@ -388,20 +414,23 @@ sub backup_machine() {
|
|||
);
|
||||
|
||||
log_message "Creating temporary backup directory: $ds_tmp_dir";
|
||||
$file_manager->MakeDirectory(
|
||||
name => $ds_tmp_dir,
|
||||
datacenter => $dc,
|
||||
createParentDirectories => true
|
||||
);
|
||||
|
||||
unless (-e $local_tmp_dir) {
|
||||
log_message "Aborting, removing temporary directory: $ds_tmp_dir";
|
||||
$file_manager->DeleteDatastoreFile(
|
||||
unless ($test) {
|
||||
$file_manager->MakeDirectory(
|
||||
name => $ds_tmp_dir,
|
||||
datacenter => $dc
|
||||
datacenter => $dc,
|
||||
createParentDirectories => true
|
||||
);
|
||||
|
||||
die "Local backup directory is not accessible: $local_tmp_dir";
|
||||
unless (-e $local_tmp_dir) {
|
||||
log_message "Aborting, removing temporary directory: $ds_tmp_dir";
|
||||
$file_manager->DeleteDatastoreFile(
|
||||
name => $ds_tmp_dir,
|
||||
datacenter => $dc
|
||||
);
|
||||
|
||||
die "Local backup directory is not accessible: $local_tmp_dir";
|
||||
}
|
||||
}
|
||||
|
||||
my $snapshot;
|
||||
|
@ -430,12 +459,14 @@ sub backup_machine() {
|
|||
|
||||
log_message $file_path;
|
||||
eval {
|
||||
$file_manager->CopyDatastoreFile(
|
||||
sourceName => $file_path,
|
||||
sourceDatacenter => $dc,
|
||||
destinationName => "$ds_tmp_dir/$file_name",
|
||||
destinationDatacenter => $dc
|
||||
);
|
||||
unless ($test) {
|
||||
$file_manager->CopyDatastoreFile(
|
||||
sourceName => $file_path,
|
||||
sourceDatacenter => $dc,
|
||||
destinationName => "$ds_tmp_dir/$file_name",
|
||||
destinationDatacenter => $dc
|
||||
);
|
||||
}
|
||||
};
|
||||
my $err = $@;
|
||||
|
||||
|
@ -449,17 +480,25 @@ sub backup_machine() {
|
|||
}
|
||||
|
||||
log_message "Creating backup snapshot.";
|
||||
my $snapshot_ref = $vm->CreateSnapshot(
|
||||
name => "backup",
|
||||
description => "Scheduled backup",
|
||||
memory => false,
|
||||
quiesce => true
|
||||
);
|
||||
$snapshot = Vim::get_view(mo_ref => $snapshot_ref);
|
||||
|
||||
my $config;
|
||||
|
||||
unless ($test) {
|
||||
my $snapshot_ref = $vm->CreateSnapshot(
|
||||
name => "backup",
|
||||
description => "Scheduled backup",
|
||||
memory => false,
|
||||
quiesce => true
|
||||
);
|
||||
$snapshot = Vim::get_view(mo_ref => $snapshot_ref);
|
||||
$config = $snapshot->config;
|
||||
} else {
|
||||
$config = $vm->config;
|
||||
}
|
||||
|
||||
log_message "Copying virtual disk files.";
|
||||
|
||||
my $devices = $snapshot->config->hardware->device;
|
||||
my $devices = $config->hardware->device;
|
||||
my $vdm = Vim::get_view(mo_ref => $service_content->virtualDiskManager);
|
||||
|
||||
my $i = -1;
|
||||
|
@ -473,6 +512,12 @@ sub backup_machine() {
|
|||
$i++;
|
||||
my $disk_path = $device->backing->fileName;
|
||||
my $disk_file = basename($disk_path);
|
||||
|
||||
if (defined($backup_disks) && !($disk_file ~~ @$backup_disks)) {
|
||||
log_message "$disk_path (Ignored)";
|
||||
next;
|
||||
}
|
||||
|
||||
log_message $disk_path;
|
||||
|
||||
if ($disk_file ~~ @copied_devices) {
|
||||
|
@ -487,20 +532,25 @@ sub backup_machine() {
|
|||
# adapterType => 'busLogic',
|
||||
# diskType => 'thin'
|
||||
#);
|
||||
$vdm->CopyVirtualDisk(
|
||||
sourceName => $disk_path,
|
||||
sourceDatacenter => $dc,
|
||||
destName => "$ds_tmp_dir/$disk_file",
|
||||
destDatacenter => $dc
|
||||
#destSpec => $disk_spec
|
||||
);
|
||||
|
||||
unless ($test) {
|
||||
$vdm->CopyVirtualDisk(
|
||||
sourceName => $disk_path,
|
||||
sourceDatacenter => $dc,
|
||||
destName => "$ds_tmp_dir/$disk_file",
|
||||
destDatacenter => $dc
|
||||
#destSpec => $disk_spec
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
log_message "Removing backup snapshot.";
|
||||
$snapshot->RemoveSnapshot(
|
||||
removeChildren => true,
|
||||
consolidate => true
|
||||
);
|
||||
unless ($test) {
|
||||
$snapshot->RemoveSnapshot(
|
||||
removeChildren => true,
|
||||
consolidate => true
|
||||
);
|
||||
}
|
||||
$snapshot = undef;
|
||||
|
||||
my $pigz_processes;
|
||||
|
@ -516,10 +566,13 @@ sub backup_machine() {
|
|||
|
||||
log_message "Compressing with Gzip (using $pigz_processes processes) to TAR file.";
|
||||
log_message $tar_command;
|
||||
my $tar_status = system($tar_command);
|
||||
|
||||
unless ($tar_status == 0) {
|
||||
die "An error occurred when trying to compress '$vm_name' machine files.";
|
||||
unless ($test) {
|
||||
my $tar_status = system($tar_command);
|
||||
|
||||
unless ($tar_status == 0) {
|
||||
die "An error occurred when trying to compress '$vm_name' machine files.";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -537,7 +590,9 @@ sub backup_machine() {
|
|||
}
|
||||
|
||||
log_message "Removing temporary directory: $local_tmp_dir";
|
||||
rmtree($local_tmp_dir);
|
||||
unless ($test) {
|
||||
rmtree($local_tmp_dir);
|
||||
}
|
||||
|
||||
if ($err) {
|
||||
die $err;
|
||||
|
@ -548,6 +603,7 @@ sub backup_machine() {
|
|||
|
||||
sub rotate_backup() {
|
||||
if ($rotation_days == 0 && $rotation_count == 0) {
|
||||
log_message "No rotation days or count, aborting.";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -597,7 +653,9 @@ sub rotate_backup() {
|
|||
foreach my $deleteFile (@delete_files) {
|
||||
my $deleteFilePath = "$local_dir/$deleteFile";
|
||||
log_message $deleteFilePath;
|
||||
unlink "$deleteFilePath";
|
||||
unless ($test) {
|
||||
unlink "$deleteFilePath";
|
||||
}
|
||||
}
|
||||
|
||||
log_message "Old backups cleaned.";
|
||||
|
@ -761,37 +819,46 @@ sub clone_machine {
|
|||
# Gathering specifications and cloning
|
||||
|
||||
log_message "Cloning machine.";
|
||||
|
||||
my $vm_clone;
|
||||
my $clone_spec = VirtualMachineCloneSpec->new(
|
||||
powerOn => false,
|
||||
template => false,
|
||||
location => $relocate_spec
|
||||
);
|
||||
my $vm_clone_ref = $vm->CloneVM(
|
||||
folder => $vm->parent,
|
||||
name => $dst_tmp_name,
|
||||
spec => $clone_spec
|
||||
);
|
||||
my $vm_clone = Vim::get_view(mo_ref => $vm_clone_ref);
|
||||
|
||||
unless ($test) {
|
||||
my $vm_clone_ref = $vm->CloneVM(
|
||||
folder => $vm->parent,
|
||||
name => $dst_tmp_name,
|
||||
spec => $clone_spec
|
||||
);
|
||||
$vm_clone = Vim::get_view(mo_ref => $vm_clone_ref);
|
||||
|
||||
my $change_spec = VirtualMachineConfigSpec->new(
|
||||
memoryMB => $memory,
|
||||
numCPUs => $num_cpus,
|
||||
cpuAllocation => $cpu,
|
||||
memoryAllocation => $mem_res,
|
||||
extraConfig => [$extra_conf]
|
||||
);
|
||||
$vm_clone->ReconfigVM(spec => $change_spec);
|
||||
my $change_spec = VirtualMachineConfigSpec->new(
|
||||
memoryMB => $memory,
|
||||
numCPUs => $num_cpus,
|
||||
cpuAllocation => $cpu,
|
||||
memoryAllocation => $mem_res,
|
||||
extraConfig => [$extra_conf]
|
||||
);
|
||||
$vm_clone->ReconfigVM(spec => $change_spec);
|
||||
}
|
||||
|
||||
if ($original_vm) {
|
||||
destroy_machine($original_vm);
|
||||
|
||||
log_message "Renaming '$dst_tmp_name' to '$dst_name'.";
|
||||
$vm_clone->Rename(newName => $dst_name);
|
||||
unless ($test) {
|
||||
$vm_clone->Rename(newName => $dst_name);
|
||||
}
|
||||
}
|
||||
|
||||
if ($poweron) {
|
||||
log_message "Powering on '$dst_name'.";
|
||||
$vm_clone->PowerOnVM();
|
||||
unless ($test) {
|
||||
$vm_clone->PowerOnVM();
|
||||
}
|
||||
}
|
||||
|
||||
log_message "Clone '$dst_name' of '$vm_name' successfully created.";
|
||||
|
@ -800,12 +867,14 @@ sub clone_machine {
|
|||
sub snapshot_machine() {
|
||||
log_message "Creating snapshot of '$vm_name'.";
|
||||
|
||||
$vm->CreateSnapshot(
|
||||
name => $snapshot_name,
|
||||
description => $snapshot_desc,
|
||||
memory => 0,
|
||||
quiesce => 0
|
||||
);
|
||||
unless ($test) {
|
||||
$vm->CreateSnapshot(
|
||||
name => $snapshot_name,
|
||||
description => $snapshot_desc,
|
||||
memory => 0,
|
||||
quiesce => 0
|
||||
);
|
||||
}
|
||||
|
||||
log_message "Snapshot of '$vm_name' successfully created.";
|
||||
}
|
||||
|
@ -821,7 +890,9 @@ sub migrate_machine {
|
|||
filter => {name => $dst_host}
|
||||
);
|
||||
|
||||
$vm->SuspendVM();
|
||||
unless ($test) {
|
||||
$vm->SuspendVM();
|
||||
}
|
||||
|
||||
if (defined($dst_datastore)) {
|
||||
my $datastore_view = Vim::find_entity_view(
|
||||
|
@ -833,27 +904,31 @@ sub migrate_machine {
|
|||
datastore => $datastore_view,
|
||||
host => $host_view
|
||||
);
|
||||
$vm->RelocateVM_Task(
|
||||
spec => $spec,
|
||||
priority => VirtualMachineMovePriority->new($priority)
|
||||
);
|
||||
unless ($test) {
|
||||
$vm->RelocateVM_Task(
|
||||
spec => $spec,
|
||||
priority => VirtualMachineMovePriority->new($priority)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$vm->MigrateVM(
|
||||
pool => $vm->resourcePool,
|
||||
host => $host_view,
|
||||
priority => VirtualMachineMovePriority->new('defaultPriority')
|
||||
);
|
||||
$vm->PowerOnVM();
|
||||
unless ($test) {
|
||||
$vm->MigrateVM(
|
||||
pool => $vm->resourcePool,
|
||||
host => $host_view,
|
||||
priority => VirtualMachineMovePriority->new('defaultPriority')
|
||||
);
|
||||
$vm->PowerOnVM();
|
||||
}
|
||||
|
||||
log_message "Migration of '$vm_name' successfull.";
|
||||
}
|
||||
|
||||
sub test_operation() {
|
||||
sub no_operation() {
|
||||
if ($vm_name) {
|
||||
open_machine();
|
||||
}
|
||||
log_message "Test operation, doing nothing.";
|
||||
log_message "Doing nothing.";
|
||||
}
|
||||
|
||||
#--------------------------------- Utils
|
||||
|
@ -880,9 +955,11 @@ sub destroy_machine {
|
|||
|
||||
log_message "Deleting machine '$destroy_vm->{name}'.";
|
||||
|
||||
if ($destroy_vm->runtime->powerState->val eq 'poweredOn') {
|
||||
$destroy_vm->PowerOffVM();
|
||||
}
|
||||
unless ($test) {
|
||||
if ($destroy_vm->runtime->powerState->val eq 'poweredOn') {
|
||||
$destroy_vm->PowerOffVM();
|
||||
}
|
||||
|
||||
$destroy_vm->Destroy();
|
||||
$destroy_vm->Destroy();
|
||||
}
|
||||
}
|
||||
|
|
Reference in New Issue