Bugs fixed

This commit is contained in:
Juan 2018-08-14 16:23:33 +02:00
parent d0022ba3ce
commit fee9a47f3f
7 changed files with 175 additions and 127 deletions

View File

@ -2,7 +2,7 @@
# Don't modify this file, copy it to config.my.pl and make your changes there. # Don't modify this file, copy it to config.my.pl and make your changes there.
# The log file path # The log file path
log_file = '/var/log/vn-vmware.log', log_file => '/var/log/vn-vmware.log',
# Hostname or IP address of vCenter host # Hostname or IP address of vCenter host
hostname => 'vcenter', hostname => 'vcenter',

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
vn-vmware (2.0.34) stable; urgency=low vn-vmware (1.0.0) stable; urgency=low
* Initial Release. * Initial Release.

2
debian/control vendored
View File

@ -1,7 +1,7 @@
Source: vn-vmware Source: vn-vmware
Priority: optional Priority: optional
Maintainer: Juan Ferrer Toribio <juan@verdnatura.es> Maintainer: Juan Ferrer Toribio <juan@verdnatura.es>
Build-Depends: build-essential, debhelper Build-Depends: devscripts
Standards-Version: 3.9.3 Standards-Version: 3.9.3
Section: misc Section: misc
Homepage: https://verdnatura.es Homepage: https://verdnatura.es

2
debian/links vendored
View File

@ -1 +1 @@
usr/share/vn-vmware.pl usr/bin/vn-vmware.pl usr/share/vn-vmware/vn-vmware.pl usr/bin/vn-vmware.pl

1
debian/rules vendored
View File

@ -2,4 +2,3 @@
%: %:
dh $@ dh $@

12
deploy.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
pkg="vn-vmware_1.0.0"
debPkg="${pkg}_all.deb"
host="root@bacula"
debuild -us -uc -b
#scp ../$debPkg $host:/root
#ssh $host dpkg -i /root/$debPkg
#ssh $host rm /root/$debPkg
debian/rules clean
rm ../${pkg}*

View File

