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