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:\...@{$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:\...@{$mkdir_output}");
+               return;
+       }
+       elsif (defined($mkdir_exit_status)) {
+               notify($ERRORS{'OK'}, 0, "directory created on 
$computer_node_name: $path, output:\...@{$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:\...@{$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:\...@{$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__
 


Reply via email to