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 2016/11/01 14:19:59 UTC

svn commit: r1767498 - in /vcl/trunk/managementnode/lib/VCL: Module/OS.pm image.pm

Author: arkurth
Date: Tue Nov  1 14:19:58 2016
New Revision: 1767498

URL: http://svn.apache.org/viewvc?rev=1767498&view=rev
Log:
VCL-1000
Added to OS.pm:
* create_management_node_reservation_info_json_file
* delete_management_node_reservation_info_json_file
* get_management_node_reservation_info_json_file_path
* post_capture
* run_management_node_stage_scripts

Added call to run_management_node_stage_scripts in OS.pm::pre_capture. It only gets executed if a 'enable_experimental_features' variable is true in the database.

Added call to post_capture at the end of image.pm::process. It calls run_management_node_stage_scripts which also only gets executed if a 'enable_experimental_features' variable is true in the database.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/image.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=1767498&r1=1767497&r2=1767498&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Tue Nov  1 14:19:58 2016
@@ -60,6 +60,26 @@ use VCL::utils;
 
 ##############################################################################
 
+=head1 CLASS VARIABLES
+
+=cut
+
+=head2 $MN_STAGE_SCRIPTS_DIRECTORY
+
+ Data type   : String
+ Description : Location on the management node where scripts reside which are
+               executed on the management node at various stages of a
+               reservation.
+               
+               Example:
+               /usr/local/vcl/tools/mn_stage_scripts
+
+=cut
+
+our $MN_STAGE_SCRIPTS_DIRECTORY = "$TOOLS/mn_stage_scripts";
+
+##############################################################################
+
 =head1 OBJECT METHODS
 
 =cut
@@ -72,10 +92,10 @@ use VCL::utils;
  Returns     : boolean
  Description : Performs the tasks common to all OS's that must be done to the
                computer prior to capturing an image:
-               -Check if the computer is responding to SSH
-               -If not responding, check if computer is powered on
-               -Power on computer if powered off and wait for SSH to respond
-               -Create currentimage.txt file
+               * Check if the computer is responding to SSH
+               * If not responding, check if computer is powered on
+               * Power on computer if powered off and wait for SSH to respond
+               * Create currentimage.txt file
 
 =cut
 
@@ -130,7 +150,10 @@ sub pre_capture {
 		return 0;
 	}
 	
-	# Run custom pre_capture scripts residing on the management node
+	# Run custom pre_capture scripts on the management node
+	$self->run_management_node_stage_scripts('pre_capture');
+	
+	# Run custom pre_capture scripts on the computer
 	$self->run_management_node_tools_scripts('pre_capture');
 	
 	notify($ERRORS{'OK'}, 0, "completed common image capture preparation tasks");
