Author: arkurth
Date: Thu Dec 18 19:26:20 2014
New Revision: 1646516

URL: http://svn.apache.org/r1646516
Log:
VCL-16
Updated code which inserts computerloadlog 'acknowledgetimeout', 
'initialconnecttimeout' and 'reconnecttimeout' so the the timestamp of these 
entries is used to determine when to stop checking for ack or connection.

Removed condition in utils.pm::check_time where it would return 'poll' whenever 
request.laststate = reserved. This is no longer necessary.

Moved initial connection check from inuse.pm to reserved.pm. This fixed 
problems where the state was left in inuse/inuse after the first connection 
check causing the computer to always be reloaded.

Moved user_connected and check_imaging_request subroutines from inuse.pm to 
State.pm since it is now used by both inuse.pm and reserved.pm.

VCL-174
Removed computer IP address from email messages sent to users. This information 
would not be accurate when NAT is used.

Other
Cleaned up utils.pm::insertloadlog.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/State.pm
    vcl/trunk/managementnode/lib/VCL/inuse.pm
    vcl/trunk/managementnode/lib/VCL/reserved.pm
    vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/State.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/State.pm?rev=1646516&r1=1646515&r2=1646516&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/State.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/State.pm Thu Dec 18 19:26:20 2014
@@ -53,6 +53,7 @@ use strict;
 use warnings;
 use diagnostics;
 use English '-no_match_vars';
+use POSIX qw(floor);
 
 use VCL::utils;
 use VCL::DataStructure;
