Author: arkurth
Date: Fri Oct 17 17:41:20 2014
New Revision: 1632640
URL: http://svn.apache.org/r1632640
Log:
VCL-685
Updated VIM_SSH.pm::_run_vim_cmd to detect if another process is attempting to
run 'services.sh restart' to prevent multiple failed attempts. It does this by
checking if the semaphore exists after a failed attempt. Added
Module.pm::does_semaphore_exist. This calls Semaphore.pm::semaphore_exists.
Added utils.pm::set_reservation_lastcheck. This is called to set
reservation.lastcheck to 20 minutes prior to the end of the reservation when
VIM_SSH.pm detects uncorrectable problems. Updated
utils.pm:update_reservation_lastcheck to not change the value if the current
value is in the future.
Other
Added $no_cache=1 argument to calls to get_computer_info and get_vmhost_info in
DataStructure.pm. This should always get fresh data.
Removed requirement to be called as an object method from
Module.pm::create_mn_os_object. The '$self' variable wasn't being used anywhere.
Updated Module.pm::new to not create a new management node OS object if the
'mn_os' argument was specified. It had been needlessly creating multiple
objects.
Modified:
vcl/trunk/managementnode/lib/VCL/DataStructure.pm
vcl/trunk/managementnode/lib/VCL/Module.pm
vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
vcl/trunk/managementnode/lib/VCL/utils.pm
Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1632640&r1=1632639&r2=1632640&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Fri Oct 17 17:41:20 2014
@@ -657,7 +657,7 @@ sub _initialize : Init {
# Get the computer info if the computer_identifier argument was
specified and add it to this object
if ($computer_identifier) {
notify($ERRORS{'DEBUG'}, 0, "computer identifier argument was
specified, retrieving data for computer: $computer_identifier");
- my $computer_info = get_computer_info($computer_identifier);
+ my $computer_info = get_computer_info($computer_identifier, 1);
if (!$computer_info) {
notify($ERRORS{'WARNING'}, 0, "DataStructure object
could not be initialized, failed to retrieve data for computer:
$computer_identifier");
@@ -672,7 +672,7 @@ sub _initialize : Init {
# Get the VM host info if the vmhost_id argument was specified and add
it to this object
if ($vmhost_id) {
notify($ERRORS{'DEBUG'}, 0, "VM host identifier argument was
specified, retrieving data for VM host: $vmhost_id");
- my $vmhost_info = get_vmhost_info($vmhost_id);
+ my $vmhost_info = get_vmhost_info($vmhost_id, 1);
if (!$vmhost_info) {
notify($ERRORS{'WARNING'}, 0, "DataStructure object
could not be initialized, failed to retrieve data for VM host: $vmhost_id");
Modified: vcl/trunk/managementnode/lib/VCL/Module.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module.pm?rev=1632640&r1=1632639&r2=1632640&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Fri Oct 17 17:41:20 2014
@@ -198,7 +198,16 @@ sub new {
# Create a management node OS object
# Check to make sure the object currently being created is not a MN OS
object to avoid endless loop
if (!$self->isa('VCL::Module::OS::Linux::ManagementNode')) {
- if (my $mn_os = $self->create_mn_os_object()) {
+ my $mn_os;
+ # Check if the mn_os argument was provided
+ if ($args->{mn_os}) {
+ $mn_os = $args->{mn_os};
+ }
+ else {
+ $mn_os = $self->create_mn_os_object()
+ }
+
+ if ($mn_os) {
$self->set_mn_os($mn_os);
$self->data->set_mn_os($mn_os);
}
@@ -432,26 +441,6 @@ sub create_os_object {
=cut
sub create_mn_os_object {
- my $self = shift;
- unless (ref($self) && $self->isa('VCL::Module')) {
- notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
- return;
- }
-
- # Check if an OS object has already been stored in the calling object
- if (my $mn_os = $self->mn_os(0)) {
- return $mn_os;
- }
-
- # Make sure calling object isn't an OS module to avoid an infinite loop
- if ($self->isa('VCL::Module::OS::Linux::ManagementNode')) {
- notify($ERRORS{'WARNING'}, 0, "this subroutine cannot be called
from an existing management node OS module: " . ref($self));
- return;
- }
-
- my $request_data = $self->data->get_request_data();
- my $reservation_id = $self->data->get_reservation_id();
-
# Create a DataStructure object containing computer data for the
management node
my $mn_data;
eval {
@@ -627,7 +616,7 @@ sub create_provisioning_object {
return 0;
}
notify($ERRORS{'DEBUG'}, 0, "$provisioning_perl_package module loaded");
-
+
# Attempt to provisioner the object, pass it the mn_os object if it has
already been created
my $constructor_arguments = {};
$constructor_arguments->{data_structure} = $self->data();
@@ -1276,7 +1265,7 @@ sub get_semaphore {
}
# Attempt to create a new semaphore object
- my $semaphore = VCL::Module::Semaphore->new({'data_structure' =>
$self->data});
+ my $semaphore = VCL::Module::Semaphore->new({'data_structure' =>
$self->data, mn_os => $self->mn_os});
if (!$semaphore) {
notify($ERRORS{'WARNING'}, 0, "failed to create semaphore
object");
return;
@@ -1297,6 +1286,40 @@ sub get_semaphore {
#/////////////////////////////////////////////////////////////////////////////
+=head2 does_semaphore_exist
+
+ Parameters : $semaphore_id
+ Returns : boolean
+ Description : Determines if an open Semaphore exists on this management node
+ matching the $semaphore_id.
+
+=cut
+
+sub does_semaphore_exist {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my ($semaphore_id) = @_;
+ if (!$semaphore_id) {
+ notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not
supplied");
+ return;
+ }
+
+ # Attempt to create a new semaphore object
+ my $semaphore = VCL::Module::Semaphore->new({'data_structure' =>
$self->data, mn_os => $self->mn_os});
+ if (!$semaphore) {
+ notify($ERRORS{'WARNING'}, 0, "failed to create semaphore
object");
+ return;
+ }
+
+ return $semaphore->semaphore_exists($semaphore_id);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 setup_get_menu
Parameters : none
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=1632640&r1=1632639&r2=1632640&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
Oct 17 17:41:20 2014
@@ -90,7 +90,7 @@ sub initialize {
notify($ERRORS{'WARNING'}, 0, "required 'vmhost_os'
argument was not passed");
return;
}
-
+
#
if (ref $args->{vmhost_os} !~ /VCL::Module::OS/) {
notify($ERRORS{'CRITICAL'}, 0, "'vmhost_os' argument
passed is not a reference to a VCL::Module::OS object, type: " .
ref($args->{vmhost_os}));
@@ -177,12 +177,21 @@ sub _run_vim_cmd {
my $wait_seconds = 2;
my $connection_reset_errors = 0;
-
- while ($attempt++ < $attempt_limit) {
+ my $services_restart_detected = 0;
+ ATTEMPT: while ($attempt++ < $attempt_limit) {
if ($attempt > 1) {
# Wait before making next attempt
notify($ERRORS{'OK'}, 0, "sleeping $wait_seconds
seconds before making attempt $attempt/$attempt_limit");
sleep $wait_seconds;
+
+ my $semaphore_id =
"$vmhost_computer_name-vmware_services_restart";
+ if ($self->does_semaphore_exist($semaphore_id)) {
+ $services_restart_detected = 1;
+ notify($ERRORS{'DEBUG'}, 0, "detected another
process is restarting VMware services, sleeping for 10 seconds");
+ sleep_uninterrupted(10);
+ my $wait_message = "another process is
restarting VMware services on $vmhost_computer_name";
+
$self->code_loop_timeout(sub{!$self->does_semaphore_exist(@_)},
[$semaphore_id], $wait_message, 140, 5);
+ }
}
# The following error is somewhat common if several processes
are adding/removing VMs at the same time:
@@ -212,11 +221,36 @@ sub _run_vim_cmd {
$connection_reset_errors++;
notify($ERRORS{'OK'}, 0, "attempt
$attempt/$attempt_limit: connection reset while attempting to run command on VM
host $vmhost_computer_name: $command, output:\n" . join("\n", @$output));
- # If 3 connection reset errors occured, attempt to run
services.sh restart
- if ($connection_reset_errors == 3) {
- notify($ERRORS{'CRITICAL'}, 0, "calling
'services.sh restart', encountered $connection_reset_errors connection reset on
VM host $vmhost_computer_name, output:\n" . join("\n", @$output));
- $self->_services_restart();
+ # If 2 connection reset errors occured, attempt to run
services.sh restart
+ if ($connection_reset_errors == 2) {
+ if ($services_restart_detected) {
+ notify($ERRORS{'WARNING'}, 0,
"encountered $connection_reset_errors connection reset errors on VM host
$vmhost_computer_name, not calling 'services.sh restart', another process
already attempted it");
+ }
+ else {
+ notify($ERRORS{'OK'}, 0, "calling
'services.sh restart', encountered $connection_reset_errors connection reset
errors on VM host $vmhost_computer_name");
+ $self->_services_restart();
+ next ATTEMPT;
+ }
}
+ elsif ($connection_reset_errors > 2) {
+ notify($ERRORS{'WARNING'}, 0, "encountered
$connection_reset_errors connection reset errors on VM host
$vmhost_computer_name");
+ }
+ else {
+ next ATTEMPT;
+ }
+
+ # Problem probably won't correct itself
+ # If request state is 'inuse', set the
reservation.lastcheck value to 20 minutes before request.end
+ # This avoids 'inuse' processes from being created over
and over again which will fail
+ my $request_state_name =
$self->data->get_request_state_name();
+ #if ($request_state_name eq 'inuse') {
+ my $reservation_id =
$self->data->get_reservation_id();
+ my $request_end_time_epoch =
convert_to_epoch_seconds($self->data->get_request_end_time());
+ my $current_time_epoch = time;
+ my $reservation_lastcheck_epoch =
($request_end_time_epoch-(20*60));
+ set_reservation_lastcheck($reservation_id,
$reservation_lastcheck_epoch);
+ #}
+ return;
}
else {
# VIM command command was executed
@@ -279,9 +313,8 @@ sub _services_restart {
}
my $services_command = "services.sh restart";
-
notify($ERRORS{'DEBUG'}, 0, "restarting VMware services on
$vmhost_computer_name");
- my ($services_exit_status, $services_output) =
$self->vmhost_os->execute($services_command, 1, 120);
+ my ($services_exit_status, $services_output) =
$self->vmhost_os->execute($services_command, 0, 120);
if (!defined($services_output)) {
notify($ERRORS{'WARNING'}, 0, "failed to run command on VM host
$vmhost_computer_name: $services_command");
return;
@@ -289,7 +322,6 @@ sub _services_restart {
else {
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;
}
@@ -337,61 +369,74 @@ sub _check_service_pid {
($running_pid) = "@$ps_output" =~ /(\d+)/g;
if (!$running_pid) {
notify($ERRORS{'DEBUG'}, 0, "parent $process_name PID
is not running");
- return;
}
elsif ($running_pid > 1) {
notify($ERRORS{'DEBUG'}, 0, "retrieved parent
$process_name PID: $running_pid");
}
else {
notify($ERRORS{'WARNING'}, 0, "parent $process_name PID
not valid: $running_pid, command: '$ps_command', output:\n" . join("\n",
@$ps_output));
- return;
+ $running_pid = '';
}
}
- # 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");
+ # Check if the .pid file exists
+ my $pid_file_exists = $self->vmhost_os->file_exists($pid_file_path);
+ if (!$running_pid) {
+ if ($pid_file_exists) {
+ notify($ERRORS{'DEBUG'}, 0, "running $process_name
process was not detected but PID file exists: $pid_file_path, deleting file");
+ if ($self->vmhost_os->delete_file($pid_file_path)) {
+ notify($ERRORS{'DEBUG'}, 0, "deleted file on
$vmhost_computer_name: $pid_file_path");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to delete
file on $vmhost_computer_name: $pid_file_path");
+ }
+ return 1;
}
else {
- notify($ERRORS{'WARNING'}, 0, "unable to determine PID
stored in $pid_file_path, contents:\n" . join("\n", @pid_file_contents));
+ notify($ERRORS{'DEBUG'}, 0, "running $process_name
process was not detected and PID file does not exist: $pid_file_path");
+ return 1;
}
}
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;
+ if ($pid_file_exists) {
+ # Retrieve the PID stored in the PID file
+ my @pid_file_contents =
$self->vmhost_os->get_file_contents($pid_file_path);
+ if (@pid_file_contents) {
+ my ($file_pid) = "@pid_file_contents" =~
/(\d+)/g;
+ if ($file_pid) {
+ notify($ERRORS{'DEBUG'}, 0, "retrieved
PID stored in $pid_file_path: $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{'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");
+ }
+ }
+
+ # 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, "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");
+ notify($ERRORS{'OK'}, 0, "updated $pid_file_path on
$vmhost_computer_name to contain the correct PID: $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;
}
Modified: vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm?rev=1632640&r1=1632639&r2=1632640&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm Fri Oct 17 17:41:20
2014
@@ -194,8 +194,61 @@ sub open_lockfile {
return;
}
+ # Determine which process is locking the file
+ my @locking_pids = $self->get_lockfile_owning_pid($file_path);
+ if (@locking_pids) {
+ if (grep { $_ eq $PID } @locking_pids) {
+ # The current process already has an exclusive lock on
the file
+ # This could happen if open_lockfile is called more
than once for the same file in the same scope
+ notify($ERRORS{'WARNING'}, 0, "file is already locked
by this process: @locking_pids");
+ return;
+ }
+ else {
+ # Attempt to retrieve the names of the locking
process(es)
+ my ($ps_exit_status, $ps_output) = run_command("ps -o
pid=,cmd= @locking_pids", 1);
+ if (defined($ps_output) && !grep(/(ps:)/, @$ps_output))
{
+ notify($ERRORS{'DEBUG'}, 0, "file is locked by
another process: @locking_pids\n" . join("\n", @$ps_output));
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "file is locked by
another process: @locking_pids");
+ }
+ return;
+ }
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "unable to determine PIDs of
processes which prevented an exclusive lock to be obtained on $file_path, lock
may have been released before lsof command was executed");
+ }
+
+ return;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_lockfile_owning_pid
+
+ Parameters : $file_path
+ Returns : integer
+ Description : Runs lsof to determine if a process has an exclusive lock on the
+ lockfile.
+
+=cut
+
+sub get_lockfile_owning_pid {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ # Get the file path argument
+ my ($file_path) = @_;
+ if (!$file_path) {
+ notify($ERRORS{'WARNING'}, 0, "file path argument was not
supplied");
+ return;
+ }
+
# Run lsof to determine which process is locking the file
- my ($exit_status, $output) = run_command("/usr/sbin/lsof -Fp
$file_path", 1);
+ my ($exit_status, $output) = $self->mn_os->execute("/usr/sbin/lsof -Fp
$file_path", 0);
if (!defined($output)) {
notify($ERRORS{'WARNING'}, 0, "failed to run losf command to
determine which process is locking the file: $file_path");
return;
@@ -207,31 +260,19 @@ sub open_lockfile {
# Parse the lsof output to determine the PID
my @locking_pids = map { /^p(\d+)/ } @$output;
- if (@locking_pids && grep { $_ eq $PID } @locking_pids) {
- # The current process already has an exclusive lock on the file
- # This could happen if open_lockfile is called more than once
for the same file in the same scope
- notify($ERRORS{'WARNING'}, 0, "file is already locked by this
process: @locking_pids");
- return;
- }
- elsif (@locking_pids) {
- # Attempt to retrieve the names of the locking process(es)
- my ($ps_exit_status, $ps_output) = run_command("ps -o pid=,cmd=
@locking_pids", 1);
- if (defined($ps_output) && !grep(/(ps:)/, @$ps_output)) {
- notify($ERRORS{'DEBUG'}, 0, "file is locked by another
process: @locking_pids\n" . join("\n", @$ps_output));
- }
- else {
- notify($ERRORS{'DEBUG'}, 0, "file is locked by another
process: @locking_pids");
- }
- return;
+ my $locking_pid_count = scalar(@locking_pids);
+ if (@locking_pids) {
+ notify($ERRORS{'DEBUG'}, 0, "$file_path is locked by process" .
($locking_pid_count == 1 ? '' : 'es') . ": @locking_pids");
+ return @locking_pids;
}
elsif (grep(/\w/, @$output)) {
- notify($ERRORS{'WARNING'}, 0, "unable to determine PIDs from
lsof output\n:" . join("\n", @$output));
+ notify($ERRORS{'WARNING'}, 0, "failed to determine owning PID
of lockfile: $file_path, unable to determine PIDs from lsof output\n:" .
join("\n", @$output));
+ return;
}
else {
- notify($ERRORS{'DEBUG'}, 0, "lsof did not return any PIDs of
processes which prevented an exclusive lock to be obtained, lock may have been
released before lsof command was executed");
+ notify($ERRORS{'DEBUG'}, 0, "file is not locked of lockfile:
$file_path");
+ return ();
}
-
- return 0;
}
#/////////////////////////////////////////////////////////////////////////////
@@ -290,6 +331,83 @@ sub release_lockfile {
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_lockfile_paths
+
+ Parameters : none
+ Returns : array
+ Description : Returns the paths to all lockfiles.
+
+=cut
+
+sub get_lockfile_paths {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my @lockfile_paths = $self->mn_os->find_files($LOCKFILE_DIRECTORY_PATH,
"*.$LOCKFILE_EXTENSION");
+
+ my $lockfile_path_count = scalar(@lockfile_paths);
+ notify($ERRORS{'DEBUG'}, 0, "retreived $lockfile_path_count lockfile
path" . ($lockfile_path_count == 1 ? '' : 's') . ":\n" . join("\n",
@lockfile_paths));
+ return @lockfile_paths;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 semaphore_exists
+
+ Parameters : $semaphore_id
+ Returns : boolean
+ Description : Determines if an open Semaphore exists on this management node
+ matching the $semaphore_id.
+
+=cut
+
+sub semaphore_exists {
+ my $self = shift;
+ unless (ref($self) && $self->isa('VCL::Module')) {
+ notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a
function, it must be called as a class method");
+ return;
+ }
+
+ my ($semaphore_id) = @_;
+ if (!$semaphore_id) {
+ notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not
supplied");
+ return;
+ }
+
+ my @lockfile_paths = $self->get_lockfile_paths();
+ if (!@lockfile_paths) {
+ notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this
management node");
+ return ();
+ }
+
+ for my $lockfile_path (@lockfile_paths) {
+ my ($lockfile_semaphore_id) = $lockfile_path =~
/([^\/]+)\.$LOCKFILE_EXTENSION/;
+ if ($lockfile_semaphore_id ne $semaphore_id) {
+ next;
+ }
+
+ # Check if the lockfile is actually locked by another process
+ # It may have been released or deleted
+ my @lockfile_owning_pids =
$self->get_lockfile_owning_pid($lockfile_path);
+ if (@lockfile_owning_pids) {
+ notify($ERRORS{'DEBUG'}, 0, "'$semaphore_id' semaphore
exists, lockfile path: $lockfile_path, owning PID: @lockfile_owning_pids");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "ignoring lockfile not
locked by another process: $lockfile_path");
+ next;
+ }
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "'$semaphore_id' semaphore does not exist");
+ return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 get_reservation_semaphore_ids
Parameters : $reservation_id
@@ -313,14 +431,13 @@ sub get_reservation_semaphore_ids {
return;
}
- my @lockfile_paths = $self->mn_os->find_files($LOCKFILE_DIRECTORY_PATH,
"*.$LOCKFILE_EXTENSION");
+ my @lockfile_paths = $self->get_lockfile_paths();
if (!@lockfile_paths) {
notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this
management node");
return ();
}
my @reservation_semaphore_ids;
-
for my $lockfile_path (@lockfile_paths) {
my ($semaphore_id) = $lockfile_path =~
/([^\/]+)\.$LOCKFILE_EXTENSION/;
@@ -377,7 +494,7 @@ sub get_process_semaphore_ids {
return;
}
- my @lockfile_paths = $self->mn_os->find_files($LOCKFILE_DIRECTORY_PATH,
"*.$LOCKFILE_EXTENSION");
+ my @lockfile_paths = $self->get_lockfile_paths();
if (!@lockfile_paths) {
notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this
management node");
return ();
Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1632640&r1=1632639&r2=1632640&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Fri Oct 17 17:41:20 2014
@@ -206,6 +206,7 @@ our @EXPORT = qw(
set_hash_process_id
set_logfile_path
set_managementnode_state
+ set_reservation_lastcheck
set_variable
setnextimage
setup_confirm
@@ -5265,6 +5266,7 @@ SET
reservation.lastcheck = '$lastcheck'
WHERE
reservation.id IN ($reservation_id_string)
+AND reservation.lastcheck <= NOW()
EOF
# Call the database execute subroutine
@@ -5280,6 +5282,63 @@ EOF
#/////////////////////////////////////////////////////////////////////////////
+=head2 set_reservation_lastcheck
+
+ Parameters : $reservation_id, $lastcheck
+ Returns : string
+ Description : Updates reservation.lastcheck to the time specified.
+
+=cut
+
+sub set_reservation_lastcheck {
+ my ($reservation_id, $reservation_lastcheck) = @_;
+
+ # Check the passed parameter
+ if (!$reservation_id || !$reservation_lastcheck) {
+ notify($ERRORS{'WARNING'}, 0, "reservation ID and last check
datetime was not specified");
+ return;
+ }
+
+ if ($reservation_lastcheck !~ /:/) {
+ $reservation_lastcheck =
convert_to_datetime($reservation_lastcheck);
+ }
+ my $reservation_lastcheck_epoch =
convert_to_epoch_seconds($reservation_lastcheck);
+
+ # Only allow the lastcheck time to be set in the future
+ my $current_time_epoch = time;
+ my $duration_seconds =
($reservation_lastcheck_epoch-$current_time_epoch);
+ if ($duration_seconds < 0) {
+ notify($ERRORS{'WARNING'}, 0, "reservation.lastcheck not set to
$reservation_lastcheck for reservation ID $reservation_id, time is in the
past");
+ return;
+ }
+ elsif ($duration_seconds < (20*60)) {
+ notify($ERRORS{'WARNING'}, 0, "reservation.lastcheck not set to
$reservation_lastcheck for reservation ID $reservation_id, time is too close to
the current time");
+ return;
+ }
+
+ # Construct the update statement
+ my $update_statement = <<EOF;
+UPDATE
+reservation
+SET
+reservation.lastcheck = '$reservation_lastcheck'
+WHERE
+reservation.id = '$reservation_id'
+EOF
+
+ # Call the database execute subroutine
+ if (database_execute($update_statement)) {
+ notify($ERRORS{'DEBUG'}, 0, "reservation.lastcheck set to
'$reservation_lastcheck' for reservation ID $reservation_id");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to set
reservation.lastcheck to '$reservation_lastcheck' for reservation ID
$reservation_id");
+ return;
+ }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 update_log_loaded_time
Parameters : $request_logid