#!/usr/bin/perl -w ################################################################## # Author: William Lam # Email: william2003[at]gmail[dot]com # 02/13/2009 # http://www.engineering.ucsb.edu/~duonglt/vmware/ ################################################################## use strict; use warnings; use Getopt::Long; use VMware::VIRuntime; use VMware::VILib; #################### # GLOBAL VARIABLES #################### my $host_type; my $host_view; my $ups_vm_name; my $ups_vm; my $content; my $sleep_duration; my $final_host_wait = 30; my %opts = ( ups_vm => { type => "=s", help => "The name of VM that is monitoring your UPS", required => 1, }, sleep => { type => "=i", help => "The amount of time (secs) to wait after a guestOS shutdown (default 15 secs)", required => 0, }, ); # validate options, and connect to the server Opts::add_options(%opts); # validate options, and connect to the server Opts::parse(); Opts::validate(); Util::connect(); if (Opts::option_is_set ('ups_vm') ) { $ups_vm_name = Opts::get_option('ups_vm'); } if (Opts::option_is_set ('sleep') ) { $sleep_duration = Opts::get_option('sleep'); } else { $sleep_duration = 15; } ############################ # PARSE COMMANDLINE OPTIONS ############################# $content = Vim::get_service_content(); $host_type = $content->about->apiType; if($host_type eq 'HostAgent') { $host_view = Vim::find_entity_views(view_type => 'HostSystem'); if (!$host_view) { print "ESX/ESXi host was not found\n"; } else { shutdownVMs($host_view); } } Util::disconnect(); ### HELPER FUNCTIONS ### sub shutdownVMs { my ($host) = @_; my $found_vima; foreach(@$host) { print giveMeDate('MDYHMS')," -- Found ESX/ESXi host: ",$_->name,"!\n"; print "\t",giveMeDate('MDYHMS')," -- Begin shutdown process ...\n"; my $vm_views = Vim::get_views (mo_ref_array => $_->vm); my $found_vima = 0; foreach my $vm (@$vm_views) { my $vm_name = $vm->summary->config->name; next if(!defined($vm_name)); if($vm_name ne $ups_vm_name) { if($vm->runtime->powerState->val eq 'poweredOn') { eval { $vm->ShutdownGuest(); sleep($sleep_duration); print "\t",giveMeDate('MDYHMS')," -- VM: ", $vm_name," shutdown succssfully.\n"; }; if($@) { eval { $vm->PowerOffVM(); sleep(5); print "\t",giveMeDate('MDYHMS')," -- VM: ", $vm_name," hard poweroff succssful (No VMware Tools, bad admin).\n"; }; if($@) { print "\t",giveMeDate('MDYHMS')," -- WARNING VM: ", $vm_name, " failed to hard power down, please verify this system later!\n"; } } } elsif($vm->runtime->powerState->val eq 'poweredOff') { print "\t",giveMeDate('MDYHMS')," -- VM: ", $vm_name," is already off.\n"; } elsif($vm->runtime->powerState->val eq 'suspended') { print "\t",giveMeDate('MDYHMS')," -- VM: ", $vm_name," is already suspended.\n"; } } else { $found_vima = 1; $ups_vm = $vm; } } #shutdown if you did not find VIMA if($found_vima == 0) { shutdownHost($_,'1'); } elsif ($found_vima == 1) { my $vima_host_view = Vim::get_view(mo_ref => $ups_vm->runtime->host); shutdownHost($vima_host_view,'2'); } } } sub shutdownHost { my ($host,$shutdown_type) = @_; my $hostname = $host->name; if($shutdown_type eq '1') { print "\t", giveMeDate('MDYHMS')," -- HOST: ", $hostname, " is shutting down!\n"; eval { $host->ShutdownHost(force => 1); }; } else { print "\t", giveMeDate('MDYHMS')," -- Shutting down final host: $hostname and UPS VM: $ups_vm_name!\n"; sleep($final_host_wait); eval { $host->ShutdownHost(force => 1); }; print "==============================================================================================\n"; } } sub giveMeDate { my ($date_format) = @_; my %dttime = (); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my $my_time; ### begin_: initialize DateTime number formats $dttime{year } = sprintf "%04d",($year + 1900); ## four digits to specify the year $dttime{mon } = sprintf "%02d",($mon + 1); ## zeropad months $dttime{mday } = sprintf "%02d",$mday; ## zeropad day of the month $dttime{wday } = sprintf "%02d",$wday + 1; ## zeropad day of week; sunday = 1; $dttime{yday } = sprintf "%02d",$yday; ## zeropad nth day of the year $dttime{hour } = sprintf "%02d",$hour; ## zeropad hour $dttime{min } = sprintf "%02d",$min; ## zeropad minutes $dttime{sec } = sprintf "%02d",$sec; ## zeropad seconds $dttime{isdst} = $isdst; if($date_format eq 'MDYHMS') { $my_time = "$dttime{mon}-$dttime{mday}-$dttime{year} $dttime{hour}:$dttime{min}:$dttime{sec}"; } elsif ($date_format eq 'YMD') { $my_time = "$dttime{year}-$dttime{mon}-$dttime{mday}"; } return $my_time; }