Author: arkurth
Date: Thu Mar 6 18:50:32 2014
New Revision: 1574996
URL: http://svn.apache.org/r1574996
Log:
VCL-734
Updated new.pm::computer_not_being_used to not use recursion. This could cause
recursive loops. Added a multiple attempt loop instead.
Moved command to rename the forked process from State.pm::initialize to
vcld::make_new_child. This was done to have the rename occur as early as
possible. Other reservations run pgrep and use the process name to determine if
another process is running for a reservation. This allows a running process to
be detected sooner after a process begins.
Added Semaphore.pm::get_process_semaphore_ids. This is used in
new.pm::computer_not_being_used to detect if a running reload process may be
transferring an image. It's possible for old, stale semaphore lockfiles to
exist in /tmp. This subroutine verifies that the lockfile matches the PID of
the other running process.
Added check to State.pm::initialize if it fails to update the state to pending.
There are a few cases where this is normal such as if the request was deleted
in the brief time before it could be updated to pending.
Updated utils.pm::reservation_being_processed to return either an array or
integer.
Modified:
vcl/trunk/managementnode/bin/vcld
vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
vcl/trunk/managementnode/lib/VCL/Module/State.pm
vcl/trunk/managementnode/lib/VCL/new.pm
vcl/trunk/managementnode/lib/VCL/utils.pm
Modified: vcl/trunk/managementnode/bin/vcld
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/bin/vcld?rev=1574996&r1=1574995&r2=1574996&view=diff
==============================================================================
--- vcl/trunk/managementnode/bin/vcld (original)
+++ vcl/trunk/managementnode/bin/vcld Thu Mar 6 18:50:32 2014
@@ -539,6 +539,9 @@ sub make_new_child {
$ENV{state} = $state;
$ENV{data} = $data_structure;
+ # Rename this process to include some request info
+ rename_vcld_process($data_structure);
+
#notify($ERRORS{'DEBUG'}, $LOGFILE, "creating new
process");
eval "use $state_module";
if ($EVAL_ERROR) {
Modified: vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm?rev=1574996&r1=1574995&r2=1574996&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm Thu Mar 6 18:50:32
2014
@@ -354,6 +354,70 @@ sub get_reservation_semaphore_ids {
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_process_semaphore_ids
+
+ Parameters : $pid
+ Returns : array
+ Description : Returns the Semaphore IDs opened by the process PID specified by
+ the argument. An empty list is returned if no Semaphores are
+ open.
+
+=cut
+
+sub get_process_semaphore_ids {
+ 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 $pid = shift;
+ if (!$pid) {
+ notify($ERRORS{'WARNING'}, 0, "process PID argument was not
supplied");
+ return;
+ }
+
+ my @lockfile_paths = $self->mn_os->find_files($LOCKFILE_DIRECTORY_PATH,
"*.$LOCKFILE_EXTENSION");
+ if (!@lockfile_paths) {
+ notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this
management node");
+ return ();
+ }
+
+ my @process_semaphore_ids;
+
+ for my $lockfile_path (@lockfile_paths) {
+ my ($semaphore_id) = $lockfile_path =~
/([^\/]+)\.$LOCKFILE_EXTENSION/;
+
+ my @lockfile_contents =
$self->mn_os->get_file_contents($lockfile_path);
+ if (!@lockfile_contents) {
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve
contents of lockfile: $lockfile_path");
+ next;
+ }
+
+ my $lockfile_line = $lockfile_contents[0];
+
+ # Line should contain a string similar to this:
+ # 31862 vclark 2376:3116 tomaintenance
vclv1-42>vclh3-12.hpc.ncsu.edu vmwarewinxp-base234-v14 admin
+ my ($lockfile_pid) = $lockfile_line =~ /^(\d+) /;
+
+ if (!defined($lockfile_pid)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to determine PID
from 1st line in $lockfile_path: '$lockfile_line'");
+ next;
+ }
+
+ if ($lockfile_pid == $pid) {
+ notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id'
belongs to process $pid");
+ push @process_semaphore_ids, $semaphore_id;
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id'
does NOT belong to process $pid");
+ }
+ }
+ return @process_semaphore_ids;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 DESTROY
Parameters : none
Modified: vcl/trunk/managementnode/lib/VCL/Module/State.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/State.pm?rev=1574996&r1=1574995&r2=1574996&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/State.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/State.pm Thu Mar 6 18:50:32 2014
@@ -106,9 +106,6 @@ sub initialize {
return;
}
- # Rename this process to include some request info
- rename_vcld_process($self->data);
-
# Update reservation lastcheck value to prevent processes from being
forked over and over if a problem occurs
my $reservation_lastcheck =
update_reservation_lastcheck($reservation_id);
if ($reservation_lastcheck) {
@@ -185,6 +182,23 @@ sub initialize {
# Update the request state to pending for this reservation
if (!update_request_state($request_id, "pending",
$request_state_name)) {
+ # Check if request was deleted
+ if (is_request_deleted($request_id)) {
+ exit;
+ }
+
+ # Check the current state
+ my ($current_request_state, $current_request_laststate)
= get_request_current_state_name($request_id);
+ if (!$current_request_state) {
+ # Request probably complete and already removed
+ notify($ERRORS{'DEBUG'}, 0, "current request
state could not be retrieved, it was probably completed by another vcld
process");
+ exit;
+ }
+ if ($current_request_state =~ /^(deleted|complete)$/ ||
$current_request_laststate =~ /^(deleted)$/) {
+ notify($ERRORS{'DEBUG'}, 0, "current request
state: $current_request_state/$current_request_laststate, exiting");
+ exit;
+ }
+
$self->reservation_failed("failed to update request
state to pending");
}
}
@@ -635,7 +649,7 @@ sub state_exit {
}
# Update the request state
- if (!is_request_deleted($request_id)) {
+ if ($request_state_name_old ne 'deleted' &&
!is_request_deleted($request_id)) {
# Check if the request state has already been
updated
# This can occur if another reservation in a
cluster failed
my ($request_state_name_current,
$request_laststate_name_current) = get_request_current_state_name($request_id);
Modified: vcl/trunk/managementnode/lib/VCL/new.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/new.pm?rev=1574996&r1=1574995&r2=1574996&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/new.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/new.pm Thu Mar 6 18:50:32 2014
@@ -553,7 +553,7 @@ sub reload_image {
notify($ERRORS{'OK'}, 0, "node status not checked,
node_status() not implemented by " . ref($self->provisioner) . ", assuming
load=true");
}
- #If reinstall state - force reload state
+ # If reinstall state - force reload state
$computer_state_name = 'reload' if ($request_state_name eq 'reinstall');
if ($computer_state_name eq 'reload') {
@@ -699,184 +699,199 @@ sub reload_image {
sub computer_not_being_used {
my $self = shift;
+
my $request_id = $self->data->get_request_id();
my $computer_id = $self->data->get_computer_id();
my $computer_short_name =
$self->data->get_computer_short_name();
- my $computer_state_name =
$self->data->get_computer_state_name();
my $imagerevision_id =
$self->data->get_imagerevision_id();
my $image_name = $self->data->get_image_name();
my $image_reloadtime =
$self->data->get_image_reload_time();
my $request_state_name =
$self->data->get_request_state_name();
- # Return 0 if computer state is maintenance, deleted, vmhostinuse
- if ($computer_state_name =~ /^(deleted|maintenance|vmhostinuse)$/) {
- notify($ERRORS{'WARNING'}, 0, "$computer_short_name is NOT
available, its state is $computer_state_name");
- return 0;
- }
-
- # Warn if computer state isn't available or reload - except for
reinstall requests
- if ($request_state_name !~ /^(reinstall)$/ && $computer_state_name !~
/^(available|reload)$/) {
- notify($ERRORS{'WARNING'}, 0, "$computer_short_name state is
$computer_state_name, checking if any conflicting reservations are active");
- }
-
- # Check if there is another request using this machine
- # Get a hash containing all of the reservations for the computer
- notify($ERRORS{'OK'}, 0, "retrieving info for reservations assigned to
$computer_short_name");
- my $competing_request_info = get_request_by_computerid($computer_id);
-
- # There should be at least 1 request -- the one being processed
- if (!$competing_request_info) {
- notify($ERRORS{'WARNING'}, 0, "failed to retrieve any requests
for computer id=$computer_id, there should be at least 1");
- return;
- }
-
- # Remove the request currently being processed from the hash
- delete $competing_request_info->{$request_id};
-
- if (!keys(%$competing_request_info)) {
- notify($ERRORS{'OK'}, 0, "$computer_short_name is not assigned
to any other reservations");
- return 1;
- }
-
- # Loop through the competing requests
- COMPETING_REQUESTS: for my $competing_request_id (sort keys
%$competing_request_info) {
- my $competing_reservation_id =
$competing_request_info->{$competing_request_id}{data}->get_reservation_id();
- my $competing_request_state =
$competing_request_info->{$competing_request_id}{data}->get_request_state_name();
- my $competing_request_laststate =
$competing_request_info->{$competing_request_id}{data}->get_request_laststate_name();
- my $competing_imagerevision_id =
$competing_request_info->{$competing_request_id}{data}->get_imagerevision_id();
- my $competing_request_start =
$competing_request_info->{$competing_request_id}{data}->get_request_start_time();
- my $competing_request_end =
$competing_request_info->{$competing_request_id}{data}->get_request_end_time();
-
- my $competing_request_start_epoch =
convert_to_epoch_seconds($competing_request_start);
- my $competing_request_end_epoch =
convert_to_epoch_seconds($competing_request_end);
-
- my $now_epoch = time;
-
- my $competing_request_info_string;
- $competing_request_info_string .= "request:reservation ID:
$competing_request_id:$competing_reservation_id\n";
- $competing_request_info_string .= "request state:
$competing_request_state/$competing_request_laststate\n";
- $competing_request_info_string .= "request start time:
$competing_request_start\n";
- $competing_request_info_string .= "request end time:
$competing_request_end";
-
- notify($ERRORS{'DEBUG'}, 0, "checking reservation assigned to
$computer_short_name:\n$competing_request_info_string");
-
- # Check for existing image creation requests
- if ($competing_request_state =~ /^(image)$/ ||
$competing_request_laststate =~ /^(image)$/) {
- notify($ERRORS{'WARNING'}, 0, "$computer_short_name is
NOT available, it is assigned to an existing imaging
reservation:\n$competing_request_info_string");
+ my $attempt_limit = 5;
+ ATTEMPT: for (my $attempt = 1; $attempt <= $attempt_limit; $attempt++) {
+ notify($ERRORS{'OK'}, 0, "attempt $attempt/$attempt_limit:
checking for competing reservations assigned to $computer_short_name");
+ my $computer_state_name =
$self->data->get_computer_state_name();
+
+ # Return 0 if computer state is maintenance, deleted,
vmhostinuse
+ if ($computer_state_name =~
/^(deleted|maintenance|vmhostinuse)$/) {
+ notify($ERRORS{'WARNING'}, 0, "$computer_short_name is
NOT available, its state is $computer_state_name");
return 0;
}
- # Check for any requests in the maintenance state
- if ($competing_request_state =~ /^(maintenance)$/) {
- notify($ERRORS{'WARNING'}, 0, "$computer_short_name is
NOT available, it is assigned to an existing request in the
'$competing_request_state' state:\n$competing_request_info_string");
- return 0;
+ # Warn if computer state isn't available or reload - except for
reinstall requests
+ if ($request_state_name !~ /^(reinstall)$/ &&
$computer_state_name !~ /^(available|reload)$/) {
+ notify($ERRORS{'WARNING'}, 0, "$computer_short_name
state is $computer_state_name, checking if any conflicting reservations are
active");
}
- # Ignore 'complete', 'failed' requests
- if ($competing_request_state =~ /^(complete|failed)$/) {
- notify($ERRORS{'DEBUG'}, 0, "ignoring request in state:
$competing_request_state/$competing_request_laststate");
- next COMPETING_REQUESTS;
- }
-
- # Check if the other reservation assigned to computer hasn't
started yet
- if ($competing_request_start_epoch > $now_epoch) {
- # If they overlap, let the other reservation worry
about it
- notify($ERRORS{'OK'}, 0, "request
$competing_request_id:$competing_reservation_id start time is in the future:
$competing_request_start");
- next COMPETING_REQUESTS;
- }
-
- # Check if the other reservation is a 'reload' reservation for
the same image revision
- if ($competing_imagerevision_id eq $imagerevision_id &&
$competing_request_state eq 'pending' && $competing_request_laststate =~
/(reload)/) {
- notify($ERRORS{'OK'}, 0, "reservation
$competing_reservation_id is currently loading $computer_short_name with the
correct image: $image_name, waiting for the other reload process to complete");
-
- my $message = "reload reservation
$competing_request_id:$competing_reservation_id is still loading
$computer_short_name with $image_name";
- my $total_wait_seconds = (60 * $image_reloadtime);
- my $attempt_delay_seconds = 30;
-
- # Loop until other process is done
- if ($self->code_loop_timeout(sub{return
!reservation_being_processed(@_)}, [$competing_reservation_id], $message,
$total_wait_seconds, $attempt_delay_seconds)) {
- notify($ERRORS{'DEBUG'}, 0, "reload reservation
$competing_reservation_id finished loading $computer_short_name with
$image_name");
-
- # Call this subroutine again in order to
retrieve a current list of competing reservations
- # The list of competing reservations may have
changed while waiting
- notify($ERRORS{'OK'}, 0, "calling this
subroutine again to retrieve the current list of competing reservations
assigned to $computer_short_name");
- return $self->computer_not_being_used();
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "reload
reservation $competing_reservation_id has NOT finished loading
$computer_short_name with $image_name, waited $total_wait_seconds seconds");
- }
+ # Check if there is another request using this machine
+ # Get a hash containing all of the reservations for the computer
+ my $competing_request_info =
get_request_by_computerid($computer_id);
+
+ # There should be at least 1 request -- the one being processed
+ if (!$competing_request_info) {
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve any
requests for computer id=$computer_id, there should be at least 1");
+ return;
}
- # Check if the other reservation assigned to computer end time
has been reached
- # -or-
- # Reload reservation -- either for a different image or the
previous check loop monitoring the reload process for the same image timed out
- #
- if ($competing_request_end_epoch <= $now_epoch ||
- ($competing_request_state =~
/(timeout|deleted|reload)/) ||
- ($competing_request_state eq 'pending' &&
$competing_request_laststate =~ /(timeout|deleted|reload)/)) {
-
- # Update the competing request state to complete
- # If this fails, check if the competing request has
already been deleted
- # Do this before checking if the reservation is being
processed to prevent new processes from being created
- if (update_request_state($competing_request_id,
"complete", ($competing_request_state eq 'pending') ?
$competing_request_laststate : $competing_request_state)) {
- notify($ERRORS{'OK'}, 0, "request state set to
'complete' for competing reservation $competing_reservation_id");
- }
- elsif (is_request_deleted($competing_request_id)) {
- notify($ERRORS{'OK'}, 0, "request state not set
to 'complete' for competing reservation $competing_reservation_id because
request has been deleted");
+ # Remove the request currently being processed from the hash
+ delete $competing_request_info->{$request_id};
+
+ if (!keys(%$competing_request_info)) {
+ notify($ERRORS{'OK'}, 0, "$computer_short_name is not
assigned to any other reservations");
+ return 1;
+ }
+
+ # Loop through the competing requests
+ COMPETING_REQUESTS: for my $competing_request_id (sort keys
%$competing_request_info) {
+ my $competing_reservation_id =
$competing_request_info->{$competing_request_id}{data}->get_reservation_id();
+ my $competing_request_state =
$competing_request_info->{$competing_request_id}{data}->get_request_state_name();
+ my $competing_request_laststate =
$competing_request_info->{$competing_request_id}{data}->get_request_laststate_name();
+ my $competing_imagerevision_id =
$competing_request_info->{$competing_request_id}{data}->get_imagerevision_id();
+ my $competing_request_start =
$competing_request_info->{$competing_request_id}{data}->get_request_start_time();
+ my $competing_request_end =
$competing_request_info->{$competing_request_id}{data}->get_request_end_time();
+
+ my $competing_request_start_epoch =
convert_to_epoch_seconds($competing_request_start);
+ my $competing_request_end_epoch =
convert_to_epoch_seconds($competing_request_end);
+
+ my $now_epoch = time;
+
+ my $competing_request_info_string;
+ $competing_request_info_string .= "request:reservation
ID: $competing_request_id:$competing_reservation_id\n";
+ $competing_request_info_string .= "request state:
$competing_request_state/$competing_request_laststate\n";
+ $competing_request_info_string .= "request start time:
$competing_request_start\n";
+ $competing_request_info_string .= "request end time:
$competing_request_end";
+
+ notify($ERRORS{'DEBUG'}, 0, "checking reservation
assigned to $computer_short_name:\n$competing_request_info_string");
+
+ # Check for existing image creation requests
+ if ($competing_request_state =~ /^(image)$/ ||
$competing_request_laststate =~ /^(image)$/) {
+ notify($ERRORS{'WARNING'}, 0,
"$computer_short_name is NOT available, it is assigned to an existing imaging
reservation:\n$competing_request_info_string");
+ return 0;
}
- else {
- notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, failed to set request state to
'complete', competing request has NOT been
deleted:\n$competing_request_info_string");
+
+ # Check for any requests in the maintenance state
+ if ($competing_request_state =~ /^(maintenance)$/) {
+ notify($ERRORS{'WARNING'}, 0,
"$computer_short_name is NOT available, it is assigned to an existing request
in the '$competing_request_state' state:\n$competing_request_info_string");
return 0;
}
- # Check if the other reservation is still being
processed
- if
(reservation_being_processed($competing_reservation_id)) {
- notify($ERRORS{'OK'}, 0, "reservation
$competing_reservation_id is currently being processed, making sure the process
doesn't have any Semaphore objects open before attempting to kill it");
+ # Ignore 'complete', 'failed' requests
+ if ($competing_request_state =~ /^(complete|failed)$/) {
+ notify($ERRORS{'DEBUG'}, 0, "ignoring request
in state: $competing_request_state/$competing_request_laststate");
+ next COMPETING_REQUESTS;
+ }
+
+ # Check if the other reservation assigned to computer
hasn't started yet
+ if ($competing_request_start_epoch > $now_epoch) {
+ # If they overlap, let the other reservation
worry about it
+ notify($ERRORS{'OK'}, 0, "request
$competing_request_id:$competing_reservation_id start time is in the future:
$competing_request_start");
+ next COMPETING_REQUESTS;
+ }
+
+ # Check if the other reservation is a 'reload'
reservation for the same image revision
+ if ($competing_imagerevision_id eq $imagerevision_id &&
$competing_request_state =~ /^(pending|reload)$/ &&
$competing_request_laststate =~ /(reload)/) {
+ notify($ERRORS{'OK'}, 0, "reservation
$competing_reservation_id is assigned to $computer_short_name with the same
image revision: $image_name, waiting for the other reload process to complete");
- # Create a Semaphore object and check if the
competing process owns any of its own Semaphore objects
- # This would indicate it's doing something such
as retrieving an image
- # Don't kill it or a partial image may be copied
- my $semaphore = VCL::Module::Semaphore->new();
- if
($semaphore->get_reservation_semaphore_ids($competing_reservation_id)) {
- notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, reservation $competing_reservation_id is
still being processed and owns a Semaphore object, not killing the competing
process, it may be transferring an image:\n$competing_request_info_string");
- return 0;
- }
+ my $message = "waiting for reload reservation
$competing_request_id:$competing_reservation_id to finish loading
$computer_short_name with $image_name";
- # Kill competing process and update request
state to complete
- notify($ERRORS{'OK'}, 0, "attempting to kill
process of competing reservation $competing_reservation_id assigned to
$computer_short_name");
- if
(kill_reservation_process($competing_reservation_id)) {
- notify($ERRORS{'OK'}, 0, "killed
process for competing reservation $competing_reservation_id");
- }
+ # Wait at least 5 minutes
+ $image_reloadtime = 5 if $image_reloadtime < 10;
+ my $total_wait_seconds = (60 *
$image_reloadtime);
+ my $attempt_delay_seconds = 10;
- # Wait for competing process to end before
verifying that it was successfully killed
- sleep 2;
+ # Loop until other process is done
+ if ($self->code_loop_timeout(sub{return
!reservation_being_processed(@_)}, [$competing_reservation_id], $message,
$total_wait_seconds, $attempt_delay_seconds)) {
+ notify($ERRORS{'DEBUG'}, 0, "reload
reservation $competing_reservation_id is not loading $computer_short_name with
$image_name");
+ # Verified competing 'reload' is not
being processed verify it is not stuck in pending/reload
+ my ($current_competing_request_state,
$current_competing_request_laststate) =
get_request_current_state_name($competing_request_id);
+ if ($current_competing_request_state eq
'pending' && $current_competing_request_laststate eq 'reload') {
+ notify($ERRORS{'OK'}, 0, "state
of competing reload request $competing_request_id:$competing_reservation_id is
$current_competing_request_state/$current_competing_request_laststate, verified
it is not being processed, changing state of competing request
$competing_request_id to 'complete'");
+
update_request_state($competing_request_id, 'complete', 'reload');
+ }
+
+ # Try again in order to retrieve a
current list of competing reservations
+ # The list of competing reservations
may have changed while waiting
+ notify($ERRORS{'OK'}, 0, "making
another attempt to retrieve the current list of competing reservations assigned
to $computer_short_name");
+ next ATTEMPT;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "reload
reservation $competing_reservation_id has NOT finished loading
$computer_short_name with $image_name, waited $total_wait_seconds seconds");
+ }
+ }
+
+ # Check if the other reservation assigned to computer
end time has been reached
+ # -or-
+ # Reload reservation -- either for a different image or
the previous check loop monitoring the reload process for the same image timed
out
+ if ($competing_request_end_epoch <= $now_epoch ||
+ ($competing_request_state =~
/(timeout|deleted|reload)/) ||
+ ($competing_request_state eq 'pending' &&
$competing_request_laststate =~ /(timeout|deleted|reload)/)) {
- # Verify that the competing reservation process
was killed
- if
(reservation_being_processed($competing_reservation_id)) {
- notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, failed to kill process for competing
reservation, competing reservation is still being
processed:\n$competing_request_info_string");
+ # Update the competing request state to complete
+ # If this fails, check if the competing request
has already been deleted
+ # Do this before checking if the reservation is
being processed to prevent new processes from being created
+ if (update_request_state($competing_request_id,
"complete", ($competing_request_state eq 'pending') ?
$competing_request_laststate : $competing_request_state)) {
+ notify($ERRORS{'OK'}, 0, "request state
set to 'complete' for competing reservation $competing_reservation_id");
+ }
+ elsif
(is_request_deleted($competing_request_id)) {
+ notify($ERRORS{'OK'}, 0, "request state
not set to 'complete' for competing reservation $competing_reservation_id
because request has been deleted");
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0,
"computer $computer_short_name is NOT available, failed to set request state to
'complete', competing request has NOT been
deleted:\n$competing_request_info_string");
return 0;
}
+
+ # Check if the other reservation is still being
processed
+ if (my @competing_reservation_pids =
reservation_being_processed($competing_reservation_id)) {
+ notify($ERRORS{'OK'}, 0, "reservation
$competing_reservation_id is currently being processed by PID(s): " . join(',
', @competing_reservation_pids) . ", making sure the process doesn't have any
Semaphore objects open before attempting to kill it");
+
+ # Create a Semaphore object and check
if the competing process owns any of its own Semaphore objects
+ # This would indicate it's doing
something such as retrieving an image
+ # Don't kill it or a partial image may
be copied
+ my $semaphore =
VCL::Module::Semaphore->new();
+ for my $competing_reservation_pid
(@competing_reservation_pids) {
+ if
($semaphore->get_process_semaphore_ids($competing_reservation_pid)) {
+
notify($ERRORS{'CRITICAL'}, 0, "computer $computer_short_name is NOT available,
reservation $competing_reservation_id is still being processed and owns a
Semaphore object, not killing the competing process, it may be transferring an
image:\n$competing_request_info_string");
+ return;
+ }
+ }
+
+ # Kill competing process and update
request state to complete
+ notify($ERRORS{'OK'}, 0, "attempting to
kill process of competing reservation $competing_reservation_id assigned to
$computer_short_name");
+ if
(kill_reservation_process($competing_reservation_id)) {
+ notify($ERRORS{'OK'}, 0,
"killed process for competing reservation $competing_reservation_id");
+ }
+
+ # Wait for competing process to end
before verifying that it was successfully killed
+ sleep 2;
+
+ # Verify that the competing reservation
process was killed
+ if
(reservation_being_processed($competing_reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0,
"computer $computer_short_name is NOT available, failed to kill process for
competing reservation, competing reservation is still being
processed:\n$competing_request_info_string");
+ return 0;
+ }
+ }
+
+ # Try again in order to retrieve a current list
of competing reservations
+ # The list of competing reservations may have
changed
+ # A new reload reservation may have been added
by timeout/deleted processes
+ notify($ERRORS{'OK'}, 0, "making another
attempt to retrieve the current list of competing reservations assigned to
$computer_short_name");
+ next ATTEMPT;
+ }
+ elsif
(reservation_being_processed($competing_reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, assigned overlapping reservations,
competing reservation is currently being
processed:\n$competing_request_info_string");
+ return 0;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, assigned overlapping reservations,
competing reservation is NOT currently being
processed:\n$competing_request_info_string");
+ return 0;
}
-
- # Call this subroutine again in order to retrieve a
current list of competing reservations
- # The list of competing reservations may have changed
- # A new reload reservation may have been added by
timeout/deleted processes
- notify($ERRORS{'OK'}, 0, "calling this subroutine again
to retrieve the current list of competing reservations assigned to
$computer_short_name");
- return $self->computer_not_being_used();
- }
- elsif (reservation_being_processed($competing_reservation_id)) {
- notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, assigned overlapping reservations,
competing reservation is currently being
processed:\n$competing_request_info_string");
- return 0;
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "computer
$computer_short_name is NOT available, assigned overlapping reservations,
competing reservation is NOT currently being
processed:\n$competing_request_info_string");
- return 0;
}
+
+ # Checked all competing requests and didn't find any
conflicting reservations
+ notify($ERRORS{'OK'}, 0, "$computer_short_name is available,
did not find any conflicting reservations");
+ return 1;
}
-
- # Checked all competing requests and didn't find any conflicting
reservations
- notify($ERRORS{'OK'}, 0, "$computer_short_name is available, did not
find any conflicting reservations");
- return 1;
}
#/////////////////////////////////////////////////////////////////////////////
Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL:
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1574996&r1=1574995&r2=1574996&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Thu Mar 6 18:50:32 2014
@@ -1290,16 +1290,17 @@ AND request.stateid = currentstate.id
AND request.laststateid = currentlaststate.id
AND state.name = '$state_name'
AND laststate.name = '$laststate_name'
+AND currentstate.name != 'maintenance'
EOF
if (!$force) {
if ($state_name eq 'pending') {
+ # Avoid: deleted/inuse --> pending/inuse
$update_statement .= "AND laststate.name =
currentstate.name\n";
}
elsif ($state_name !~ /(complete|failed|maintenance)/) {
# New state is not pending
- # Need to avoid:
- # pending/image --> inuse/inuse
+ # Avoid: pending/image --> inuse/inuse
$update_statement .= "AND currentstate.name =
'pending'\n";
$update_statement .= "AND currentlaststate.name =
'$laststate_name'\n";
}
@@ -6541,7 +6542,6 @@ sub get_user_info {
notify($ERRORS{'DEBUG'}, 0, "retrieving current user
info for '$user_identifier' from database, cached data is stale:
$data_age_seconds seconds old");
}
}
- notify($ERRORS{'DEBUG'}, 0, "retrieving user info: $user_identifier");
# If affiliation identifier argument wasn't supplied, set it to %
wildcard
$affiliation_identifier = '%' if !$affiliation_identifier;
@@ -6653,7 +6653,7 @@ EOF
if (!$user_info->{uid}) {
$user_info->{uid} = ($user_info->{id} + 500);
$user_info->{STANDALONE} = 1;
- notify($ERRORS{'DEBUG'}, 0, "UID value is not configured for
user $user_login_id, setting UID to VCL user ID: $user_login_id, standalone:
1");
+ notify($ERRORS{'DEBUG'}, 0, "UID value is not configured for
user '$user_login_id', setting UID: $user_info->{uid}, standalone: 1");
}
# Fix the unityid if the user's UID is >= 1,000,000
@@ -7327,7 +7327,7 @@ sub format_data {
}
# If a string was passed which appears to be XML, convert it to a hash
using XML::Simple
- if (scalar(@data) == 1 && !ref($data[0]) && $data[0] =~ /^</) {
+ if (scalar(@data) == 1 && defined($data[0]) && !ref($data[0]) &&
$data[0] =~ /^</) {
my $xml_hashref = xml_string_to_hash($data[0]);
return format_data($xml_hashref);
}
@@ -7638,7 +7638,17 @@ sub switch_vmhost_id {
Description : Retrieves the computerloadlog entries for all reservations
belonging to the request. A hash is constructed with keys set to
the reservation IDs. The data of each key is a reference to an
- array containing the computerloadstate names.
+ array containing the computerloadstate names. Example:
+ {
+ 3115 => [
+ "begin",
+ ],
+ 3116 => [
+ "begin",
+ "nodeready"
+ ]
+ }
+
=cut
@@ -7695,10 +7705,9 @@ EOF
=head2 reservation_being_processed
Parameters : reservation ID
- Returns : true if reservation is avtively being processed, false
otherwise
+ Returns : array or boolean
Description : Checks the computerloadlog table for rows matching the
- reservation ID and loadstate = begin. Returns true if any
- matching rows exist, false otherwise.
+ reservation ID and loadstate = begin.
=cut
@@ -7732,11 +7741,11 @@ sub reservation_being_processed {
# Check if at least 1 row was returned
my $computerloadlog_exists;
if (scalar @computerloadlog_rows == 1) {
- notify($ERRORS{'DEBUG'}, 0, "computerloadlog 'begin' entry
exists for reservation");
+ notify($ERRORS{'DEBUG'}, 0, "computerloadlog 'begin' entry
exists for reservation $reservation_id");
$computerloadlog_exists = 1;
}
elsif (scalar @computerloadlog_rows > 1) {
- notify($ERRORS{'WARNING'}, 0, "multiple computerloadlog 'begin'
entries exist for reservation");
+ notify($ERRORS{'WARNING'}, 0, "multiple computerloadlog 'begin'
entries exist for reservation $reservation_id");
$computerloadlog_exists = 1;
}
else {
@@ -7749,21 +7758,18 @@ sub reservation_being_processed {
# Check the results and return
if ($computerloadlog_exists && @processes_running) {
- notify($ERRORS{'DEBUG'}, 0, "reservation is currently being
processed, computerloadlog 'begin' entry exists and running process was found:
@processes_running");
- return 1;
+ notify($ERRORS{'DEBUG'}, 0, "reservation $reservation_id is
currently being processed, computerloadlog 'begin' entry exists and running
process was found: @processes_running");
}
elsif (!$computerloadlog_exists && @processes_running) {
- notify($ERRORS{'WARNING'}, 0, "computerloadlog 'begin' entry
does NOT exist but running process was found: @processes_running, assuming
reservation is currently being processed");
- return 1;
+ notify($ERRORS{'WARNING'}, 0, "computerloadlog 'begin' entry
does NOT exist but running process was found: @processes_running, assuming
reservation $reservation_id is currently being processed");
}
elsif ($computerloadlog_exists && !@processes_running) {
- notify($ERRORS{'WARNING'}, 0, "computerloadlog 'begin' entry
exists but running process was NOT found, assuming reservation is NOT currently
being processed");
- return 0;
+ notify($ERRORS{'WARNING'}, 0, "computerloadlog 'begin' entry
exists but running process was NOT found, assuming reservation $reservation_id
is NOT currently being processed");
}
else {
- notify($ERRORS{'DEBUG'}, 0, "reservation is NOT currently being
processed");
- return 0;
+ notify($ERRORS{'DEBUG'}, 0, "reservation $reservation_id is NOT
currently being processed");
}
+ return wantarray ? @processes_running : scalar(@processes_running);
}
#/////////////////////////////////////////////////////////////////////////////
@@ -8928,8 +8934,14 @@ sub setup_get_hash_choice {
if ($display_key1) {
$display_name = $hash_ref->{$key}{$display_key1};
}
+
if ($display_key2) {
- $display_name .= " (" .
$hash_ref->{$key}{$display_key2} . ")";
+ if ($display_key2 =~ /^([^-]+)-([^-]+)$/) {
+ $display_name .= " (" .
$hash_ref->{$key}{$1}{$2} . ")";
+ }
+ else {
+ $display_name .= " (" .
$hash_ref->{$key}{$display_key2} . ")";
+ }
}
if (!$display_name) {