@@ -225,13 +226,114 @@ sub initialize {
                notify($ERRORS{'DEBUG'}, 0, "child reservation, not updating 
request state to 'pending'");
        }
        
-       notify($ERRORS{'DEBUG'}, 0, "computerloadlog states after state object 
is initialized:\n" . format_data(get_request_loadstate_names($request_id)));
+       #notify($ERRORS{'DEBUG'}, 0, "computerloadlog states after state object 
is initialized:\n" . format_data(get_request_loadstate_names($request_id)));
        
        return 1;
 } ## end sub initialize
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 user_connected
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Checks if the user is connected to the computer. If the user
+               isn't connected and this is a cluster request, checks if a
+               computerloadlog 'connected' entry exists for any of the other
+               reservations in cluster.
+
+=cut
+
+sub user_connected {
+       my $self = shift;
+       if (ref($self) !~ /VCL::/) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called 
as a class method of a VCL object");
+               return;
+       }
+       
+       my $request_id                   = $self->data->get_request_id();
+       my @reservation_ids              = $self->data->get_reservation_ids();
+       my $reservation_id               = $self->data->get_reservation_id();
+       my $reservation_lastcheck        = 
$self->data->get_reservation_lastcheck_time();
+       my $reservation_count            = 
$self->data->get_request_reservation_count();
+       my $computer_id                  = $self->data->get_computer_id();
+       my $computer_short_name          = 
$self->data->get_computer_short_name();
+       my $server_request_id            = $self->data->get_server_request_id();
+       my $request_duration_epoch_secs  = 
$self->data->get_request_duration_epoch();
+       my $request_duration_hrs         = floor($request_duration_epoch_secs / 
60 / 60);
+       my $ignore_connections_gte_min   = 
$self->os->get_timings('ignore_connections_gte');
+       my $ignore_connections_gte       = floor($ignore_connections_gte_min / 
60);
+       
+       # Check if user deleted the request
+       $self->state_exit() if is_request_deleted($request_id);
+       
+       # Check if this is an imaging request, causes process to exit if state 
or laststate = image
+       $self->check_imaging_request();
+       
+       # Check if this is a server request, causes process to exit if server 
request
+       if ($server_request_id) {
+               notify($ERRORS{'DEBUG'}, 0, "server reservation detected, set 
as user is connected");
+               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
+               return 1;
+       }
+       
+       # If duration is >= 24 hrs set as connected and return
+       if ($request_duration_hrs >= $ignore_connections_gte) {
+               notify($ERRORS{'OK'}, 0, "reservation duration is 
$request_duration_hrs hrs is >= to ignore_connections setting 
$ignore_connections_gte hrs, skipping inuse checks");
+               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
+               return 1;
+       }       
+
+       # Check if the user has connected to the reservation being processed
+       if ($self->os->is_user_connected()) {
+               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
+               
+               # If this is a cluster request, update the lastcheck value for 
all reservations
+               # This signals the other reservation inuse processes that a 
connection was detected on another computer
+               if ($reservation_count > 1) {
+                       update_reservation_lastcheck(@reservation_ids);
+               }
+               return 1;
+       }
+       
+       if ($reservation_count > 1) {
+               my $current_reservation_lastcheck = 
get_current_reservation_lastcheck($reservation_id);
+               if ($current_reservation_lastcheck ne $reservation_lastcheck) {
+                       notify($ERRORS{'DEBUG'}, 0, "user connected to another 
computer in the cluster, reservation.lastcheck updated since this process 
began: $reservation_lastcheck --> $current_reservation_lastcheck");
+                       return 1;
+               }
+               else {
+                       notify($ERRORS{'DEBUG'}, 0, "no connection to another 
computer in the cluster detected, reservation.lastcheck has not been updated 
since this process began: $reservation_lastcheck");
+               }
+       }
+       
+       return 0;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 check_imaging_request
+
+ Parameters  : none
+ Returns     : boolean
+ Description : The inuse process exits if the request state or laststate are 
set
+               to image, or if the forimaging flag has been set.
+
+=cut
+
+sub check_imaging_request {
+       my $self = shift;
+       my $request_id = $self->data->get_request_id();
+       
+       my $imaging_result = is_request_imaging($request_id);
+       if ($imaging_result eq 'image') {
+               notify($ERRORS{'OK'}, 0, "image creation process has begun, 
exiting");
+               $self->state_exit();
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 reservation_failed
 
  Parameters  : $message
@@ -704,7 +806,7 @@ sub state_exit {
                        # Do this to ensure that reservations are not processed 
again quickly after this process exits
                        # For cluster requests, the parent may have had to wait 
a while for child processes to exit
                        # Resetting reservation.lastcheck causes reservations 
to wait the full interval between inuse checks
-                       if ($request_state_name_new =~ /(inuse)/) {
+                       if ($request_state_name_new =~ /(reserved|inuse)/) {
                                update_reservation_lastcheck(@reservation_ids);
                        }
                        
@@ -806,7 +908,7 @@ sub DESTROY {
                        my @reservation_ids = 
$self->data->get_reservation_ids();
                        if (@reservation_ids && $request_id) {
                                $self->state_exit();
-                               notify($ERRORS{'DEBUG'}, 0, "computerloadlog 
states remaining after process exits:\n" . 
format_data(get_request_loadstate_names($request_id)));
+                               #notify($ERRORS{'DEBUG'}, 0, "computerloadlog 
states remaining after process exits:\n" . 
format_data(get_request_loadstate_names($request_id)));
                        }
                        elsif (!$SETUP_MODE) {
                                notify($ERRORS{'WARNING'}, 0, "failed to 
retrieve the reservation ID, computerloadlog 'begin' rows not removed");

Modified: vcl/trunk/managementnode/lib/VCL/inuse.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/inuse.pm?rev=1646516&r1=1646515&r2=1646516&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/inuse.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/inuse.pm Thu Dec 18 19:26:20 2014
@@ -103,10 +103,8 @@ sub process {
        
        my $request_id              = $self->data->get_request_id();
        my $request_state_name      = $self->data->get_request_state_name();
-       my $request_laststate_name  = $self->data->get_request_laststate_name();
        my $request_start           = $self->data->get_request_start_time();
        my $request_end             = $self->data->get_request_end_time();
-       my $request_data            = $self->data->get_request_data();
        my $request_forimaging      = $self->data->get_request_forimaging();
        my $request_checkuser       = $self->data->get_request_checkuser();
        my $reservation_id          = $self->data->get_reservation_id();
@@ -117,24 +115,7 @@ sub process {
        my $computer_id             = $self->data->get_computer_id();
        my $computer_short_name     = $self->data->get_computer_short_name();
        
-       
-       my $connect_timeout_seconds;
-       if ($request_laststate_name eq 'reserved') {
-               $connect_timeout_seconds = 
$self->os->get_timings('initialconnecttimeout');
-               notify($ERRORS{'DEBUG'}, 0, "checking for initial user 
connection, using 'initialconnecttimeout' variable: $connect_timeout_seconds 
seconds");
-       }
-       else {
-               $connect_timeout_seconds = 
$self->os->get_timings('reconnecttimeout');
-               notify($ERRORS{'DEBUG'}, 0, "checking for subsequent 
connection, using 'reconnecttimeout' variable: $connect_timeout_seconds 
seconds");
-       }
-
-       # Make sure connect timeout is long enough
-       # It has to be a bit longer than the ~5 minute period between inuse 
checks due to cluster reservations
-       # If too short, a user may be connected to one computer in a cluster 
and another inuse process times out before the connected computer is checked
-       my $connect_timeout_minutes = ceil($connect_timeout_seconds / 60);
-       
-       # Connect timeout must be in whole minutes
-       $connect_timeout_seconds = ($connect_timeout_minutes * 60);
+       my $connect_timeout_seconds = 
$self->os->get_timings('reconnecttimeout');
        
        # Check if reboot operation was requested
        if ($request_state_name =~ /reboot/) {
@@ -158,6 +139,14 @@ sub process {
                $self->state_exit('inuse', 'inuse');
        }
        
+       # Make sure connect timeout is long enough
+       # It has to be a bit longer than the ~5 minute period between inuse 
checks due to cluster reservations
+       # If too short, a user may be connected to one computer in a cluster 
and another inuse process times out before the connected computer is checked
+       my $connect_timeout_minutes = ceil($connect_timeout_seconds / 60);
+       
+       # Connect timeout must be in whole minutes
+       $connect_timeout_seconds = ($connect_timeout_minutes * 60);
+       
        my $now_epoch_seconds = time;
        
        my $request_start_epoch_seconds = 
convert_to_epoch_seconds($request_start);
@@ -219,7 +208,7 @@ sub process {
                        $self->state_exit() if is_request_deleted($request_id);
                        
                        # Check if this is an imaging request, causes process 
to exit if state or laststate = image
-                       $self->_check_imaging_request();
+                       $self->check_imaging_request();
                        
                        # Get the current request end time from the database
                        my $current_request_end = get_request_end($request_id);
@@ -272,6 +261,19 @@ sub process {
                notify($ERRORS{'DEBUG'}, 0, "skipping end time notice interval 
check, request duration: $request_duration_hours hours, parent reservation: 
$is_parent_reservation");
        }
        
+       # Check if the computer is responding to SSH
+       # Skip connection checks if the computer is not responding to SSH
+       # This prevents a reservatino from timing out if the user is actually 
connected but SSH from the management node isn't working
+       if (!$self->os->is_ssh_responding()) {
+               notify($ERRORS{'OK'}, 0, "$computer_short_name is not 
responding to SSH, skipping user connection check");
+               $self->state_exit('inuse', 'inuse');
+       }
+       
+       # Update the firewall if necessary - this is what allows a user to 
click Connect from different locations
+       if ($self->os->can('firewall_compare_update')) {
+               $self->os->firewall_compare_update();
+       }
+       
        # Compare remaining minutes to connect timeout
        # Connect timeout may be longer than 15 minutes
        # Make sure connect timeout doesn't run into the end time notice
@@ -286,35 +288,16 @@ sub process {
                $self->state_exit('inuse', 'inuse');
        }
        
-       # Check if the computer is responding to SSH
-       # Skip connection checks if the computer is not responding to SSH
-       # This prevents a reservatino from timing out if the user is actually 
connected but SSH from the management node isn't working
-       if (!$self->os->is_ssh_responding()) {
-               notify($ERRORS{'OK'}, 0, "$computer_short_name is not 
responding to SSH, skipping user connection check");
-               $self->state_exit('inuse', 'inuse');
-       }
-       
-       # Update the firewall if necessary - this is what allows a user to 
click Connect from different locations
-       # Not necessary first time inuse state is processed after reserved
-       if ($request_laststate_name ne 'reserved' && 
$self->os->can('firewall_compare_update')) {
-               $self->os->firewall_compare_update();
-       }
-       
        # TODO: fix user connection checking for cluster requests
-       if ($reservation_count > 1 && $request_laststate_name ne 'reserved') {
+       if ($reservation_count > 1) {
                notify($ERRORS{'OK'}, 0, "skipping user connection check for 
cluster request");
                $self->state_exit('inuse', 'inuse');
        }
        
-       # Insert connecttimeout immediately before beginning to check for user 
connection
+       # Insert reconnecttimeout immediately before beginning to check for 
user connection
        # Web uses timestamp of this to determine when next to refresh the page
        # Important because page should refresh as soon as possible to 
reservation timing out
-       if ($request_laststate_name eq 'reserved') {
-               insertloadlog($reservation_id, $computer_id, "connecttimeout", 
"begin initial connection timeout ($connect_timeout_seconds seconds)");
-       }
-       else {
-               insertloadlog($reservation_id, $computer_id, "connecttimeout", 
"begin reconnection timeout ($connect_timeout_seconds seconds)");
-       }
+       insertloadlog($reservation_id, $computer_id, "reconnecttimeout", "begin 
reconnection timeout ($connect_timeout_seconds seconds)");
        
        # Check to see if user is connected. user_connected will true(1) for 
servers and requests > 24 hours
        my $user_connected = 
$self->code_loop_timeout(sub{$self->user_connected()}, [], "waiting for user to 
connect to $computer_short_name", $connect_timeout_seconds, 15);
@@ -329,38 +312,24 @@ sub process {
                elsif ($server_request_id) {
                        notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, server reservation");
                }
-               elsif ($request_forimaging && $request_laststate_name ne 
'reserved') {
+               elsif ($request_forimaging) {
                        notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, imaging reservation");
                }
-               elsif ($reservation_count > 1 && $request_laststate_name ne 
'reserved') {
+               elsif ($reservation_count > 1) {
                        notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, cluster reservation");
                }
                elsif ($request_duration_hours > 24) {
                        notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, request duration: $request_duration_hours hours");
                }
+               elsif (is_request_deleted($request_id)) {
+                       $self->state_exit();
+               }
                else {
-                       $self->state_exit() if is_request_deleted($request_id);
-                       
                        # Update reservation lastcheck, otherwise request will 
be processed immediately again
                        update_reservation_lastcheck($reservation_id);
                        
-                       if ($request_laststate_name eq 'reserved') {
-                               $self->_notify_user_no_login();
-                               $self->state_exit('timeout', 'timeout', 
'nologin');
-                       }
-                       else {
-                               $self->_notify_user_timeout();
-                               $self->state_exit('timeout', 'timeout', 
'timeout');
-                       }
-               }
-       }
-       
-       # If this is the first time the inuse state is being processed, tighten 
up the firewall
-       if ($request_laststate_name eq 'reserved') {
-               # Process the connect methods again, lock the firewall down to 
the address the user connected from
-               my $remote_ip = $self->data->get_reservation_remote_ip();
-               if (!$self->os->process_connect_methods($remote_ip, 1)) {
-                       notify($ERRORS{'CRITICAL'}, 0, "failed to process 
connect methods after user connected to computer");
+                       $self->_notify_user_timeout();
+                       $self->state_exit('timeout', 'inuse', 'timeout');
                }
        }
        
@@ -369,85 +338,6 @@ sub process {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 user_connected
-
- Parameters  : none
- Returns     : boolean
- Description : Checks if the user is connected to the computer. If the user
-               isn't connected and this is a cluster request, checks if a
-               computerloadlog 'connected' entry exists for any of the other
-               reservations in cluster.
-
-=cut
-
-sub user_connected {
-       my $self = shift;
-       if (ref($self) !~ /VCL::/) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called 
as a class method of a VCL object");
-               return;
-       }
-       
-       my $request_id                   = $self->data->get_request_id();
-       my @reservation_ids              = $self->data->get_reservation_ids();
-       my $reservation_id               = $self->data->get_reservation_id();
-       my $reservation_lastcheck        = 
$self->data->get_reservation_lastcheck_time();
-       my $reservation_count            = 
$self->data->get_request_reservation_count();
-       my $computer_id                  = $self->data->get_computer_id();
-       my $computer_short_name          = 
$self->data->get_computer_short_name();
-       my $server_request_id            = $self->data->get_server_request_id();
-       my $request_duration_epoch_secs  = 
$self->data->get_request_duration_epoch();
-       my $request_duration_hrs         = floor($request_duration_epoch_secs / 
60 / 60);
-       my $ignore_connections_gte_min   = 
$self->os->get_timings('ignore_connections_gte');
-       my $ignore_connections_gte       = floor($ignore_connections_gte_min / 
60);
-       
-       # Check if user deleted the request
-       $self->state_exit() if is_request_deleted($request_id);
-       
-       # Check if this is an imaging request, causes process to exit if state 
or laststate = image
-       $self->_check_imaging_request();
-       
-       # Check if this is a server request, causes process to exit if server 
request
-       if ($server_request_id) {
-               notify($ERRORS{'DEBUG'}, 0, "server reservation detected, set 
as user is connected");
-               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
-               return 1;
-       }
-       
-       # If duration is >= 24 hrs set as connected and return
-       if ($request_duration_hrs >= $ignore_connections_gte) {
-               notify($ERRORS{'OK'}, 0, "reservation duration is 
$request_duration_hrs hrs is >= to ignore_connections setting 
$ignore_connections_gte hrs, skipping inuse checks");
-               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
-               return 1;
-       }       
-
-       # Check if the user has connected to the reservation being processed
-       if ($self->os->is_user_connected()) {
-               insertloadlog($reservation_id, $computer_id, "connected", "user 
connected to $computer_short_name");
-               
-               # If this is a cluster request, update the lastcheck value for 
all reservations
-               # This signals the other reservation inuse processes that a 
connection was detected on another computer
-               if ($reservation_count > 1) {
-                       update_reservation_lastcheck(@reservation_ids);
-               }
-               return 1;
-       }
-       
-       if ($reservation_count > 1) {
-               my $current_reservation_lastcheck = 
get_current_reservation_lastcheck($reservation_id);
-               if ($current_reservation_lastcheck ne $reservation_lastcheck) {
-                       notify($ERRORS{'DEBUG'}, 0, "user connected to another 
computer in the cluster, reservation lastcheck updated since this process 
began: $reservation_lastcheck --> $current_reservation_lastcheck");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "no connection to another 
computer in the cluster detected, reservation lastcheck has not been updated 
since this process began: $reservation_lastcheck");
-               }
-       }
-       
-       return 0;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 _notify_user_endtime
 
  Parameters  : $request_data_hash_reference, $notice_interval
@@ -477,7 +367,6 @@ sub _notify_user_endtime {
        
        my $computer_short_name             = 
$self->data->get_computer_short_name();
        my $computer_type                   = $self->data->get_computer_type();
-       my $computer_public_ip_address      = 
$self->data->get_computer_public_ip_address();
        my $image_os_name                   = $self->data->get_image_os_name();
        my $image_prettyname                = 
$self->data->get_image_prettyname();
        my $image_os_type                   = $self->data->get_image_os_type();
@@ -488,7 +377,7 @@ sub _notify_user_endtime {
        my $user_emailnotices               = 
$self->data->get_user_emailnotices();
        my $user_imtype_name                = 
$self->data->get_user_imtype_name();
        my $user_im_id                      = $self->data->get_user_im_id();
-       my $request_forimaging              = $self->_check_imaging_request();  
+       my $request_forimaging              = $self->check_imaging_request();   
        my $request_id                      = $self->data->get_request_id();
        
        my $message;
@@ -585,7 +474,6 @@ sub _notify_user_disconnect {
        
        my $computer_short_name             = 
$self->data->get_computer_short_name();
        my $computer_type                   = $self->data->get_computer_type();
-       my $computer_public_ip_address      = 
$self->data->get_computer_public_ip_address();
        my $image_os_name                   = $self->data->get_image_os_name();
        my $image_prettyname                = 
$self->data->get_image_prettyname();
        my $image_os_type                   = $self->data->get_image_os_type();
@@ -597,7 +485,7 @@ sub _notify_user_disconnect {
        my $user_imtype_name                = 
$self->data->get_user_imtype_name();
        my $user_im_id                      = $self->data->get_user_im_id();
        my $is_parent_reservation           = 
$self->data->is_parent_reservation();
-       my $request_forimaging              = $self->_check_imaging_request();
+       my $request_forimaging              = $self->check_imaging_request();
        
        my $disconnect_string;
        if ($disconnect_time == 0) {
@@ -711,7 +599,6 @@ sub _notify_user_timeout {
        
        my $computer_short_name             = 
$self->data->get_computer_short_name();
        my $computer_type                   = $self->data->get_computer_type();
-       my $computer_public_ip_address      = 
$self->data->get_computer_public_ip_address();
        my $image_os_name                   = $self->data->get_image_os_name();
        my $image_prettyname                = 
$self->data->get_image_prettyname();
        my $image_os_type                   = $self->data->get_image_os_type();
@@ -726,7 +613,7 @@ sub _notify_user_timeout {
        
        my $message = <<"EOF";
 
-Your reservation has timed out due to inactivity for image $image_prettyname 
at address $computer_public_ip_address.
+Your reservation has timed out due to inactivity for image $image_prettyname.
 
 To make another reservation, please revisit:
 $user_affiliation_sitewwwaddress
@@ -786,7 +673,6 @@ sub _notify_user_request_ended {
        my $computer_id                     = $self->data->get_computer_id();
        my $computer_short_name             = 
$self->data->get_computer_short_name();
        my $computer_type                   = $self->data->get_computer_type();
-       my $computer_public_ip_address      = 
$self->data->get_computer_public_ip_address();
        my $image_os_name                   = $self->data->get_image_os_name();
        my $image_prettyname                = 
$self->data->get_image_prettyname();
        my $image_os_type                   = $self->data->get_image_os_type();
@@ -891,12 +777,11 @@ sub _notify_user_no_login {
        my $affiliation_sitewwwaddress = 
$self->data->get_user_affiliation_sitewwwaddress();
        my $affiliation_helpaddress    = 
$self->data->get_user_affiliation_helpaddress();
        my $image_prettyname           = $self->data->get_image_prettyname();
-       my $computer_public_ip_address = 
$self->data->get_computer_public_ip_address();
        my $is_parent_reservation      = $self->data->is_parent_reservation();
 
        my $message = <<"EOF";
 
-Your reservation has timed out for image $image_prettyname at address 
$computer_public_ip_address because no initial connection was made.
+Your reservation has timed out for image $image_prettyname because no initial 
connection was made.
 
 To make another reservation, please revisit $affiliation_sitewwwaddress.
 
@@ -932,28 +817,6 @@ EOF
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _check_imaging_request
-
- Parameters  : none
- Returns     : boolean
- Description : The inuse process exits if the request state or laststate are 
set
-               to image, or if the forimaging flag has been set.
-
-=cut
-
-sub _check_imaging_request {
-       my $self = shift;
-       my $request_id = $self->data->get_request_id();
-       
-       my $imaging_result = is_request_imaging($request_id);
-       if ($imaging_result eq 'image') {
-               notify($ERRORS{'OK'}, 0, "image creation process has begun, 
exiting");
-               $self->state_exit();
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 _start_imaging_request
 
  Parameters  : none

Modified: vcl/trunk/managementnode/lib/VCL/reserved.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1646516&r1=1646515&r2=1646516&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reserved.pm Thu Dec 18 19:26:20 2014
@@ -71,6 +71,7 @@ use warnings;
 use diagnostics;
 
 use VCL::utils;
+use POSIX qw(strftime);
 
 ##############################################################################
 
@@ -92,16 +93,20 @@ use VCL::utils;
 sub process {
        my $self = shift;
        
-       my $request_id                  = $self->data->get_request_id();
-       my $request_data                = $self->data->get_request_data();
-       my $request_logid               = $self->data->get_request_log_id();
-       my $reservation_id              = $self->data->get_reservation_id();
-       my $reservation_count           = $self->data->get_reservation_count();
-       my $computer_id                 = $self->data->get_computer_id();
-       my $computer_short_name         = 
$self->data->get_computer_short_name();
-       my $is_parent_reservation       = $self->data->is_parent_reservation();
-       my $server_request_id           = $self->data->get_server_request_id();
-       my $acknowledge_timeout_seconds = 
$self->os->get_timings('acknowledgetimeout');
+       my $request_id                      = $self->data->get_request_id();
+       my $request_data                    = $self->data->get_request_data();
+       my $request_logid                   = $self->data->get_request_log_id();
+       my $request_checkuser               = 
$self->data->get_request_checkuser();
+       my $reservation_id                  = $self->data->get_reservation_id();
+       my $reservation_count               = 
$self->data->get_reservation_count();
+       my $computer_id                     = $self->data->get_computer_id();
+       my $computer_short_name             = 
$self->data->get_computer_short_name();
+       my $is_parent_reservation           = 
$self->data->is_parent_reservation();
+       my $server_request_id               = 
$self->data->get_server_request_id();
+       my $imagemeta_checkuser             = 
$self->data->get_imagemeta_checkuser();
+       
+       my $acknowledge_timeout_seconds     = 
$self->os->get_timings('acknowledgetimeout');
+       my $initial_connect_timeout_seconds = 
$self->os->get_timings('initialconnecttimeout');
        
        # Update the log loaded time to now for this request
        update_log_loaded_time($request_logid);
@@ -118,15 +123,22 @@ sub process {
        
        # Wait for the user to acknowledge the request by clicking Connect 
button or from API
        my $user_acknowledged = 
$self->code_loop_timeout(sub{$self->user_acknowledged()}, [], 'waiting for user 
acknowledgement', $acknowledge_timeout_seconds, 1, 10);
+       if (!$user_acknowledged) {
+               $self->_notify_user_timeout($request_data);
+               $self->state_exit('timeout', 'reserved', 'noack');
+       }
        
        # Add noinitialconnection and then delete acknowledgetimeout
        insertloadlog($reservation_id, $computer_id, "noinitialconnection", 
"user clicked Connect");
        delete_computerloadlog_reservation($reservation_id, 
'acknowledgetimeout');
        
-       if (!$user_acknowledged) {
-               $self->_notify_user_timeout($request_data);
-               switch_state($request_data, 'timeout', 'timeout', 'noack', 1);
-       }
+       # Capture the exact time user acknowledgement was detected
+       my $connection_check_start_epoch_seconds = time;
+       
+       # Insert initialconnecttimeout immediately after user acknowledged
+       # Web uses timestamp of this to determine when next to refresh the page
+       # The timestamp of this computerloadlog entry will be used to determine 
when to timeout the connection checking during the inuse state
+       insertloadlog($reservation_id, $computer_id, "initialconnecttimeout", 
"begin initial connection timeout ($initial_connect_timeout_seconds seconds)");
        
        # Call OS module's grant_access() subroutine which adds user accounts 
to computer
        if ($self->os->can("grant_access") && !$self->os->grant_access()) {
@@ -144,10 +156,65 @@ sub process {
                $self->reservation_failed("OS module post_reserve failed");
        }
 
-       # Add a 'reserved' computerloadlog entry
+       # Add a 'postreserve' computerloadlog entry
        # Do this last - important for cluster reservation timing
        # Parent's reserved process will loop until this exists for all child 
reservations
-       insertloadlog($reservation_id, $computer_id, "postreserve", 
"$computer_short_name post reserve successfully");
+       insertloadlog($reservation_id, $computer_id, "postreserve", 
"$computer_short_name post reserve successful");
+       
+       # Get the current time
+       my $now_epoch_seconds = time;
+       
+       # Calculate the exact time when connection checking should end
+       my $connection_check_end_epoch_seconds = 
($connection_check_start_epoch_seconds + $initial_connect_timeout_seconds);
+       my $connect_timeout_remaining_seconds = 
($connection_check_end_epoch_seconds - $now_epoch_seconds);
+       
+       my $now_string                       = strftime('%H:%M:%S', 
localtime($now_epoch_seconds));
+       my $connection_check_start_string    = strftime('%H:%M:%S', 
localtime($connection_check_start_epoch_seconds));
+       my $connection_check_end_string      = strftime('%H:%M:%S', 
localtime($connection_check_end_epoch_seconds));
+       my $connect_timeout_string           = strftime('%H:%M:%S', 
gmtime($initial_connect_timeout_seconds));
+       my $connect_timeout_remaining_string = strftime('%H:%M:%S', 
gmtime($connect_timeout_remaining_seconds));
+       
+       notify($ERRORS{'DEBUG'}, 0, "beginning to check for initial user 
connection:\n" .
+               "connection check start    :   
$connection_check_start_string\n" .
+               "connect timeout total     : + $connect_timeout_string\n" .
+               "--------------------------------------\n" .
+               "connection check end      : = $connection_check_end_string\n" .
+               "current time              : - $now_string\n" .
+               "--------------------------------------\n" .
+               "connect timeout remaining : = 
$connect_timeout_remaining_string ($connect_timeout_remaining_seconds 
seconds)\n"
+       );
+       
+       # Check to see if user is connected. user_connected will true(1) for 
servers and requests > 24 hours
+       my $user_connected = 
$self->code_loop_timeout(sub{$self->user_connected()}, [], "waiting for initial 
user connection to $computer_short_name", $connect_timeout_remaining_seconds, 
15);
+       
+       # Delete the connecttimeout immediately after acknowledgement loop ends
+       delete_computerloadlog_reservation($reservation_id, 'connecttimeout');
+       
+       if (!$user_connected) {
+               if (!$imagemeta_checkuser || !$request_checkuser) {
+                       notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, imagemeta checkuser: $imagemeta_checkuser, 
request checkuser: $request_checkuser");
+               }
+               elsif ($server_request_id) {
+                       notify($ERRORS{'OK'}, 0, "never detected user 
connection, skipping timeout, server reservation");
+               }
+               elsif (is_request_deleted($request_id)) {
+                       $self->state_exit();
+               }
+               else {
+                       $self->_notify_user_no_login();
+                       $self->state_exit('timeout', 'reserved', 'nologin');
+               }
+       }
+       
+       # Update reservation lastcheck, otherwise inuse request will be 
processed immediately again
+       update_reservation_lastcheck($reservation_id);
+       
+       # Tighten up the firewall
+       # Process the connect methods again, lock the firewall down to the 
address the user connected from
+       my $remote_ip = $self->data->get_reservation_remote_ip();
+       if (!$self->os->process_connect_methods($remote_ip, 1)) {
+               notify($ERRORS{'CRITICAL'}, 0, "failed to process connect 
methods after user connected to computer");
+       }
        
        # For cluster reservations, the parent must wait until all child 
reserved processes have exited
        # Otherwise, the state will change to inuse while the child processes 
are still finishing up the reserved state
@@ -163,7 +230,7 @@ sub process {
        }
        
        # Change the request and computer state to inuse then exit
-       switch_state($request_data, 'inuse', 'inuse', '', 1);
+       $self->state_exit('inuse');
 } ## end sub process
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -291,12 +358,11 @@ sub _notify_user_timeout {
        my $affiliation_sitewwwaddress = 
$self->data->get_user_affiliation_sitewwwaddress();
        my $affiliation_helpaddress    = 
$self->data->get_user_affiliation_helpaddress();
        my $image_prettyname           = $self->data->get_image_prettyname();
-       my $computer_public_ip_address = 
$self->data->get_computer_public_ip_address();
        my $is_parent_reservation      = $self->data->is_parent_reservation();
 
        my $message = <<"EOF";
 
-Your reservation has timed out for image $image_prettyname at address 
$computer_public_ip_address because no initial connection was made.
+Your reservation has timed out for image $image_prettyname because no initial 
connection was made.
 
 To make another reservation, please revisit $affiliation_sitewwwaddress.
 

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1646516&r1=1646515&r2=1646516&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Thu Dec 18 19:26:20 2014
@@ -174,6 +174,8 @@ our @EXPORT = qw(
        get_request_current_state_name
        get_request_end
        get_request_info
+       get_reservation_computerloadlog_entries
+       get_reservation_computerloadlog_time
        get_request_loadstate_names
        get_reservation_accounts
        get_resource_groups
@@ -1127,9 +1129,6 @@ sub check_time {
                        notify($ERRORS{'DEBUG'}, 0, "reservation will end in 10 
minutes or less ($end_diff_minutes)");
                        return "end";
                }
-               elsif ($request_laststate_name =~ /reserved/) {
-                       return "poll";
-               }
                else {
                        # End time is more than 10 minutes in the future
                        if($serverrequest) {    
@@ -1148,20 +1147,19 @@ sub check_time {
                                }
                                else {
                                        return 0;
-                                       }
+                               }
                        }
                        else {
-                       #notify($ERRORS{'DEBUG'}, 0, "reservation will end in 
more than 10 minutes ($end_diff_minutes)");
+                               #notify($ERRORS{'DEBUG'}, 0, "reservation will 
end in more than 10 minutes ($end_diff_minutes)");
                                my $general_inuse_check_time = 
($ENV{management_node_info}->{GENERAL_INUSE_CHECK} * -1);
-
                                if ($lastcheck_diff_minutes <= 
$general_inuse_check_time) {
-                               #notify($ERRORS{'DEBUG'}, 0, "reservation was 
last checked more than 5 minutes ago ($lastcheck_diff_minutes)");
-                               return "poll";
-                       }
-                       else {
-                               #notify($ERRORS{'DEBUG'}, 0, "reservation has 
been checked within the past 5 minutes ($lastcheck_diff_minutes)");
-                               return 0;
-                       }
+                                       #notify($ERRORS{'DEBUG'}, 0, 
"reservation was last checked more than 5 minutes ago 
($lastcheck_diff_minutes)");
+                                       return "poll";
+                               }
+                               else {
+                                       #notify($ERRORS{'DEBUG'}, 0, 
"reservation has been checked within the past 5 minutes 
($lastcheck_diff_minutes)");
+                                       return 0;
+                               }
                        }
                } ## end else [ if ($end_diff_minutes <= 10)
        } ## end elsif ($request_state_name =~ /inuse|imageinuse/) [ if 
($request_state_name =~ /new|imageprep|reload|tomaintenance|tovmhostinuse/)
@@ -2701,105 +2699,61 @@ sub notify_via_im {
 
 =head2 insertloadlog
 
- Parameters  : $resid,   $computerid, $loadstatename, $additionalinfo
- Returns     : 0 or 1
- Description : accepts info from processes to update the loadlog table
+ Parameters  : $reservation_id, $computer_id, $loadstatename, $additional_info
+ Returns     : boolean
+ Description : Inserts an entry into the computerloadlog table.
 
 =cut
 
 sub insertloadlog {
-       my ($resid,   $computerid, $loadstatename, $additionalinfo) = @_;
-       my ($package, $filename,   $line,          $sub)            = caller(0);
-
-       # Check the parameters
-       if (!(defined($resid))) {
-               notify($ERRORS{'CRITICAL'}, 0, "unable to insert into 
computerloadlog, reservation id is not defined");
-               return 0;
-       }
-       elsif (!($resid)) {
-               notify($ERRORS{'CRITICAL'}, 0, "unable to insert into 
computerloadlog, reservation id is 0");
-               return 0;
-       }
-
-       if (!(defined($computerid))) {
-               notify($ERRORS{'CRITICAL'}, 0, "unable to insert into 
computerloadlog, computer id is not defined");
-               return 0;
-       }
-       elsif (!($computerid)) {
-               notify($ERRORS{'CRITICAL'}, 0, "unable to insert into 
computerloadlog, computer id is 0");
-               return 0;
+       my ($reservation_id, $computer_id, $loadstatename, $additional_info) = 
@_;
+       if (!defined($reservation_id)) {
+               notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not 
supplied");
+               return;
        }
-
-       if (!(defined($additionalinfo)) || !$additionalinfo) {
-               notify($ERRORS{'WARNING'}, 0, "additionalinfo is either not 
defined or 0, using 'no additional info'");
-               $additionalinfo = 'no additional info';
+       elsif (!defined($computer_id)) {
+               notify($ERRORS{'WARNING'}, 0, "computer ID argument was not 
supplied");
+               return;
        }
-
-       my $loadstateid;
-       if (!(defined($loadstatename)) || !$loadstatename) {
-               notify($ERRORS{'WARNING'}, 0, "loadstatename is either not 
defined or 0, using NULL");
-               $loadstatename = 'NULL';
-               $loadstateid   = 'NULL';
+       elsif (!defined($loadstatename)) {
+               notify($ERRORS{'WARNING'}, 0, "computerloadstate name argument 
was not supplied");
+               return;
        }
-       else {
-               # loadstatename was specified as a parameter
-               # Check if the loadstatename exists in the computerloadstate 
table
-               my $select_statement = "
-      SELECT DISTINCT
-      computerloadstate.id
-      FROM
-      computerloadstate
-      WHERE
-      computerloadstate.loadstatename = '$loadstatename'
-      ";
-
-               my @selected_rows = database_select($select_statement);
-               if ((scalar @selected_rows) == 0) {
-                       notify($ERRORS{'WARNING'}, 0, "computerloadstate table 
entry does not exist: $loadstatename, using NULL");
-                       $loadstateid   = 'NULL';
-                       $loadstatename = 'NULL';
-               }
-               else {
-                       $loadstateid = $selected_rows[0]{id};
-                       #notify($ERRORS{'DEBUG'}, 0, "computerloadstate id 
found: id=$loadstateid, name=$loadstatename");
-               }
-       } ## end else [ if (!(defined($loadstatename)) || !$loadstatename)
+       $additional_info = 'no additional info' unless 
defined($additional_info);
 
-       # Escape any single quotes in additionalinfo
-       $additionalinfo =~ s/\'/\\\'/g;
+       # Escape any special characters in additional info
+       $additional_info = quotemeta $additional_info;
 
        # Assemble the SQL statement
-       my $insert_loadlog_statement = "
-   INSERT INTO
-   computerloadlog
-   (
-      reservationid,
-      computerid,
-      loadstateid,
-      timestamp,
-      additionalinfo
-   )
-   VALUES
-   (
-      '$resid',
-      '$computerid',
-      '$loadstateid',
-      NOW(),
-      '$additionalinfo'
-   )
-   ";
+       my $insert_loadlog_statement = <<EOF;
+INSERT INTO
+computerloadlog
+(
+       reservationid,
+       computerid,
+       loadstateid,
+       timestamp,
+       additionalinfo
+)
+VALUES
+(
+       '$reservation_id',
+       '$computer_id',
+       (SELECT id FROM computerloadstate WHERE loadstatename = 
'$loadstatename'),
+       NOW(),
+       '$additional_info'
+)
+EOF
 
        # Execute the insert statement, the return value should be the id of 
the computerloadlog row that was inserted
-       my $loadlog_id = database_execute($insert_loadlog_statement);
-       if ($loadlog_id) {
-               notify($ERRORS{'OK'}, 0, "inserted computer=$computerid, 
$loadstatename, $additionalinfo");
+       if (database_execute($insert_loadlog_statement)) {
+               notify($ERRORS{'OK'}, 0, "inserted '$loadstatename' 
computerloadlog entry");
+               return 1;
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "failed to insert entry into 
computerloadlog table");
-               return 0;
+               notify($ERRORS{'WARNING'}, 0, "failed to insert 
'$loadstatename' computerloadlog entry");
+               return;
        }
-
-       return 1;
 } ## end sub insertloadlog
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -8345,6 +8299,136 @@ sub switch_vmhost_id {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_reservation_computerloadlog_entries
+
+ Parameters  : $reservation_id
+ Returns     : array
+ Description : Retrieves computerloadlog info for a single reservation. An 
array
+               of hashes is returned. The array is ordered from oldest entry to
+               newest.
+               [
+                  {
+                     "additionalinfo" => "beginning to process, state is test",
+                     "computerid" => 3582,
+                     "computerloadstate" => {
+                     "loadstatename" => "begin"
+                     },
+                        "id" => 3494,
+                        "loadstateid" => 54,
+                        "reservationid" => 3115,
+                        "timestamp" => "2014-12-17 16:09:11"
+                  },
+                  {
+                     "additionalinfo" => "begin initial connection timeout 
(xxx seconds)",
+                     "computerid" => 3582,
+                     "computerloadstate" => {
+                     "loadstatename" => "initialconnecttimeout"
+                     },
+                        "id" => 3495,
+                        "loadstateid" => 56,
+                        "reservationid" => 3115,
+                        "timestamp" => "2014-12-17 16:09:14"
+                  }
+               ]
+
+=cut
+
+sub get_reservation_computerloadlog_entries {
+       my ($reservation_id) = @_;
+       if (!$reservation_id) {
+               notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not 
passed");
+               return;
+       }
+
+       my $select_statement = <<EOF;
+SELECT
+computerloadlog.*,
+computerloadstate.loadstatename AS computerloadstate_loadstatename
+
+FROM
+computerloadlog,
+computerloadstate
+
+WHERE
+computerloadlog.reservationid = $reservation_id
+AND computerloadlog.loadstateid = computerloadstate.id
+
+ORDER BY computerloadlog.timestamp ASC
+EOF
+
+       my @rows = database_select($select_statement);
+       
+       my @computerloadlog_info;
+       for my $row (@rows) {
+               for my $column (keys %$row) {
+                       my $value = $row->{$column};
+                       if ($column =~ /^([^_]+)_([^_]+)$/) {
+                               $row->{$1}{$2} = $value;
+                               delete $row->{$column};
+                       }
+               }
+               
+               push @computerloadlog_info, $row;
+       }
+       
+       #notify($ERRORS{'DEBUG'}, 0, "retrieved computerloadlog info for 
reservation $reservation_id:\n" . format_data(@computerloadlog_info));
+       return @computerloadlog_info;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_computerloadlog_time
+
+ Parameters  : $reservation_id, $loadstatename, $newest (optional)
+ Returns     : string (datetime)
+ Description : Retrieves the timestamp of a computerloadlog entry matching the
+               $loadstatename argument for a reservation and returns the time 
in
+               epoch seconds. By default, the timestamp of the oldest matching
+               entry is returned. The newest may be returned by providing the
+               $newest argument.
+
+=cut
+
+sub get_reservation_computerloadlog_time {
+       my ($reservation_id, $loadstatename, $newest) = @_;
+       if (!defined($reservation_id)) {
+               notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not 
supplied");
+               return;
+       }
+       if (!defined($loadstatename)) {
+               notify($ERRORS{'WARNING'}, 0, "computerloadstate name argument 
was not supplied");
+               return;
+       }
+       
+       # Get all computerloadlog entries for the reservation
+       my @computerloadlog_entries = 
get_reservation_computerloadlog_entries($reservation_id);
+       if (!@computerloadlog_entries) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve timestamp of 
computerloadlog '$loadstatename' entry for reservation $reservation_id, 
computerloadlog entries could not be retrieved");
+               return;
+       }
+       
+       my $timestamp;
+       for my $computerloadlog_entry (@computerloadlog_entries) {
+               if ($computerloadlog_entry->{computerloadstate}{loadstatename} 
eq $loadstatename) {
+                       $timestamp = $computerloadlog_entry->{timestamp};
+                       last unless $newest;
+               }
+       }
+       
+       my $type = ($newest ? 'newest' : 'oldest');
+       if ($timestamp) {
+               my $timestamp_epoch = convert_to_epoch_seconds($timestamp);
+               notify($ERRORS{'DEBUG'}, 0, "retrieved $type timestamp of first 
'$loadstatename' computerloadlog entry for reservation $reservation_id: 
'$timestamp', returning $timestamp_epoch");
+               return $timestamp_epoch;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve $type 
timestamp of first '$loadstatename' computerloadlog entry for reservation 
$reservation_id");
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_request_loadstate_names
 
  Parameters  : $request_id
@@ -8474,7 +8558,7 @@ sub reservation_being_processed {
                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 $reservation_id is currently being processed");
+               notify($ERRORS{'DEBUG'}, 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 $reservation_id 
is NOT currently being processed");


Reply via email to