@ -23,18 +23,18 @@ use constant true => 1;
my %opts = ( my %opts = (
operation => { operation => {
type => "=s", type => "=s",
help => "Operation to perform: backuping, cloning,rotate, backup, clone, snapshot, migrate", help => "Operation to perform: backuping, cloning, rotate, backup, clone, snapshot, migrate",
required => true required => true
}, },
job => {
type => "=s",
help => "The job name"
},
vmname => { vmname => {
type => "=s", type => "=s",
variable => "vmname", variable => "vmname",
help => "Name of the virtual machine" help => "Name of the virtual machine"
}, },
job => {
type => "=s",
help => "The job name"
},
rotation_days => { rotation_days => {
type => "=i", type => "=i",
help => "Rotation days for backups", help => "Rotation days for backups",
@ -108,6 +108,11 @@ my %opts = (
help => "Whether to power on machine after operation", help => "Whether to power on machine after operation",
default => 1 default => 1
}, },
show_logs => {
type => "",
help => "Whether to redirect logs to stdout",
default => 0
},
snapshot_name => { snapshot_name => {
type => "=s", type => "=s",
help => "Name of the snapshot", help => "Name of the snapshot",
@ -124,9 +129,9 @@ Opts::add_options(%opts);
Opts::parse(); Opts::parse();
Opts::validate(); Opts::validate();
my $vmname = Opts::get_option('vmname');
my $operation = Opts::get_option('operation'); my $operation = Opts::get_option('operation');
my $job = Opts::get_option('job'); my $job = Opts::get_option('job');
my $vmname = Opts::get_option('vmname');
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 $dst_name = Opts::get_option('dst_name'); my $dst_name = Opts::get_option('dst_name');
@ -143,46 +148,77 @@ my $cbt_size = Opts::get_option('cbt_size');
my $cbt = Opts::option_is_set('cbt'); my $cbt = Opts::option_is_set('cbt');
my $overwrite = Opts::option_is_set('overwrite'); my $overwrite = Opts::option_is_set('overwrite');
my $poweron = Opts::option_is_set('poweron'); my $poweron = Opts::option_is_set('poweron');
my $show_logs = Opts::option_is_set('show_logs');
my $snapshot_name = Opts::get_option('snapshot_name'); my $snapshot_name = Opts::get_option('snapshot_name');
my $snapshot_desc = Opts::get_option('snapshot_desc'); my $snapshot_desc = Opts::get_option('snapshot_desc');
my $log_fh;
my $vm;
my $remote_host;
my $vm_datastore;
my $time_pattern = '%Y-%m-%d_%H-%M';
my $local_backup_dir = %config{local_backup_dir};
my $backup_datastore = %config{backup_datastore};
my $vcenter_host = %config{hostname};
my $username = %config{user};
my %config; my %config;
my @config_files = (
my $config_files = (
'config.my.pl',
'config.pl',
'/etc/vn-vmware/config.my.pl', '/etc/vn-vmware/config.my.pl',
'/etc/vn-vmware/config.pl' '/etc/vn-vmware/config.pl',
'config.my.pl',
'config.pl'
); );
foreach my $config_file (@$config_files) { foreach my $config_file (@config_files) {
if (-e $config_file) { if (-e $config_file) {
%config = do $config_file; %config = do $config_file;
last; last;
} }
} }
unless (%config) {
die "Configuration file not found";
}
my $vm;
my $remote_host;
my $vm_datastore;
my $log_fh;
my $time_pattern = '%Y-%m-%d_%H-%M';
my $local_backup_dir = $config{local_backup_dir};
sub log_to_file {
my ($message) = @_;
my $time = Time::Piece->new;
my $timeMark = $time->strftime('%Y-%m-%d %H:%M:%S');
print $log_fh "$timeMark : $message\n";
}
sub log_message {
my ($message) = @_;
if ($log_fh) {
log_to_file $message;
} else {
print "$message\n"
}
}
sub log_error {
my ($message) = @_;
print STDERR color("red").$message.color("reset");
if ($log_fh) {
log_to_file $message;
}
}
unless ($show_logs) {
open($log_fh, '>', $config{log_file});
}
eval { eval {
&main(); main();
}; };
if (my $err = $@) { if ($@) {
print STDERR color("red").$err.color("reset"); log_error($@);
log $err; }
if ($log_fh) {
close $log_fh;
} }
sub main { sub main {
$log_fh = STDOUT; my $vcenter_host = $config{hostname};
my $username = $config{user};
VMware::VICredStore::init(filename => %config{credentials_file}); VMware::VICredStore::init(filename => $config{credentials_file});
my $password = VMware::VICredStore::get_password(server => $vcenter_host, username => $username); my $password = VMware::VICredStore::get_password(server => $vcenter_host, username => $username);
my $url = "https://$vcenter_host/sdk/vimService"; my $url = "https://$vcenter_host/sdk/vimService";
@ -201,44 +237,41 @@ sub main {
die "Cannot connect to $vcenter_host"; die "Cannot connect to $vcenter_host";
} }
log "Connected to $vcenter_host"; log_message "Connected to $vcenter_host";
eval { eval {
given ($operation) { given ($operation) {
when ('backuping') { when ('backuping') {
&open_log(); backup_job();
&backuping();
} }
when ('cloning') { when ('cloning') {
&open_log(); clone_job();
&cloning();
} }
when ('rotate') { when ('rotate') {
&rotate_backup(); rotate_backup();
} }
when ('backup') { when ('backup') {
&open_machine(); open_machine();
&backup_machine(); backup_machine();
} }
when ('clone') { when ('clone') {
&open_machine(); open_machine();
&clone_machine(); clone_machine();
} }
when ('snapshot') { when ('snapshot') {
&open_machine(); open_machine();
&snapshot_machine(); snapshot_machine();
} }
when ('migrate') { when ('migrate') {
&open_machine(); open_machine();
&migrate_machine(); migrate_machine();
} }
} }
}; };
my $err = $@; my $err = $@;
Vim::logout(); Vim::logout();
close $log_fh;
if ($err) { if ($err) {
die $err; die $err;
@ -247,53 +280,68 @@ sub main {
#--------------------------------- Operations #--------------------------------- Operations
sub backuping() { sub backup_job() {
log "Backup job '$job' started"; unless (exists $config{schedules}{$job}) {
die "Backup job '$job' doesn't exists";
my %schedule = %config{schedules}{$job};
my %rotation_cfg = %config{rotations}{%schedule{rotation}}
$rotation_count = %rotation_cfg{count};
$rotation_days = %rotation_cfg{days};
my @machines = %schedule{machines};
foreach $vmname (@$machines) {
&open_machine();
&backup_machine();
&rotate_backup();
} }
log "Backup job '$job' finished"; log_message "Backup job '$job' started";
my $schedule = $config{schedules}{friday};
my $rotation_cfg = $config{rotations}{$schedule->{rotation}};
$rotation_count = $rotation_cfg->{count};
$rotation_days = $rotation_cfg->{days};
my @machines = $schedule->{machines};
foreach $vmname (@machines) {
eval {
print "$vmname\n";
#open_machine();
#backup_machine();
#rotate_backup();
};
if ($@) {
log_error($@);
}
}
log_message "Backup job '$job' finished";
} }
sub cloning() { sub clone_job() {
log "Clone job '$job' started"; unless (exists $config{clone}{$job}) {
die "Cloning job '$job' doesn't exists";
}
my %cfg = %config{clone}{$job}; log_message "Clone job '$job' started";
$vmname = %cfg{vm}; my $cfg = $config{clone}{$job};
$dst_name = %cfg{dst_name};
$dst_host = %cfg{dst_host};
$dst_datastore = %cfg{dst_datastore};
$memory = %cfg{memory};
$num_cpus = %cfg{num_cpus};
$mac = %cfg{mac};
$poweron = %cfg{poweron};
$overwrite = %cfg{overwrite};
&open_machine(); $vmname = $cfg->{vm};
&clone_machine(); $dst_name = $cfg->{dst_name};
$dst_host = $cfg->{dst_host};
$dst_datastore = $cfg->{dst_datastore};
$memory = $cfg->{memory};
$num_cpus = $cfg->{num_cpus};
$mac = $cfg->{mac};
$poweron = $cfg->{poweron};
$overwrite = $cfg->{overwrite};
log "Clone job '$job' finished"; open_machine();
clone_machine();
log_message "Clone job '$job' finished";
} }
sub backup_machine() { sub backup_machine() {
log "Backup of '$vmname' started"; log_message "Backup of '$vmname' started";
my $time = Time::Piece->new; my $time = Time::Piece->new;
my $timeMark = $time->strftime($time_pattern); my $timeMark = $time->strftime($time_pattern);
my $tmpDir = ".$timeMark"; my $tmpDir = ".$timeMark";
my $backup_datastore = $config{backup_datastore};
my $dsBackupPath = "[$backup_datastore] $vmname/$tmpDir"; my $dsBackupPath = "[$backup_datastore] $vmname/$tmpDir";
my $local_dir = "$local_backup_dir/$vmname"; my $local_dir = "$local_backup_dir/$vmname";
my $localTmpDir = "$local_dir/$tmpDir"; my $localTmpDir = "$local_dir/$tmpDir";
@ -307,7 +355,7 @@ sub backup_machine() {
my $fileManager = Vim::get_view(mo_ref => $serviceContent->fileManager); my $fileManager = Vim::get_view(mo_ref => $serviceContent->fileManager);
my $dc = Vim::find_entity_view( my $dc = Vim::find_entity_view(
view_type => "Datacenter", view_type => "Datacenter",
filter => {'name' => $datacenter} filter => {'name' => $config{datacenter}}
); );
$fileManager->MakeDirectory( $fileManager->MakeDirectory(
@ -361,11 +409,11 @@ sub backup_machine() {
die $err; die $err;
} }
log "Backup of '$vmname' successfully created"; log_message "Backup of '$vmname' successfully created";
} }
sub rotate_backup() { sub rotate_backup() {
log "Rotating '$vmname' backups"; log_message "Rotating '$vmname' backups";
use List::Util qw[min]; use List::Util qw[min];
@ -406,38 +454,38 @@ sub rotate_backup() {
splice(@deleteFiles, -min($rotation_count - $keptCount, $removeCount)); splice(@deleteFiles, -min($rotation_count - $keptCount, $removeCount));
} }
my $removeCount = scalar(@deleteFiles); $removeCount = scalar(@deleteFiles);
if ($removeCount == $fileCount) { if ($removeCount == $fileCount) {
die "Rotation aborted, because is trying to remove all backups"; die "Rotation aborted, because is trying to remove all backups";
} }
foreach my $deleteFile (@deleteFiles) { foreach my $deleteFile (@deleteFiles) {
log "Removing $deleteFile (Not done until script is tested for a while)"; log_message "Removing $deleteFile (Not done until script is tested for a while)";
#unlink $deleteFile; #unlink $deleteFile;
} }
if (scalar(@deleteFiles) == 0) { if (scalar(@deleteFiles) == 0) {
log "No backups to clean"; log_message "No backups to clean";
} else { } else {
log "$removeCount backups cleaned"; log_message "$removeCount backups cleaned";
} }
closedir($dh); closedir($dh);
} }
sub clone_machine { sub clone_machine {
log "Cloning '$vmname' to '$dst_name'"; log_message "Cloning '$vmname' to '$dst_name'";
&check_datastore(); check_datastore();
my $vmOriginal = Vim::find_entity_view( my $vmOriginal = Vim::find_entity_view(
view_type => 'VirtualMachine', view_type => 'VirtualMachine',
filter => {'name' => $dst_name} filter => {'name' => $dst_name}
); );
if ($vmOriginal) { if ($vmOriginal) {
if ($overwrite) { if ($overwrite) {
&set_power_state($vmOriginal, "poweredOff"); set_power_state($vmOriginal, "poweredOff");
sleep(20); sleep(20);
$vmOriginal->Destroy(); $vmOriginal->Destroy();
} else { } else {
@ -549,7 +597,7 @@ sub clone_machine {
my $guest_id = ($vm->guest->guestId =~ m/^other/) ? "debian6_64Guest" : $vm->guest->guestId; my $guest_id = ($vm->guest->guestId =~ m/^other/) ? "debian6_64Guest" : $vm->guest->guestId;
my $vm_dev_spec = VirtualDeviceConfigSpec->new(device => $newNetworkDevice, operation => $config_spec_operation); my $vm_dev_spec = VirtualDeviceConfigSpec->new(device => $newNetworkDevice, operation => $config_spec_operation);
my $extra_conf = OptionValue->new(key => "guestinfo.hostname", value => $dst_name); my $extra_conf = OptionValue->new(key => "guestinfo.hostname", value => $dst_name);
my $changeSpec = VirtualMachineConfigSpec->new( my $changeSpec = VirtualMachineConfigSpec->new(
deviceChange => [$vm_dev_spec], deviceChange => [$vm_dev_spec],
@ -574,15 +622,15 @@ sub clone_machine {
spec => $cloneSpec spec => $cloneSpec
); );
log "Clone '$dst_name' of '$vmname' successfully created"; log_message "Clone '$dst_name' of '$vmname' successfully created";
} }
sub snapshot_machine() { sub snapshot_machine() {
log "Creating snapshot of '$vmname' with CBT $cbt"; log_message "Creating snapshot of '$vmname' with CBT $cbt";
if ($cbt) { if ($cbt) {
if ($vm->capability->changeTrackingSupported) { if ($vm->capability->changeTrackingSupported) {
&setCBT(true); setCBT(true);
} else { } else {
die "CBT not supported"; die "CBT not supported";
} }
@ -613,46 +661,46 @@ sub snapshot_machine() {
my $vmFolder = "/vmfs/volumes/$vm_datastore/$vmname"; my $vmFolder = "/vmfs/volumes/$vm_datastore/$vmname";
my $command = "cd $vmFolder && ".q[ls -lhr *-0*-ctk.vmdk|head -n1 |awk '{print $9}' |cut -c].(length($vmname)+2)."-".(length($vmname)+7); my $command = "cd $vmFolder && ".q[ls -lhr *-0*-ctk.vmdk|head -n1 |awk '{print $9}' |cut -c].(length($vmname)+2)."-".(length($vmname)+7);
my $fic_snap = &execute_ssh_command($command); my $fic_snap = execute_ssh_command($command);
if (length($fic_snap) > 0) { if (length($fic_snap) > 0) {
$command = "cd $vmFolder && ".q[ls -lhr *-0*-delta.vmdk|head -n1 |awk '{print $5}' | sed '$s/...$//']; $command = "cd $vmFolder && ".q[ls -lhr *-0*-delta.vmdk|head -n1 |awk '{print $5}' | sed '$s/...$//'];
my $tamano_snp = &execute_ssh_command($command); my $tamano_snp = execute_ssh_command($command);
if (($tamano_snp + 0) >= $cbt_size) { if (($tamano_snp + 0) >= $cbt_size) {
&set_power_state($vmbackup, "poweredOff"); set_power_state($vmbackup, "poweredOff");
$command = "scp -i /etc/ssh/ssh_host_dsa_key $vmFolder/$vmname.vmdk root@"."$dst_host:/vmfs/volumes/$dst_datastore/$vm_dst_datastore"; $command = "scp -i /etc/ssh/ssh_host_dsa_key $vmFolder/$vmname.vmdk root@"."$dst_host:/vmfs/volumes/$dst_datastore/$vm_dst_datastore";
&execute_ssh_command($command); execute_ssh_command($command);
&create_snapshot($vm); create_snapshot($vm);
&create_snapshot($vmbackup); create_snapshot($vmbackup);
my $fichero = "$vmname-".substr($fic_snap,0,length($fic_snap)-1)."*.vmdk"; my $fichero = "$vmname-".substr($fic_snap,0,length($fic_snap)-1)."*.vmdk";
log "Copying snapshot $fichero is less or equal than $cbt_size with a size of ".length($fic_snap).""; log_message "Copying snapshot $fichero is less or equal than $cbt_size with a size of ".length($fic_snap)."";
$command = "scp -i /etc/ssh/ssh_host_dsa_key $vmFolder/$fichero root@"."$dst_host:/vmfs/volumes/$dst_datastore/$vm_dst_datastore"; $command = "scp -i /etc/ssh/ssh_host_dsa_key $vmFolder/$fichero root@"."$dst_host:/vmfs/volumes/$dst_datastore/$vm_dst_datastore";
&execute_ssh_command($command); execute_ssh_command($command);
# Deletes all snapshots # Deletes all snapshots
$vm->RemoveAllSnapshots(); $vm->RemoveAllSnapshots();
&create_snapshot($vm); create_snapshot($vm);
} else { } else {
log "No snapshot is made since the size of $vmname-$fic_snap-delta.vmdk is less than $cbt_size"; log_message "No snapshot is made since the size of $vmname-$fic_snap-delta.vmdk is less than $cbt_size";
} }
} else { } else {
log "Creating first snapshot"; log_message "Creating first snapshot";
&create_snapshot($vm); create_snapshot($vm);
} }
} else { } else {
&create_snapshot($vm); create_snapshot($vm);
} }
log "Snapshot of '$vmname' successfully created"; log_message "Snapshot of '$vmname' successfully created";
} }
sub migrate_machine { sub migrate_machine {
log "Migrating '$vmname' to $dst_host"; log_message "Migrating '$vmname' to $dst_host";
unless ($priority) { unless ($priority) {
$priority = "highPriority"; $priority = "highPriority";
@ -687,7 +735,7 @@ sub migrate_machine {
); );
$vm->PowerOnVM(); $vm->PowerOnVM();
log "Migration of '$vmname' successfull"; log_message "Migration of '$vmname' successfull";
} }
#--------------------------------- Utils #--------------------------------- Utils
@ -711,18 +759,7 @@ sub open_machine() {
$vm_datastore = $_->{name}; $vm_datastore = $_->{name};
} }
log "Found machine '$vmname' at host $remote_host at datastore '$vm_datastore'"; log_message "Found machine '$vmname' at host $remote_host at datastore '$vm_datastore'";
}
sub open_log {
open($log_fh, '>', %config{log_file});
}
sub log {
my ($message) = @_;
my $time = Time::Piece->new;
my $timeMark = $time->strftime('%Y-%m-%d %H:%M:%S');
print $log_fh "$timeMark : $message\n";
} }
sub setCBT { sub setCBT {
@ -731,7 +768,7 @@ sub setCBT {
return; return;
} }
eval { eval {
log "Switching CBT to $enable"; log_message "Switching CBT to $enable";
my $spec = Vim::VirtualMachineConfigSpec->new(changeTrackingEnabled => $enable); my $spec = Vim::VirtualMachineConfigSpec->new(changeTrackingEnabled => $enable);
my $task = $vm->ReconfigVM_Task(spec => $spec); my $task = $vm->ReconfigVM_Task(spec => $spec);
}; };
@ -756,9 +793,9 @@ sub execute_ssh_command {
my ($command) = @_; my ($command) = @_;
my $promptEnd = '/\w+[\$\%\#\>]\s{0,1}$/o'; my $promptEnd = '/\w+[\$\%\#\>]\s{0,1}$/o';
my $ssh = Net::OpenSSH->new($remote_host) or die "Cannot connect to $dst_host via SSH"; my $ssh = Net::OpenSSH->new($remote_host) or die "Cannot connect to $dst_host via SSH";
log "SSH: $remote_host: $command"; log_message "SSH: $remote_host: $command";
my $result = $ssh->capture($command); my $result = $ssh->capture($command);
log "SSH: Result: $result"; log_message "SSH: Result: $result";
$ssh->system('exit'); $ssh->system('exit');
return substr($result, 0, 200); return substr($result, 0, 200);
} }
@ -771,11 +808,11 @@ sub set_power_state {
given ($state) { given ($state) {
when ('poweredOff') { when ('poweredOff') {
$vmPower->ShutdownGuest(); $vmPower->ShutdownGuest();
log "Turning off ".$vmPower->name; log_message "Turning off ".$vmPower->name;
} }
when ('poweredOn') { when ('poweredOn') {
$vmPower->PowerOnVM(); $vmPower->PowerOnVM();
log "Turning on ".$vmPower->name; log_message "Turning on ".$vmPower->name;
} }
} }
sleep(50); sleep(50);