@@ -139,6 +162,35 @@ sub pre_capture {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 post_capture
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs the tasks common to all OS's that must be done to the
+               computer after capturing an image:
+               * Runs post_capture stage scripts on the management node if any
+                 exist
+
+=cut
+
+sub post_capture {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Run custom post_capture scripts on the management node
+	my $enable_experimental_features = get_variable('enable_experimental_features', 0);
+	if ($enable_experimental_features) {
+		$self->run_management_node_stage_scripts('post_capture');
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 reserve
 
  Parameters  : none
@@ -4277,6 +4329,111 @@ sub run_management_node_tools_scripts {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 run_management_node_stage_scripts
+
+ Parameters  : $stage
+ Returns     : boolean
+ Description : Runs scripts on the management node intended for the state
+               specified by the argument. This is useful if you need to
+               configure something such as a storage unit or firewall device
+               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
+               
+               The scripts are stored on the management node under:
+               /usr/local/vcl/tools/mn_stage_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
+               
+               It will attempt to execute any files under this directory.
+               
+               Prior to executing the scripts, a JSON file is created under /tmp
+               with information regarding the reservation. The actual file path
+               will be:
+               /tmp/<reservation ID>.json
+               
+               Information about the reservation can be retrieved within the
+               script by simply using grep or using something to parse JSON such
+               as jsawk. Sample script:
+               
+               JSON_FILE="$1"
+               echo "JSON file: ${JSON_FILE}"
+               PRIVATE_IP=`cat ${JSON_FILE} | jsawk 'return this.computer.privateIPaddress'`
+               echo "computer private IP: ${PRIVATE_IP}"
+
+=cut
+
+sub run_management_node_stage_scripts {
+	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");
+		return;
+	}
+	
+	# Get the stage argument
+	my $stage = shift;
+	if (!$stage) {
+		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)/) {
+		notify($ERRORS{'WARNING'}, 0, "invalid stage argument was supplied: $stage");
+		return;
+	}
+	
+	# Override the die handler 
+	local $SIG{__DIE__} = sub{};
+	
+	my $reservation_id = $self->data->get_reservation_id();
+	my $management_node_short_name = $self->data->get_management_node_short_name();
+	
+	my $scripts_directory_path = "$MN_STAGE_SCRIPTS_DIRECTORY/$stage";
+	my @script_file_paths = $self->mn_os->find_files($scripts_directory_path, '*');
+	if (!@script_file_paths) {
+		notify($ERRORS{'DEBUG'}, 0, "no files exist in directory: $scripts_directory_path");
+		return 1;
+	}
+	
+	# Sort the files so they can be executed in a known order
+	@script_file_paths = sort_by_file_name(@script_file_paths);
+	
+	my $script_count = scalar(@script_file_paths);
+	notify($ERRORS{'DEBUG'}, 0, "found $script_count files under $scripts_directory_path:\n" . join("\n", @script_file_paths));
+	
+	# Create a JSON file on the management node containing reservation info
+	$self->create_management_node_reservation_info_json_file();
+	
+	my $mn_json_file_path = $self->get_management_node_reservation_info_json_file_path();
+	
+	# Execute the scripts
+	for my $script_file_path (@script_file_paths) {
+		my $command = "chmod +x $script_file_path && $script_file_path $mn_json_file_path";
+		my ($exit_status, $output) = $self->mn_os->execute($command);
+		if (!defined($output)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to execute script on management node: $command");
+			return;
+		}
+		else {
+			notify($ERRORS{'DEBUG'}, 0, "executed script on management node $management_node_short_name, exit status: $exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
+		}
+	}
+	
+	#$self->delete_management_node_reservation_info_json_file();
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_connect_method_remote_ip_addresses
 
  Parameters  : none
@@ -4651,6 +4808,79 @@ sub delete_reservation_info_json_file {
 	return $self->delete_file($json_file_path);
 }
 
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_management_node_reservation_info_json_file_path
+
+ Parameters  : none
+ Returns     : string
+ Description : Returns the location where the files resides on the management
+               node that contains JSON formatted information about the
+               reservation. For Linux computers, the location is:
+               /tmp/<reservation ID>.json.
+
+=cut
+
+sub get_management_node_reservation_info_json_file_path {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	my $reservation_id = $self->data->get_reservation_id();
+	return "/tmp/$reservation_id.json";
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 create_management_node_reservation_info_json_file
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Creates a text file on the the management node containing
+               reservation data in JSON format.
+
+=cut
+
+sub create_management_node_reservation_info_json_file {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Note: it would make sense to put this and the related subroutines in ManagementNode.pm
+	# However, this sub in particular needs to remain here or else the information returned by get_reservation_info_json_string will be wrong
+	# The DataStructure available in $self->mn_os gets altered. Computer info is replaced with info for the management node.
+	
+	my $json_file_path = $self->get_management_node_reservation_info_json_file_path();
+	my $json_string = $self->data->get_reservation_info_json_string() || return;
+	return $self->mn_os->create_text_file($json_file_path, $json_string);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_management_node_reservation_info_json_file
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Deletes the text file on the management node containing
+               reservation data in JSON format.
+
+=cut
+
+sub delete_management_node_reservation_info_json_file {
+	my $self = shift;
+	if (ref($self) !~ /VCL::Module::OS/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $json_file_path = $self->get_management_node_reservation_info_json_file_path();
+	return $self->mn_os->delete_file($json_file_path);
+}
+
 #///////////////////////////////////////////////////////////////////////////
 1;
 __END__

Modified: vcl/trunk/managementnode/lib/VCL/image.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/image.pm?rev=1767498&r1=1767497&r2=1767498&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/image.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/image.pm Tue Nov  1 14:19:58 2016
@@ -229,6 +229,10 @@ EOF
 		notify($ERRORS{'WARNING'}, 0, "image table could not be updated for image=$image_id");
 	}
 	
+	# Call the OS module's post_capture subroutine
+	# This call might be relocated to each provisioning module's process subroutine like the call to pre_capture
+	$self->os->post_capture();
+	
 	$self->reservation_successful($image_size);
 } ## end sub process