Исправление для shutdownHostViaSOAPAPICall.pl
Некто по имени William Lam ранее, 12/10/2009, написал скрипт shutdownHostViaSOAPAPICall.pl, который при запуске выключал указанные в отдельном файле хосты VMware. Современные гипервизоры уже работатют исключительно по HTTPS с самоподписными сертификатами и скрипт это не учитывал. Ниже приведен текст с исправлением этого недостатка.
Дополнительно, помимо логина и пароля в переменную $sha1_thumb необходимо указать sha1 отпечаток сертификата хоста VMware.
Гипервизоры версий 6.5, 6.7 выключает без проблем.
#!/usr/local/bin/perl -w # William Lam # 12/10/2009 # http://engineering.ucsb.edu/~duonglt/vmware/ # http://communities.vmware.com/docs/DOC-9852
use strict; use warnings; use Term::ANSIColor; use LWP::UserAgent; use HTTP::Request; use HTTP::Cookies; use Data::Dumper; # Please fill out the # username and password # for your ESX(i) host my $host_username = 'fillmein'; my $host_password = 'fillmein'; my $sha1_thumb = 'e5b8147c2225e72c2093958e101d03da16147c83'; #### DO NOT EDIT PAST HERE #### my @hostlist; my ($file,$request,$message,$response,$retval,$cookie); &verifyUserInput(); &processFile($file); print 'File loaded OK\n'; foreach my $hostname(@hostlist) { ######################## # intial hello message ######################## $message = &createHelloMessage($host_username,$host_password); $response = &sendRequest($hostname,$message); $retval = checkReponse($response); if($retval eq 1) { ######################## # grab cookie ######################## my $cookie = &extractCookie($response); ######################## # shutdown message ######################## $message = createShutdownMessage(); ######################## # hasta la vista ESX(i) ######################## print color("yellow") . "Creating and sending shutdown command to $hostname ...\n" . color("reset"); $response = &sendRequest($hostname,$message,$cookie); $retval = checkReponse($response); if($retval eq 1) { print "\t" . color("green") . "Succesfully initiated shutdown of $hostname\n\n" . color("reset"); } else { print "\t" . color("red") . "Sent shutdown message but did not get confirmation back from $hostname\n\n" . color("reset"); } } else { print color("red") . "Failed to issue shutdown command to $hostname\n\n" . color("reset"); } } ##################### # # HELP FUNCTIONS # ##################### sub sendRequest { my ($host,$msg,$cookie) = @_; my $host_to_connect = "https://" . $host . "/sdk"; my $userAgent = LWP::UserAgent->new(agent => 'VMware VI Client/4.0.0'); $userAgent->ssl_opts(SSL_fingerprint => 'sha1$'.$sha1_thumb); my $request = HTTP::Request->new(POST => $host_to_connect); $request->header(SOAPAction => '"urn:internalvim25/4.0"'); $request->content($msg); $request->content_type("text/xml; charset=utf-8"); if(defined($cookie)) { $cookie->add_cookie_header($request); } my $rsp = $userAgent->request($request); } sub createHelloMessage { my ($user,$pass) = @_; my $msg = <<SOAP_HELLO_MESSAGE; <soap:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Login xmlns="urn:internalvim25"> <_this xsi:type="SessionManager" type="SessionManager" serverGuid="">ha-sessionmgr</_this> <userName>$user</userName> <password>$pass</password> <locale>en_US</locale> </Login> </soap:Body> </soap:Envelope> SOAP_HELLO_MESSAGE return $msg; } sub createShutdownMessage { my $msg = <<SOAP_SHUTDOWN_MESSAGE; <soap:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ShutdownHost_Task xmlns="urn:internalvim25"> <_this xsi:type="HostSystem" type="HostSystem" serverGuid="">ha-host</_this> <force>true</force> </ShutdownHost_Task> </soap:Body> </soap:Envelope> SOAP_SHUTDOWN_MESSAGE return $msg; } sub extractCookie { my ($rsp) = @_; my $cookie_jar = HTTP::Cookies->new; $cookie_jar->extract_cookies($rsp); return $cookie_jar; } sub checkReponse { my ($resp) = @_; my $ret = -1; if($resp->code == 200) { #print $resp->as_string; return 1; } else { print "\n" . color("red") . $resp->error_as_HTML . color("reset") . "\n";; return $ret; } } # Subroutine to process the input file sub processFile { my ($hostlist) = @_; my $HANDLE; open (HANDLE, $hostlist) or die("ERROR: Can not locate \"$hostlist\" input file!\n"); my @lines = <HANDLE>; my @errorArray; my $line_no = 0; close(HANDLE); foreach my $line (@lines) { $line_no++; &TrimSpaces($line); if($line) { if($line =~ /^\s*:|:\s*$/){ print "Error in Parsing File at line: $line_no\n"; print "Continuing to the next line\n"; next; } my $host = $line; &TrimSpaces($host); push @hostlist,$host; } } } sub TrimSpaces { foreach (@_) { s/^\s+|\s*$//g } } sub verifyUserInput { if(@ARGV != 1 ) { print color("magenta") . "\nUsage: $0 [HOST_FILE]\n\n" . color("reset"); exit; } else { $file = $ARGV[0]; } if($host_username eq 'fillmein' || $host_password eq 'fillmein') { print color("red") . "Please fill in \$host_username & \$host_password information in the script prior to starting!\n\n" . color("reset"); exit } }