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 2009/12/14 21:30:58 UTC

svn commit: r890470 - /incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm

Author: arkurth
Date: Mon Dec 14 20:30:34 2009
New Revision: 890470

URL: http://svn.apache.org/viewvc?rev=890470&view=rev
Log:
VCL-279
Added call_post_load_custom() sub to Linux.pm. It checks if /etc/init.d/post_load_custom exists and executes it after an image is loaded. This allows an image creator to easily add a custom script which automatically executes on image load. This functionality already exists for Windows. 

Added $NODE_CONFIGURATION_DIRECTORY class variable to Linux.pm to match Windows.pm.

Also added subroutine headers to Linux.pm where they were missing but did not populate the information.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=890470&r1=890469&r2=890470&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Mon Dec 14 20:30:34 2009
@@ -56,6 +56,38 @@
 
 ##############################################################################
 
+=head1 CLASS VARIABLES
+
+=cut
+
+=head2 $NODE_CONFIGURATION_DIRECTORY
+
+ Data type   : String
+ Description : Location on computer on which an image has been loaded where
+               configuration files reside.
+
+=cut
+
+our $NODE_CONFIGURATION_DIRECTORY = '/root/VCL';
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_node_configuration_directory
+
+ Parameters  : None.
+ Returns     : String containing filesystem path
+ Description : Retrieves the $NODE_CONFIGURATION_DIRECTORY variable value the
+               OS. This is the path on the computer's hard drive where image
+					configuration files and scripts are copied.
+
+=cut
+
+sub get_node_configuration_directory {
+	return $NODE_CONFIGURATION_DIRECTORY;
+}
+
+##############################################################################
+
 =head1 OBJECT METHODS
 
 =cut
