Author: arkurth
Date: Fri Aug  1 18:06:55 2014
New Revision: 1615186

URL: http://svn.apache.org/r1615186
Log:
VCL-769
Added VIM_SSH.pm::_check_service_pid. This checks if the contents of a 
service's PID file matches the parent service process. If they do not match, 
the PID file is updated. This is done before 'services.sh restart' is called.

Added a semaphore to the _services_restart subroutine so that multiple 
processes for the same VM host do not attempt to restart the services at the 
same time.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1615186&r1=1615185&r2=1615186&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm Fri 
Aug  1 18:06:55 2014
@@ -255,15 +255,127 @@ sub _services_restart {
        
        my $vmhost_computer_name = 
$self->vmhost_os->data->get_computer_short_name();
        
-       my $command = "services.sh restart";
-       my ($exit_status, $output) = $self->vmhost_os->execute($command);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to run command on VM host 
$vmhost_computer_name: $command");
+       # Check if the PID files for the following services are correct
+       $self->_check_service_pid('hostd-worker', 
'/var/run/vmware/vmware-hostd.PID');
+       $self->_check_service_pid('sfcb-vmware_bas', 
'/var/run/vmware/vicimprovider.PID');
+       
+       my $services_command = "services.sh restart";
+       my $semaphore = 
$self->get_semaphore("$vmhost_computer_name-vmware_services_restart", 0);
+       if (!$semaphore) {
+               notify($ERRORS{'OK'}, 0, "unable to obtain semaphore, another 
process is likely running '$services_command' on $vmhost_computer_name, 
sleeping for 30 seconds and then proceeding");
+               sleep_uninterrupted(30);
+               return 1;
+       }
+       
+       notify($ERRORS{'DEBUG'}, 0, "restarting VMware services on 
$vmhost_computer_name");
+       my ($services_exit_status, $services_output) = 
$self->vmhost_os->execute($services_command, 1, 90);
+       if (!defined($services_output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to run command on VM host 
$vmhost_computer_name: $services_command");
                return;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "executed command to restart VMware 
services on $vmhost_computer_name, command: '$command', output:\n" . join("\n", 
@$output));
+               notify($ERRORS{'OK'}, 0, "executed command to restart VMware 
services on $vmhost_computer_name, command: '$services_command', output:\n" . 
join("\n", @$services_output));
+       }
+       
+       return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _check_service_pid
+
+ Parameters  : $process_name, $pid_file_path
+ Returns     : boolean
+ Description : Checks if the PID stored in the PID file matches the parent PID
+               of the running service process. Problems occur if the file does
+               not match the running process PID. Most often, vim-cmd commands
+               fail with an error such as:
+               Connect to localhost failed: Connection failure
+               
+               The PID file is updated with the correct PID if the PID file
+               contents cannot be retrieved and parsed or if the PID stored in
+               the file does not match the running process.
+
+=cut
+
+sub _check_service_pid {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($process_name, $pid_file_path) = @_;
+       if (!defined($process_name) || !defined($pid_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "process name and PID file path 
arguments were not supplied");
+               return;
        }
+       
+       my $vmhost_computer_name = 
$self->vmhost_os->data->get_computer_short_name();
+       
+       # Retrieve the running PID
+       my $running_pid;
+       my $ps_command = "ps |grep $process_name |awk '{print \$2}'";
+       my ($ps_exit_status, $ps_output) = 
$self->vmhost_os->execute($ps_command);
+       if (!defined($ps_output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to run command to 
determine main $process_name PID on $vmhost_computer_name");
+       }
+       else {
+               ($running_pid) = "@$ps_output" =~ /(\d+)/g;
+               if ($running_pid) {
+                       notify($ERRORS{'DEBUG'}, 0, "retrieved parent 
$process_name PID: $running_pid");
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "unable to determine 
parent $process_name PID, command: '$ps_command', output:\n" . join("\n", 
@$ps_output));
+                       return;
+               }
+       }
+       
+       # Retrieve the PID stored in the PID file
+       my $file_pid;
+       my @pid_file_contents = 
$self->vmhost_os->get_file_contents($pid_file_path);
+       if (@pid_file_contents) {
+               ($file_pid) = "@pid_file_contents" =~ /(\d+)/g;
+               if ($file_pid) {
+                       notify($ERRORS{'DEBUG'}, 0, "retrieved PID stored in 
$pid_file_path: $file_pid");
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "unable to determine PID 
stored in $pid_file_path, contents:\n" . join("\n", @pid_file_contents));
+               }
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve contents of 
$pid_file_path");
+       }
+       
+       # Check if it is necessary to update the PID file
+       if ($file_pid) {
+               if ($file_pid eq $running_pid) {
+                       notify($ERRORS{'OK'}, 0, "PID in $pid_file_path 
($file_pid) matches PID of parent $process_name process ($running_pid), update 
not necessary");
+                       return 1;
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "PID in $pid_file_path 
($file_pid) does not match PID of parent $process_name process ($running_pid), 
updating $pid_file_path to contain $running_pid");
+               }
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "PID in $pid_file_path could not be 
determined, updating $pid_file_path to contain $running_pid");
+       }
+       
+       # Update the PID file with the correct PID
+       my $echo_command = "echo -n $running_pid > $pid_file_path";
+       my ($echo_exit_status, $echo_output) = 
$self->vmhost_os->execute($echo_command);
+       if (!defined($echo_output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to run command to update 
$pid_file_path on $vmhost_computer_name");
+               return;
+       }
+       elsif (grep(/(ash:|echo:)/, @$echo_output)) {
+               notify($ERRORS{'WARNING'}, 0, "error occurred updating 
$pid_file_path on $vmhost_computer_name, command: '$echo_command', output:\n" . 
joini("\n", @$echo_output));
+               return;
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "updated $pid_file_path on 
$vmhost_computer_name to contain the correct PID: $running_pid");
+       }
+       
        return 1;
 }
 


Reply via email to