|
|
@ -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);
|
|
|
|