@@ -198,7 +230,6 @@
 	my $clear_extsshd = "sed -ie \"/^AllowUsers .*/d\" /etc/ssh/external_sshd_config";
 	if (run_ssh_command($computer_node_name, $management_node_keys, $clear_extsshd, "root")) {
 		notify($ERRORS{'DEBUG'}, 0, "cleared AllowUsers directive from external_sshd_config");
-		return 1;
 	}
 	else {
 		notify($ERRORS{'CRITICAL'}, 0, "failed to clear AllowUsers from external_sshd_config");
@@ -209,11 +240,26 @@
 	if ($self->clear_private_keys()) {
 		notify($ERRORS{'OK'}, 0, "cleared known identity keys");
 	}
+	
+	# Check if post_load_custom script exists and execute it
+	if (!$self->call_post_load_custom()) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute post_load_custom script");
+	}
 
 	return 1;
 
 } ## end sub post_load
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 clear_private_keys
+
+ Parameters  :
+ Returns     :
+ Description :
+
+=cut
+
 sub clear_private_keys {
 	my $self = shift;
 		unless (ref($self) && $self->isa('VCL::Module')) {
@@ -238,6 +284,17 @@
 	}
 
 }
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_static_public_address
+
+ Parameters  :
+ Returns     :
+ Description :
+
+=cut
+
 sub set_static_public_address {
 	my $self = shift;
 	if (ref($self) !~ /linux/i) {
@@ -455,6 +512,16 @@
 	return $GATEWAY;
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 logoff_user
+
+ Parameters  :
+ Returns     :
+ Description :
+
+=cut
+
 sub logoff_user {
 	my $self = shift;
 	if (ref($self) !~ /linux/i) {
@@ -957,7 +1024,18 @@
 
 	return 1;
 
-} 
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 is_connected
+
+ Parameters  :
+ Returns     :
+ Description :
+
+=cut
+
 sub is_connected {
 	my $self = shift;
 	if (ref($self) !~ /linux/i) {
@@ -990,6 +1068,176 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 call_post_load_custom
+
+ Parameters  : none
+ Returns     : If successfully ran post_load_custom script: 1
+               If post_load_custom script does not exist: 1
+               If error occurred: false
+ Description : Checks if /etc/init.d/post_load_custom script exists on the
+               Linux node and attempts to run it. This script can be created by
+					the image creator and will run when the image is loaded.
+
+=cut
+
+sub call_post_load_custom {
+	my $self = shift;
+	if (ref($self) !~ /linux/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Check if post_load_custom exists
+	my $post_load_custom_path = '/etc/init.d/post_load_custom';
+	if ($self->filesystem_entry_exists($post_load_custom_path)) {
+		notify($ERRORS{'DEBUG'}, 0, "post_load_custom script exists: $post_load_custom_path");
+	}
+	else {
+		notify($ERRORS{'OK'}, 0, "post_load_custom script does NOT exist: $post_load_custom_path");
+		return 1;
+	}
+	
+	# Get the node configuration directory, make sure it exists, create if necessary
+	my $node_log_directory = $self->get_node_configuration_directory() . '/Logs';
+	if (!$self->create_directory($node_log_directory)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create node log file directory: $node_log_directory");
+		return;
+	}
+	
+	my $management_node_keys = $self->data->get_management_node_keys();
+	my $computer_node_name   = $self->data->get_computer_node_name();
+	
+	# Assemble the log file path
+	my $post_load_custom_log_path = $node_log_directory . "/post_load_custom.log";
+	
+	# Assemble the command
+	my $post_load_custom_command;
+	# Make sure the script is readable and executable
+	$post_load_custom_command .= "chmod +rx \"$post_load_custom_path\"";
+	# Redirect the script output to the log file path
+	$post_load_custom_command .= " && \"$post_load_custom_path\" >> \"$post_load_custom_log_path\" 2>&1";
+	
+	# Execute the command
+	my ($post_load_custom_exit_status, $post_load_custom_output) = run_ssh_command($computer_node_name, $management_node_keys, $post_load_custom_command, '', '', 1);
+	if (defined($post_load_custom_exit_status) && $post_load_custom_exit_status == 0) {
+		notify($ERRORS{'OK'}, 0, "executed $post_load_custom_path, exit status: $post_load_custom_exit_status");
+	}
+	elsif (defined($post_load_custom_exit_status)) {
+		notify($ERRORS{'WARNING'}, 0, "$post_load_custom_path returned a non-zero exit status: $post_load_custom_exit_status, output:\n@{$post_load_custom_output}");
+		return 0;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to execute $post_load_custom_path");
+		return;
+	}
+
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 create_directory
+
+ Parameters  : directory path
+ Returns     : If successful: true
+               If failed: false
+ Description : Creates a directory on the Linux node. If a multi-level
+               directory path is specified, parent directories are also created
+					if they do not exist.
+
+=cut
+
+sub create_directory {
+	my $self = shift;
+	if (ref($self) !~ /module/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Make sure path argument was specified
+	my $path = shift;
+	if (!$path) {
+		notify($ERRORS{'WARNING'}, 0, "directory path argument was not specified");
+		return;
+	}
+	
+	my $management_node_keys = $self->data->get_management_node_keys();
+	my $computer_node_name   = $self->data->get_computer_node_name();
+
+	# Assemble the mkdir command and execute it
+	my $mkdir_command = "mkdir -p \"$path\" && ls -d \"$path\"";
+	my ($mkdir_exit_status, $mkdir_output) = run_ssh_command($computer_node_name, $management_node_keys, $mkdir_command, '', '', 1);
+	if (defined($mkdir_output) && grep(/ls: /, @$mkdir_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create directory on $computer_node_name: $path, exit status: $mkdir_exit_status, output:\n@{$mkdir_output}");
+		return;
+	}
+	elsif (defined($mkdir_exit_status)) {
+		notify($ERRORS{'OK'}, 0, "directory created on $computer_node_name: $path, output:\n@{$mkdir_output}");
+		return 1;
+	}
+	elsif (defined($mkdir_exit_status)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create directory on $computer_node_name: $path, exit status: $mkdir_exit_status, output:\n@{$mkdir_output}");
+		return;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to delete file on $computer_node_name: $path");
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 filesystem_entry_exists
+
+ Parameters  : filesystem path
+ Returns     : If entry exists: 1
+               If entry does not exist: 0
+					If error occurred: undefined
+ Description : Checks if a filesystem entry (file or directory) exists on the
+					Linux node.
+
+=cut
+
+sub filesystem_entry_exists {
+	my $self = shift;
+	if (ref($self) !~ /module/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Get the path from the subroutine arguments and make sure it was passed
+	my $path = shift;
+	if (!$path) {
+		notify($ERRORS{'WARNING'}, 0, "unable to detmine if file exists, path was not specified as an argument");
+		return;
+	}
+	
+	my $management_node_keys = $self->data->get_management_node_keys();
+	my $computer_node_name   = $self->data->get_computer_node_name();
+	
+	# Assemble the dir command and execute it
+	my $ls_command = "ls -l \"$path\"";
+	my ($ls_exit_status, $ls_output) = run_ssh_command($computer_node_name, $management_node_keys, $ls_command, '', '', 1);
+	if (defined($ls_output) && grep(/no such file/i, @$ls_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "filesystem entry does NOT exist on $computer_node_name: $path");
+		return 0;
+	}
+	elsif ((defined($ls_exit_status) && $ls_exit_status == 0) || (defined($ls_output) && grep(/$path/i, @$ls_output))) {
+		notify($ERRORS{'DEBUG'}, 0, "filesystem entry exists on $computer_node_name: $path, dir output:\n" . join("\n", @$ls_output));
+		return 1;
+	}
+	elsif ($ls_exit_status) {
+		notify($ERRORS{'WARNING'}, 0, "failed to determine if filesystem entry exists on $computer_node_name: $path, exit status: $ls_exit_status, output:\n@{$ls_output}");
+		return;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to determine if filesystem entry exists on $computer_node_name: $path");
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 1;
 __END__