You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2017/05/03 22:14:19 UTC

svn commit: r1793726 - in /vcl/trunk/managementnode/lib/VCL: ./ Module/ Module/OS/ Module/OS/Linux/ Module/OS/Windows/

Author: arkurth
Date: Wed May  3 22:14:19 2017
New Revision: 1793726

URL: http://svn.apache.org/viewvc?rev=1793726&view=rev
Log:
VCL-1000
Renamed:
* OS.pm::run_management_node_tools_scripts --> run_stage_scripts_on_computer
* ManagementNode.pm::run_management_node_stage_scripts --> run_stage_scripts_on_management_node

Added:
* OS.pm::run_stage_scripts
run_stage_scripts which calls both run_stage_scripts_on_computer and run_stage_scripts_on_management_node to avoid making the same 2 calls in many locations. Replaced individual calls with single call to run_stage_scripts.

The following were added and only contain a call to OS.pm::run_stage_scripts with the corresponding stage argument:
* OS.pm::post_load
* OS.pm::post_reserve
* OS.pm::post_initial_connection
* OS.pm::post_reservation
* OS.pm::pre_reload

Removed calls to the run*scripts subroutines and added calls to the new subroutines in OS.pm:
* Linux.pm::post_load --> $self->SUPER::post_load
* Linux.pm::post_reserve --> $self->SUPER::post_reserve
* Linux.pm::post_reservation --> $self->SUPER::post_reservation
* ESXi.pm::post_load --> $self->SUPER::post_load (Note: this module is not supported yet)
* OSX.pm::post_load --> $self->SUPER::post_load
* Windows.pm::post_load --> $self->SUPER::post_load
* Windows.pm::post_reserve --> $self->SUPER::post_reserve
* Windows.pm::post_reservation --> $self->SUPER::post_reservation
* Windows.pm::pre_reload --> $self->SUPER::pre_reload
* Version_5.pm.pm::pre_reload --> $self->SUPER::pre_reload
* Version_6.pm.pm::pre_reload --> $self->SUPER::pre_reload

Replaced call to run_management_node_tools_scripts with OS.pm::post_initial_connection in reserved.pm::process causing both computer and management node scripts to be executed.

Changed location where scripts reside that are executed on the management node during the stages to better align with other directories under tools:
* tools/mn_stage_scripts --> tools/ManagementNode/Scripts

Moved execution of vcl_post_load.cmd from Version_5.pm and Version_6.pm to Windows.pm::post_load.


Other
Fixed bug in Windows.pm::_get_os_perl_package. It was using the wrong package for Windows 10 and 2016.

Updated utils.pm::help to include information for all command line options.

Cleaned up and added debugging information to utils.pm::check_time. Parameterized timing window for when preloads are processed to make it easier to configure it to use the variable table in the future.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ESXi.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/UnixLab.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/OSX.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm
    vcl/trunk/managementnode/lib/VCL/new.pm
    vcl/trunk/managementnode/lib/VCL/reclaim.pm
    vcl/trunk/managementnode/lib/VCL/reserved.pm
    vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed May  3 22:14:19 2017
@@ -130,14 +130,8 @@ sub pre_capture {
 		return 0;
 	}
 	
-	# Run custom pre_capture scripts on the management node
-	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
-	if ($enable_experimental_features) {
-		$self->mn_os->run_management_node_stage_scripts('pre_capture');
-	}
-	
-	# Run custom pre_capture scripts on the computer
-	$self->run_management_node_tools_scripts('pre_capture');
+	# Run custom pre_capture scripts
+	$self->run_stage_scripts('pre_capture');
 	
 	notify($ERRORS{'OK'}, 0, "completed common image capture preparation tasks");
 	return 1;
@@ -163,12 +157,32 @@ sub post_capture {
 		return;
 	}
 	
-	# Run custom post_capture scripts on the management node
-	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
-	if ($enable_experimental_features) {
-		$self->mn_os->run_management_node_stage_scripts('post_capture');
+	# Run custom post_capture scripts
+	$self->run_stage_scripts('post_capture');
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 post_load
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs common OS steps after an image is loaded.
+
+=cut
+
+sub post_load {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
 	}
 	
+	# Run custom post_load scripts
+	$self->run_stage_scripts('post_load');
+	
 	return 1;
 }
 
@@ -209,6 +223,99 @@ sub reserve {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 post_reserve
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs common OS steps after an image is loaded.
+
+=cut
+
+sub post_reserve {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+	
+	# Run custom post_reserve scripts
+	$self->run_stage_scripts('post_reserve');
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 post_initial_connection
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs common OS steps after a user makes an initial
+               connection.
+
+=cut
+
+sub post_initial_connection {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Run custom post_initial_connection scripts
+	$self->run_stage_scripts('post_initial_connection');
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 post_reservation
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs common OS steps after a user's reservation is over.
+
+=cut
+
+sub post_reservation {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+	
+	# Run custom post_reservation scripts
+	$self->run_stage_scripts('post_reservation');
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 pre_reload
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs common OS steps prior to a computer being reloaded.
+
+=cut
+
+sub pre_reload {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+	
+	# Run custom pre_reload scripts
+	$self->run_stage_scripts('pre_reload');
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 add_user_accounts
 
  Parameters  : none
@@ -4346,17 +4453,51 @@ sub get_timings {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 run_management_node_tools_scripts
+=head2 run_stage_scripts
+
+Parameters  : $stage
+ Returns     : boolean
+ Description : Runs scripts on both the management node and computer intended
+               for the reservation stage specified by the argument. Management
+               node scripts are executed first.
+
+=cut
+
+sub run_stage_scripts {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Get the stage argument
+	my $stage = shift;
+	if (!$stage) {
+		notify($ERRORS{'WARNING'}, 0, "stage argument was not supplied");
+		return;
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "attempting to execute custom scripts for '$stage' stage if any exist");
+	
+	my $computer_result = $self->run_stage_scripts_on_computer($stage);
+	my $management_node_result = $self->mn_os->run_stage_scripts_on_management_node($stage);
+	return $computer_result && $management_node_result;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 run_stage_scripts_on_computer
 
  Parameters  : $stage
  Returns     : boolean
  Description : Runs scripts on the computer intended for the state specified by
                the argument. The stage argument may be any of the following:
-               * pre_capture
                * post_load
-               * post_reserve
-               * post_initial_connection
-               * post_reservation
+					* post_reserve
+					* post_initial_connection
+					* post_reservation
+					* pre_reload
+					* pre_capture
                
                Scripts are stored in various directories under tools matching
                the OS of the image being loaded. For example, scripts residing
@@ -4390,7 +4531,7 @@ sub get_timings {
 
 =cut
 
-sub run_management_node_tools_scripts {
+sub run_stage_scripts_on_computer {
 	my $self = shift;
 	if (ref($self) !~ /VCL::Module/) {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
@@ -4403,10 +4544,25 @@ sub run_management_node_tools_scripts {
 		notify($ERRORS{'WARNING'}, 0, "stage argument was not supplied");
 		return;
 	}
-	elsif ($stage !~ /(pre_capture|post_load|post_reserve|post_initial_connection|post_reservation)/) {
+	
+	my $computer_stages = {
+		'post_capture' => 0,
+		'post_initial_connection' => 1,
+		'post_load' => 1,
+		'post_reservation' => 1,
+		'post_reserve' => 1,
+		'pre_capture' => 1,
+		'pre_reload' => 1,
+	};
+	
+	if (!defined($computer_stages->{$stage})) {
 		notify($ERRORS{'WARNING'}, 0, "invalid stage argument was supplied: $stage");
 		return;
 	}
+	elsif (!$computer_stages->{$stage}) {
+		notify($ERRORS{'DEBUG'}, 0, "'$stage' stage scripts are not supported to be run on a computer");
+		return 1;
+	}
 	
 	my $computer_node_name = $self->data->get_computer_node_name();
 	my $image_name = $self->data->get_image_name();

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed May  3 22:14:19 2017
@@ -527,9 +527,6 @@ sub post_load {
 		$self->update_public_hostname();
 	}
 	
-	# Run custom post_load scripts residing on the management node
-	$self->run_management_node_tools_scripts('post_load');
-	
 	# Run the vcl_post_load script if it exists in the image
 	my @post_load_script_paths = ('/usr/local/vcl/vcl_post_load', '/etc/init.d/vcl_post_load');	
 
@@ -549,8 +546,8 @@ sub post_load {
 		}
 	}
 	
-	return 1;
-} ## end sub post_load
+	return $self->SUPER::post_load();
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
@@ -573,17 +570,7 @@ sub post_reserve {
 	my $image_name = $self->data->get_image_name();
 	my $computer_short_name = $self->data->get_computer_short_name();
 	
-	notify($ERRORS{'OK'}, 0, "initiating Linux post_reserve: $image_name on $computer_short_name");
 	
-	# Run custom post_reserve scripts on the management node
-	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
-	if ($enable_experimental_features) {
-		$self->mn_os->run_management_node_stage_scripts('post_reserve');
-	}
-	
-	# Run custom post_reserve scripts residing on the management node
-	$self->run_management_node_tools_scripts('post_reserve');
-
 	# User supplied data
 	#check if variable is set
 	#get variable from variable table related to server reservation id ‘userdata|<reservation id>’
@@ -637,7 +624,8 @@ sub post_reserve {
 			}
 		}
 	}
-	return 1;
+	
+	return $self->SUPER::post_reserve();
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -658,9 +646,6 @@ sub post_reservation {
 		return 0;
 	}
 	
-	# Run custom post_reservation scripts residing on the management node
-	$self->run_management_node_tools_scripts('post_reservation');
-	
 	my $script_path = '/usr/local/vcl/vcl_post_reservation';
 	
 	# Check if script exists
@@ -672,13 +657,7 @@ sub post_reservation {
 		notify($ERRORS{'DEBUG'}, 0, "script does NOT exist: $script_path");
 	}
 	
-	# Run custom post_reserve scripts on the management node
-	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
-	if ($enable_experimental_features) {
-		$self->mn_os->run_management_node_stage_scripts('post_reservation');
-	}
-	
-	return 1;
+	return $self->SUPER::post_reservation();
 }
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ESXi.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ESXi.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ESXi.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ESXi.pm Wed May  3 22:14:19 2017
@@ -92,7 +92,7 @@ sub post_load {
 		return 0;
 	}
 	
-	return 1;
+	return $self->SUPER::post_load();
 }
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm Wed May  3 22:14:19 2017
@@ -69,11 +69,11 @@ use VCL::utils;
                reservation.
                
                Example:
-               /usr/local/vcl/tools/mn_stage_scripts
+               /usr/local/vcl/tools/ManagementNode/Scripts
 
 =cut
 
-our $MN_STAGE_SCRIPTS_DIRECTORY = "$TOOLS/mn_stage_scripts";
+our $MN_STAGE_SCRIPTS_DIRECTORY = "$TOOLS/ManagementNode/Scripts";
 
 ##############################################################################
 
@@ -374,7 +374,7 @@ sub delete_management_node_reservation_i
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 run_management_node_stage_scripts
+=head2 run_stage_scripts_on_management_node
 
  Parameters  : $stage
  Returns     : boolean
@@ -384,20 +384,21 @@ sub delete_management_node_reservation_i
                specifically for each reservation.
                
                The stage argument may be any of the following:
-               * pre_capture
-               * post_capture
-               * post_load
-               * post_reserve
-               * post_initial_connection
-               * post_reservation
+					* post_capture
+					* post_initial_connection
+					* post_load
+					* post_reservation
+					* post_reserve
+					* pre_capture
+					* pre_reload
                
                The scripts are stored on the management node under:
-               /usr/local/vcl/tools/mn_stage_scripts
+               /usr/local/vcl/tools/ManagementNode/Scripts
                
                No scripts exist by default. When the vcld process reaches the
                stage specified by the argument, it will check the subdirectory
                with a name that matches the stage name. For example:
-               /usr/local/vcl/tools/mn_stage_scripts/post_capture
+               /usr/local/vcl/tools/ManagementNode/Scripts/post_capture
                
                It will attempt to execute any files under this directory.
                
@@ -417,7 +418,7 @@ sub delete_management_node_reservation_i
 
 =cut
 
-sub run_management_node_stage_scripts {
+sub run_stage_scripts_on_management_node {
 	my $self = shift;
 	if (ref($self) !~ /VCL::/i) {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
@@ -430,10 +431,26 @@ sub run_management_node_stage_scripts {
 		notify($ERRORS{'WARNING'}, 0, "stage argument was not supplied");
 		return;
 	}
-	elsif ($stage !~ /(pre_capture|post_capture|post_load|post_reserve|post_initial_connection|post_reservation)/) {
+	
+	my $management_node_stages = {
+		'post_capture' => 1,
+		'post_initial_connection' => 1,
+		'post_load' => 1,
+		'post_reservation' => 1,
+		'post_reserve' => 1,
+		'pre_capture' => 1,
+		'pre_reload' => 1,
+	};
+	
+	if (!defined($management_node_stages->{$stage})) {
 		notify($ERRORS{'WARNING'}, 0, "invalid stage argument was supplied: $stage");
 		return;
 	}
+	elsif (!$management_node_stages->{$stage}) {
+		# Note: Not currently used, could someday if a particular stage is defined for computer scripts but not MN scripts
+		notify($ERRORS{'DEBUG'}, 0, "'$stage' stage scripts are not supported to be run on a managment node");
+		return 1;
+	}
 	
 	# Override the die handler 
 	local $SIG{__DIE__} = sub{};

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/UnixLab.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/UnixLab.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/UnixLab.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/UnixLab.pm Wed May  3 22:14:19 2017
@@ -350,11 +350,11 @@ sub reserve { return 1; }
 
 #//////////////////////////////////////////////////////////////////////////////
 
-=head2 run_management_node_tools_scripts
+=head2 run_stage_scripts_on_computer
 
 =cut
 
-sub run_management_node_tools_scripts { return 1; }
+sub run_stage_scripts_on_computer { return 1; }
 
 #/////////////////////////////////////////////////////////////////////////////
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/OSX.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/OSX.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/OSX.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/OSX.pm Wed May  3 22:14:19 2017
@@ -276,6 +276,9 @@ sub post_load {
 	
 	$self->activate_irapp();
 	
+	# arkurth: added for possible future use, don't have a way to test
+	# Use the following line to enable execution of stage scripts:
+	# return $self->SUPER::post_load();
 	notify($ERRORS{'OK'}, 0, "returning 1");
 	return 1;
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed May  3 22:14:19 2017
@@ -995,15 +995,34 @@ sub post_load {
 		}
 		delete $self->{reboot_required};
 	}
-	
+
+=item *
+
+ Run custom post_load scripts residing in the image
+
+=cut
+
+	my $script_path = '$SYSTEMROOT/vcl_post_load.cmd';
+	if (!$self->file_exists($script_path)) {
+		notify($ERRORS{'DEBUG'}, 0, "custom post_load script does NOT exist in image: $script_path");
+	}
+	else {
+		$self->run_script($script_path);
+	}
+
+=item *
+
+ Call OS.pm::post_load
+
+=cut
+
+	return $self->SUPER::post_load();
 
 =back
 
 =cut
 
-	notify($ERRORS{'DEBUG'}, 0, "Windows common post-load tasks complete");
-	return 1;
-} ## end sub post_load
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
@@ -1060,16 +1079,9 @@ sub post_reserve {
 		return 0;
 	}
 	
-	# Run custom post_reserve scripts residing on the management node
-	$self->run_management_node_tools_scripts('post_reserve');
-	
 	# Check if custom post_reserve script exists in the image
 	my $script_path = '$SYSTEMROOT/vcl_post_reserve.cmd';
-	if (!$self->file_exists($script_path)) {
-		notify($ERRORS{'DEBUG'}, 0, "custom post_reserve script does NOT exist in image: $script_path");
-		return 1;
-	}
-	else {
+	if ($self->file_exists($script_path)) {
 		# If post_reserve script exists, assume it does user or reservation-specific actions
 		# If the user never connects and the reservation times out, there's no way to revert these actions in order to clean the computer for another user
 		# Tag the image as tainted so it is reloaded
@@ -1078,8 +1090,11 @@ sub post_reserve {
 		# Run the post_reserve script
 		$self->run_script($script_path);
 	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "custom post_reserve script does NOT exist in image: $script_path");
+	}
 	
-	return 1;
+	return $self->SUPER::post_reserve();
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1100,9 +1115,6 @@ sub post_reservation {
 		return 0;
 	}
 	
-	# Run custom post_reservation scripts residing on the management node
-	$self->run_management_node_tools_scripts('post_reservation');
-	
 	# Check if custom post_reservation script exists in image
 	my $script_path = '$SYSTEMROOT/vcl_post_reservation.cmd';
 	if ($self->file_exists($script_path)) {
@@ -1113,7 +1125,7 @@ sub post_reservation {
 		notify($ERRORS{'DEBUG'}, 0, "custom post_reservation script does NOT exist in image: $script_path");
 	}
 	
-	return 1;
+	return $self->SUPER::post_reservation();
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1142,7 +1154,7 @@ sub pre_reload {
 		$self->ad_delete_computer($computer_name, $computer_current_domain_name);
 	}
 	
-	return 1;
+	return $self->SUPER::pre_reload();
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -12706,9 +12718,12 @@ sub _get_os_perl_package {
 	elsif ($product_name =~ /(XP|2003)/i) {
 		$perl_package = "VCL::Module::OS::Windows::Version_5::$1";
 	}
-	elsif ($product_name =~ /(Vista|2008|2012|2016|7|8|10)/ig) {
+	elsif ($product_name =~ /(Vista|2008|2012|7|8)/ig) {
 		$perl_package = "VCL::Module::OS::Windows::Version_6::$1";
 	}
+	elsif ($product_name =~ /(2016|10)/ig) {
+		$perl_package = "VCL::Module::OS::Windows::Version_10::$1";
+	}
 	else {
 		notify($ERRORS{'WARNING'}, 0, "failed to determine OS installed on computer, unsupported Windows product name: $product_name");
 		return;

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_5.pm Wed May  3 22:14:19 2017
@@ -150,43 +150,16 @@ sub post_load {
 	
 	notify($ERRORS{'DEBUG'}, 0, "beginning Windows version 5.x post-load tasks");
 
-=item * Call parent class's post_load() subroutine
+=item * Call Windows.pm::post_load()
 
 =cut
 
-	notify($ERRORS{'DEBUG'}, 0, "calling parent class post_load() subroutine");
-	if ($self->SUPER::post_load()) {
-		notify($ERRORS{'OK'}, 0, "successfully executed parent class post_load() subroutine");
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to execute parent class post_load() subroutine");
-		return;
-	}
-
-=item * Run custom post_load scripts residing on the management node
-
-=cut
-
-	$self->run_management_node_tools_scripts('post_load');
-
-=item * Run custom post_load scripts residing in the image
-
-=cut
-
-	my $script_path = '$SYSTEMROOT/vcl_post_load.cmd';
-	if (!$self->file_exists($script_path)) {
-		notify($ERRORS{'DEBUG'}, 0, "custom post_load script does NOT exist in image: $script_path");
-	}
-	else {
-		$self->run_script($script_path);
-	}
+	return $self->SUPER::post_load();
 
 =back
 
 =cut
 
-	notify($ERRORS{'DEBUG'}, 0, "Windows version 5.x post-load tasks complete");
-	return 1;
 }
 
 ##############################################################################

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows/Version_6.pm Wed May  3 22:14:19 2017
@@ -183,21 +183,15 @@ sub post_load {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module object method");
 		return;
 	}
-	
-	notify($ERRORS{'DEBUG'}, 0, "beginning Windows version 6 post-load tasks");
 
 =item * Call parent class's post_load() subroutine
 
 =cut
 
-	notify($ERRORS{'DEBUG'}, 0, "calling parent class post_load() subroutine");
-	if ($self->SUPER::post_load()) {
-		notify($ERRORS{'OK'}, 0, "successfully executed parent class post_load() subroutine");
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to execute parent class post_load() subroutine");
-		return;
-	}
+	$self->SUPER::post_load() || return;
+	
+	
+	notify($ERRORS{'DEBUG'}, 0, "beginning Windows version 6 post-load tasks");
 
 =item * Ignore default routes configured for the private interface and use default routes configured for the public interface
 
@@ -211,24 +205,6 @@ sub post_load {
 
 	$self->activate();
 
-=item * Run custom post_load scripts residing on the management node
-
-=cut
-
-	$self->run_management_node_tools_scripts('post_load');
-
-=item * Run custom post_load scripts residing in the image
-
-=cut
-
-	my $script_path = '$SYSTEMROOT/vcl_post_load.cmd';
-	if (!$self->file_exists($script_path)) {
-		notify($ERRORS{'DEBUG'}, 0, "custom post_load script does NOT exist in image: $script_path");
-	}
-	else {
-		$self->run_script($script_path);
-	}
-
 =back
 
 =cut

Modified: vcl/trunk/managementnode/lib/VCL/new.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/new.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/new.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/new.pm Wed May  3 22:14:19 2017
@@ -580,7 +580,7 @@ sub reload_image {
 		# Attempt to create a new OS object representing OS currently installed and check if that object implements a 'pre_reload' subroutine
 		if ($self->os->is_ssh_responding()) {
 			my $computer_current_os = $self->create_current_os_object($computer_id, 1);
-			if ($computer_current_os && $computer_current_os->can('pre_reload')) {
+			if ($computer_current_os) {
 				$computer_current_os->pre_reload();
 			}
 		}

Modified: vcl/trunk/managementnode/lib/VCL/reclaim.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reclaim.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reclaim.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reclaim.pm Wed May  3 22:14:19 2017
@@ -249,14 +249,7 @@ sub insert_reload_and_exit {
 	my $computer_id                = $self->data->get_computer_id();
 	my $computer_shortname         = $self->data->get_computer_short_name();
 	
-	# Run any vcl_post_reservation scripts (if exists)
-	if ($self->os->can("post_reservation")) {
-		if ($self->os->is_ssh_responding()) {
-			if ($self->os->post_reservation()) {
-				notify($ERRORS{'OK'}, 0, "post_reservation script has been executed on $computer_shortname prior to reloading");
-			}
-		}
-	}
+	$self->os->post_reservation();
 	
 	# Retrieve next image
 	my ($action, $next_image_name, $next_image_id, $next_imagerevision_id) = $self->data->get_next_image_data_structure();

Modified: vcl/trunk/managementnode/lib/VCL/reserved.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reserved.pm Wed May  3 22:14:19 2017
@@ -279,8 +279,8 @@ sub process {
 		}
 	}
 	
-	# Run custom post_initial_connection scripts residing on the management node
-	$self->os->run_management_node_tools_scripts('post_initial_connection');
+	# Perform steps after a user makes an initial connection
+	$self->os->post_initial_connection();
 	
 	# 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

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1793726&r1=1793725&r2=1793726&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Wed May  3 22:14:19 2017
@@ -549,10 +549,12 @@ Please read the README and INSTALLATION
 Documentation is available at http://cwiki.apache.org/VCL.
 
 Command line options:
+-conf=<path> | Specify vcld configuration file (default: /etc/vcl/vcld.conf)
+-log=<path>  | Specify vcld log file (default: /var/log/vcld.log)
 -setup       | Run management node setup
--conf=<path> | Specify vcld configuration file
 -verbose     | Run vcld in verbose mode
--debug       | Run vcld in non-daemon mode
+-nodaemon    | Run vcld in non-daemon mode
+-exn         | Use persistent SSH connections (experimental)
 -help        | Display this help information
 ============================================================================
 END
@@ -1107,6 +1109,9 @@ sub check_time {
 	my $lastcheck_diff_minutes = round($lastcheck_diff_seconds / 60);
 	my $start_diff_minutes     = round($start_diff_seconds / 60);
 	my $end_diff_minutes       = round($end_diff_seconds / 60);
+	
+	my $preload_window_minutes_prior_high = 35;
+	my $preload_window_minutes_prior_low = 25;
 
 	# Print the time differences
 	#notify($ERRORS{'OK'}, 0, "reservation lastcheck difference: $lastcheck_diff_minutes minutes ($lastcheck_diff_seconds seconds)");
@@ -1115,20 +1120,24 @@ sub check_time {
 	#notify($ERRORS{'OK'}, 0, "changelog timestamp difference:   $changelog_diff_seconds seconds");
 
 	# Check the state, and then figure out the return code
-	if ($request_state_name =~ /new|imageprep|reload|tovmhostinuse/) {
+	if ($request_state_name =~ /(new|imageprep|reload|tovmhostinuse|test)/) {
 		if ($start_diff_minutes > 0) {
 			# Start time is either now or in future, $start_diff_minutes is positive
-			
-			if ($start_diff_minutes > 35) {
-				#notify($ERRORS{'DEBUG'}, 0, "reservation will start in more than 35 minutes ($start_diff_minutes)");
+			my $preload_start_minutes = ($start_diff_minutes - $preload_window_minutes_prior_high);
+			if ($start_diff_minutes > $preload_window_minutes_prior_high) {
+				if (($preload_start_minutes <= 5 || $start_diff_minutes % 5 == 0) && ($start_diff_seconds % 60) >= 50) {
+					notify($ERRORS{'DEBUG'}, 0, "$request_state_name request start time is $start_diff_minutes minutes from now, preload process will begin in $preload_start_minutes minutes ($preload_window_minutes_prior_high minutes prior to request start time), returning 0");
+				}
 				return "0";
 			}
-			elsif ($start_diff_minutes >= 25 && $start_diff_minutes <= 35) {
-				notify($ERRORS{'DEBUG'}, 0, "reservation will start in 25-35 minutes ($start_diff_minutes)");
+			elsif ($start_diff_minutes >= $preload_window_minutes_prior_low && $start_diff_minutes <= $preload_window_minutes_prior_high) {
+				notify($ERRORS{'DEBUG'}, 0, "$request_state_name request start time is $start_diff_minutes minutes from now, returning 'preload'");
 				return "preload";
 			}
 			else {
-				#notify($ERRORS{'DEBUG'}, 0, "reservation will start less than 25 minutes ($start_diff_minutes)");
+				if (($start_diff_minutes <= 5 || $start_diff_minutes % 5 == 0) && ($start_diff_seconds % 60) >= 50) {
+					notify($ERRORS{'DEBUG'}, 0, "$request_state_name request will be processed in $start_diff_minutes minutes, returning 0");
+				}
 				return "0";
 			}
 		} ## end if ($start_diff_minutes > 0)
@@ -1138,28 +1147,33 @@ sub check_time {
 			#Start time is fairly old - something is off
 			#send warning to log for tracking purposes
 			if ($start_diff_minutes < -17) {
-				notify($ERRORS{'WARNING'}, 0, "reservation start time was in the past 17 minutes ($start_diff_minutes)");
+				notify($ERRORS{'WARNING'}, 0, "reservation start time was in the past 17 minutes ($start_diff_minutes), returning 'start'");
+			}
+			else {
+				notify($ERRORS{'DEBUG'}, 0, "reservation start time was $start_diff_minutes minutes ago, returning 'start'");
 			}
 			
 			return "start";
 			
 		} ## end else [ if ($start_diff_minutes > 0)
 	}
-	elsif ($request_state_name =~ /tomaintenance/) {
+	elsif ($request_state_name =~ /(tomaintenance)/) {
+		# Only display this once per hour at most, tomaintenance can be far into the future
 		if ($start_diff_minutes > 0) {
-			# Start time is either now or in future, $start_diff_minutes is positive
-			notify($ERRORS{'DEBUG'}, 0, "$request_state_name request will be processed in $start_diff_minutes minutes");
+			if ($start_diff_minutes % 60 == 0 && ($start_diff_seconds % 60) >= 50) {
+				notify($ERRORS{'DEBUG'}, 0, "$request_state_name request will be processed in $start_diff_minutes minutes, returning 0");
+			}
 			return "0";
 		}
 		else {
 			# Start time is in past, $start_diff_minutes is negative
-			notify($ERRORS{'DEBUG'}, 0, "$request_state_name request will be processed now");
+			notify($ERRORS{'DEBUG'}, 0, "$request_state_name request will be processed now, returning 'start'");
 			return "start";
 		}
 	}
-	elsif ($request_state_name =~ /inuse/) {
+	elsif ($request_state_name =~ /(inuse)/) {
 		if ($end_diff_minutes <= 10) {
-			notify($ERRORS{'DEBUG'}, 0, "reservation will end in 10 minutes or less ($end_diff_minutes)");
+			notify($ERRORS{'DEBUG'}, 0, "reservation will end in 10 minutes or less ($end_diff_minutes), returning 'end'");
 			return "end";
 		}
 		elsif ($lastcheck_epoch_seconds < $changelog_epoch_seconds && $changelog_diff_seconds < 0) {
@@ -1194,32 +1208,31 @@ sub check_time {
 					return "poll";
 				}
 				else {
-					#notify($ERRORS{'DEBUG'}, 0, "reservation has been checked within the past $general_inuse_check_time minutes ($lastcheck_diff_minutes)");
+					#notify($ERRORS{'DEBUG'}, 0, "reservation has been checked within the past $general_inuse_check_time minutes ($lastcheck_diff_minutes), returning 0");
 					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/)
-
-	elsif ($request_state_name =~ /complete|failed/) {
+	elsif ($request_state_name =~ /(complete|failed)/) {
 		# Don't need to keep requests in database if laststate was...
 		if ($request_laststate_name =~ /image|deleted|makeproduction|reload|tomaintenance|tovmhostinuse/) {
+			notify($ERRORS{'DEBUG'}, 0, "request laststate is '$request_laststate_name', returning 'remove'");
 			return "remove";
 		}
-
-		if ($end_diff_minutes < 0) {
-			notify($ERRORS{'DEBUG'}, 0, "reservation end time was in the past ($end_diff_minutes)");
+		elsif ($end_diff_minutes < 0) {
+			notify($ERRORS{'DEBUG'}, 0, "reservation end time was in the past ($end_diff_minutes), returning 'remove'");
 			return "remove";
 		}
 		else {
 			# End time is now or in the future
-			#notify($ERRORS{'DEBUG'}, 0, "reservation end time is either right now or in the future ($end_diff_minutes)");
+			notify($ERRORS{'DEBUG'}, 0, "reservation end time is either right now or in the future ($end_diff_minutes), returning 0");
 			return "0";
 		}
 	}    # Close if state is complete or failed
-
 	# Just return start for all other states
 	else {
+		notify($ERRORS{'DEBUG'}, 0, "request state is '$request_state_name', returning 'start'");
 		return "start";
 	}
 
@@ -8841,13 +8854,20 @@ sub format_array_reference {
 	my $indent_character = ' ';
 	my $indent_count = 3;
 	
-	my $data_type = ref($data);
-	if ($data_type !~ /(ARRAY|HASH)/) {
-		return "'',\n";
+	if (!defined($data)) {
+		return "<undef>,\n";
 	}
 	
-	
-	
+	my $data_type = ref($data);
+	if (!$data_type) {
+		if (length($data) > 100) {
+			$data = substr($data, 0, 100) . '<truncated>';
+		}
+		return "'" . $data . "',\n";
+	}
+	elsif ($data_type !~ /(ARRAY|HASH)/) {
+		return "<ref:$data_type>,\n";
+	}
 
 	my $hash_ref;
 	my $opening_char;
@@ -10620,6 +10640,11 @@ sub get_file_size_info_string {
 sub get_copy_speed_info_string {
 	my ($copied_bytes, $duration_seconds) = @_;
 	
+	# Avoid divide by zero errors
+	if ($duration_seconds == 0) {
+		$duration_seconds = 1;
+	}
+
 	my $minutes = ($duration_seconds / 60);
 	$minutes =~ s/\..*//g;
 	my $seconds = ($duration_seconds - ($minutes * 60));