Author: arkurth
Date: Wed Aug 12 15:13:30 2015
New Revision: 1695554

URL: http://svn.apache.org/r1695554
Log:
VCL-871
Updated OS.pm::create_text_file to ensure that text is added on a new line at 
the end of the file if called with the $append flag. This subroutine should 
correctly add newlines when necessary. Callers of append_text_file (which calls 
create_text_file) should not have to ensure a trailing newline exists in the 
string passed.

Removed trailing newline from the AllowUsers line appended to 
external_sshd_config in Linux.pm::grant_connect_method_access. It should no 
longer be needed.

Updated OS.pm::set_vcld_post_load_status to use create_text_file instead of 
echo.

VCL-896
Reworked and cleaned up Linux.pm::update_public_hostname. Added call to 
hostnamectl.  Removed Linux.pm::update_hostname_file which was using sed and 
echo instead of create_text_file.

VCL-897
Changed argument accepted by Linux.pm::grant_root_access to a simple string. 
Changed Linux.pm::create_user to only call grant_root_access if necessary.

Other
Added Linux.pm::install_package. This isn't currently being called but may be 
used in the future.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.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=1695554&r1=1695553&r2=1695554&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed Aug 12 15:13:30 2015
@@ -1363,37 +1363,22 @@ sub set_vcld_post_load_status {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
                return;
        }
-
-       my $image_os_type = $self->data->get_image_os_type();
-       my $computer_node_name = $self->data->get_computer_node_name();
-       
-       my $time = localtime;
        
        my $file_path = 'currentimage.txt';
-       $self->remove_lines_from_file($file_path, 'vcld_post_load');
        
+       my $time = localtime;
        my $post_load_line = "vcld_post_load=success ($time)";
        
-       # Assemble the command
-       my $command;
-       $command .= " echo >> $file_path";
-       $command .= " && echo \"$post_load_line\" >> $file_path";
-       
-       my ($exit_status, $output) = $self->execute($command, 1);
-       if (defined($exit_status) && $exit_status == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "added line to $file_path on 
$computer_node_name: '$post_load_line'");
-       }
-       elsif ($exit_status) {
-               notify($ERRORS{'WARNING'}, 0, "failed to add line to $file_path 
on $computer_node_name: '$post_load_line', exit status: $exit_status, 
output:\n" . join("\n", @$output));
-               return;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to add 
line to $file_path on $computer_node_name");
-               return;
+       my $file_contents;
+       my @existing_lines = $self->get_file_contents($file_path);
+       for my $existing_line (@existing_lines) {
+               if ($existing_line !~ /\w/ || $existing_line =~ 
/^vcld_post_load/) {
+                       next;
+               }
+               $file_contents .= "$existing_line\n";
        }
-       
-       $self->set_text_file_line_endings($file_path);
-       return 1;
+       $file_contents .= $post_load_line;
+       return $self->create_text_file($file_path, $file_contents);
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2142,10 +2127,17 @@ sub get_public_default_gateway {
 
  Parameters  : $file_path, $file_contents, $append
  Returns     : boolean
- Description : Creates a text file on the computer. The $file_contents
-               string argument is converted to ASCII hex values. These values
-               are echo'd on the computer which avoids problems with special
-               characters and escaping.
+ Description : Creates a text file on the computer or appends to an existing
+               file.
+               
+               A trailing newline character is added to the end of the
+               file if one is not present in the $file_contents argument.
+               
+               It is assumed that when appending to an existing file, the value
+               of $file_contents is intended to be added on a new line at the
+               end of the file. The contents of the existing file are first
+               retrieved. If the existing file does not contain a trailing
+               newline, one is added before appending to the file.
 
 =cut
 
@@ -2167,24 +2159,57 @@ sub create_text_file {
        }
        
        my $computer_node_name = $self->data->get_computer_node_name();
-       my $image_os_type = $self->data->get_image_os_type();
        
-       # Attempt to create the parent directory if it does not exist
-       if ($file_path =~ /[\\\/]/ && $self->can('create_directory')) {
-               my $parent_directory_path = parent_directory_path($file_path);
-               $self->create_directory($parent_directory_path) if 
$parent_directory_path;
+       my $image_os_type = $self->data->get_image_os_type();
+       my $newline;
+       if ($image_os_type =~ /win/i) {
+               $newline = "\r\n";
+       }
+       else {
+               $newline = "\n";
        }
        
-       my $mode;
+       # Used only to format notify messages
        my $mode_string;
        if ($append) {
-               $mode = '>>';
                $mode_string = 'append';
+               
+               # Retrieve the contents of the existing file if necessary
+               if ($self->file_exists($file_path)) {
+                       my $existing_file_contents = 
$self->get_file_contents($file_path);
+                       if (!defined($existing_file_contents)) {
+                               # Do not proceed if any problem occurred 
retrieving the existing file contents
+                               # Otherwise, it would be overwritten and data 
would be lost
+                               notify($ERRORS{'WARNING'}, 0, "failed to 
$mode_string text file on $computer_node_name, append argument was specified 
but contents of the existing file could not be retrieved: $file_path");
+                               return;
+                       }
+                       elsif ($existing_file_contents && 
$existing_file_contents !~ /\n$/) {
+                               # Add a newline to the end of the existing 
contents if one isn't present
+                               $existing_file_contents .= $newline;
+                               $file_contents_string = $existing_file_contents 
. $file_contents_string;
+                       }
+                       
+               }
        }
        else {
-               $mode = '>';
                $mode_string = 'create';
        }
+
+       # Make sure the file contents ends with a newline
+       # This is helpful to prevent problems with files such as sshd_config 
and sudoers where a line might be echo'd to the end of it
+       # Without the newline, the last line could wind up being a merged line 
if a simple echo is used to add a line
+       if (length($file_contents_string) && $file_contents_string !~ /\n$/) {
+               $file_contents_string .= $newline;
+       }
+       
+       # Make line endings consistent
+       $file_contents_string =~ s/\r*\n/$newline/g;
+
+       # Attempt to create the parent directory if it does not exist
+       if ($file_path =~ /[\\\/]/ && $self->can('create_directory')) {
+               my $parent_directory_path = parent_directory_path($file_path);
+               $self->create_directory($parent_directory_path) if 
$parent_directory_path;
+       }
        
        # The echo method will fail of the file contents are too large
        # An "Argument list too long" error will be displayed
@@ -2206,8 +2231,13 @@ sub create_text_file {
                # Join the hex values together into a string
                my $hex_string = join('', @hex_values);
                
-               # Attempt to create/append the file using the hex string
-               my $command = "echo -e \"$hex_string\" $mode \"$file_path\"";
+               # Enclose the file path in quotes if it contains a space
+               if ($file_path =~ /[\s]/) {
+                       $file_path = "\"$file_path\"";
+               }
+               
+               # Attempt to create the file using the hex string
+               my $command = "echo -n -e \"$hex_string\" > $file_path";
                my ($exit_status, $output) = $self->execute($command, 0, 15, 1);
                if (!defined($output)) {
                        notify($ERRORS{'DEBUG'}, 0, "failed to execute command 
to $mode_string file on $computer_node_name, attempting to create file on 
management node and copy it to $computer_node_name");
@@ -2228,20 +2258,7 @@ sub create_text_file {
                notify($ERRORS{'DEBUG'}, 0, "skipping attempt to $mode_string 
on $computer_node_name using echo, file content string length: 
$file_contents_length");
        }
        
-       # File will be copied from the management node to the computer
-       if ($append) {
-               if ($self->file_exists($file_path)) {
-                       my $existing_file_contents = 
$self->get_file_contents($file_path);
-                       if (defined($existing_file_contents)) {
-                               $file_contents_string = $existing_file_contents 
. $file_contents_string;
-                       }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "failed to 
$mode_string text file on $computer_node_name, append argument was specified 
but contents of the existing file could not be retrieved: $file_path");
-                               return;
-                       }
-               }
-       }
-       
+       # File was not created using the quicker echo method
        # Create a temporary file on the management node, copy it to the 
computer, then delete temporary file from management node
        my $mn_temp_file_path = tmpnam();
        if (!$self->mn_os->create_text_file($mn_temp_file_path, 
$file_contents_string, $append)) {
@@ -2253,7 +2270,6 @@ sub create_text_file {
                return;
        }
        $self->mn_os->delete_file($mn_temp_file_path);
-       
        notify($ERRORS{'DEBUG'}, 0, "created text file on $computer_node_name 
by copying a file created on management node");
        return 1;
 }
@@ -4122,13 +4138,9 @@ sub update_cluster {
                $cluster_info_string .= "$cluster_computer_public_ip_address\n";
        }
        
-       # Remove trailing newline
-       $cluster_info_string =~ s/\n$//;
-       
        # Create the cluster_info file on the computer
        if ($self->create_text_file($cluster_info_file_path, 
$cluster_info_string)) {
                notify($ERRORS{'DEBUG'}, 0, "created $cluster_info_file_path on 
$computer_short_name:\n$cluster_info_string");
-               $self->set_text_file_line_endings($cluster_info_file_path);
        }
        else {
                notify($ERRORS{'WARNING'}, 0, "failed to create 
$cluster_info_file_path on $computer_short_name");
@@ -4136,7 +4148,7 @@ sub update_cluster {
        }
        
        # Open the firewall allowing other cluster reservations computers access
-       if ($self->can('enable_firewall_port')) {
+       if (@public_ip_addresses && $self->can('enable_firewall_port')) {
                my $firewall_scope = join(",", @public_ip_addresses);
                notify($ERRORS{'DEBUG'}, 0, "attempting to open the firewall on 
$computer_short_name to allow access from other cluster reservation computers: 
$firewall_scope");
                

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=1695554&r1=1695553&r2=1695554&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed Aug 12 15:13:30 2015
@@ -636,12 +636,8 @@ sub post_reservation {
  Parameters  : none
  Returns     : boolean
  Description : Retrieves the public IP address being used on the Linux 
computer.
-               Runs ipcalc locally on the management node to determine the
-               registered hostname for that IP address. If unable to determine
-               the hostname by running ipcalc on the management node, an 
attempt
-               is made to run ipcalc on the Linux computer. Once the hostname 
is
-               determined, the hostname command is run to set the hostname on
-               the Linux computer.
+               Determines the hostname the IP address resolves to. Sets the
+               hostname on the Linux computer.
 
 =cut
 
@@ -654,93 +650,92 @@ sub update_public_hostname {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       # Get the IP address of the public adapter
-       my $public_ip_address = $self->get_public_ip_address();
-       if (!$public_ip_address) {
-               notify($ERRORS{'WARNING'}, 0, "hostname cannot be set, unable 
to determine public IP address");
-               return;
+       my $public_hostname = shift;
+       if (!$public_hostname) {
+               # Get the IP address of the public adapter
+               my $public_ip_address = $self->get_public_ip_address();
+               if (!$public_ip_address) {
+                       notify($ERRORS{'WARNING'}, 0, "hostname cannot be set, 
unable to determine public IP address");
+                       return;
+               }
+               notify($ERRORS{'DEBUG'}, 0, "retrieved public IP address of 
$computer_node_name: $public_ip_address");
+               
+               # Get the hostname for the public IP address
+               $public_hostname = ip_address_to_hostname($public_ip_address) 
|| $computer_node_name;
        }
-       notify($ERRORS{'DEBUG'}, 0, "retrieved public IP address of 
$computer_node_name: $public_ip_address");
        
-       # Get the hostname for the public IP address
-       my $public_hostname = ip_address_to_hostname($public_ip_address) || 
$computer_node_name;
+       my $error_occurred = 0;
        
-       # Set the node's hostname to public hostname
-       if ($self->can("update_hostname_file")) {
-               if (!$self->update_hostname_file($public_hostname)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to update 
hostname file");
+       # Check if hostname file exists and update if necessary
+       my $hostname_file_path = '/etc/hostname';
+       if ($self->file_exists($hostname_file_path)) {
+               if ($self->create_text_file($hostname_file_path, 
$public_hostname)) {
+                       notify($ERRORS{'DEBUG'}, 0, "updated 
$hostname_file_path on $computer_node_name with hostname '$public_hostname'");
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "failed to update 
$hostname_file_path on $computer_node_name with '$public_hostname'");
+                       $error_occurred = 1;
                }
-       }
-       
-       my $hostname_command = "hostname $public_hostname";
-       my ($hostname_exit_status, $hostname_output) = 
$self->execute($hostname_command);
-       if (!defined($hostname_output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to SSH command to set 
hostname on $computer_node_name to $public_hostname, command: 
'$hostname_command'");
-               return;
-       }
-       elsif ($hostname_exit_status == 0) {
-               notify($ERRORS{'OK'}, 0, "set public hostname on 
$computer_node_name to $public_hostname");
-               return 1;
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "failed to set public hostname on 
$computer_node_name to $public_hostname, exit status: $hostname_exit_status, 
output:\n" . join("\n", @$hostname_output));
-               return 0;
+               notify($ERRORS{'DEBUG'}, 0, "$hostname_file_path not updated on 
$computer_node_name because the file does not exist");
        }
        
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 update_hostname_file
-
- Parameters  : hostname
- Returns     : boolean
- Description : updates the static hostname file on node, so hostname persists 
across reboots
-               seperated from update_public_hostname as the file location and 
format can differ
-               accross Linux distributions
-
-=cut
-
-sub update_hostname_file {
-       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 0;
-       }
-
-       my $public_hostname = shift;
-       if (!$public_hostname) {
-               notify($ERRORS{'WARNING'}, 0, "public_hostname was not passed 
correctly");
-               return 0;
-       }
-
-       my $computer_node_name = $self->data->get_computer_node_name();
-       my $network_file_path = '/etc/sysconfig/network';
        
-       my $hostname_file_path =  '/etc/hostname';
-       # For Linux OS that are using /etc/hostname
-       if($self->file_exists($hostname_file_path)) {
-               my $update_hostname_file_cmd = "echo $public_hostname > 
$hostname_file_path";
-               if($self->execute($update_hostname_file_cmd)) {
-                       notify($ERRORS{'OK'}, 0, "updated $hostname_file_path 
on $computer_node_name to $public_hostname");
+       # Check if network file exists and update if necessary
+       my $network_file_path = '/etc/sysconfig/network';
+       if ($self->file_exists($network_file_path)) {
+               my $sed_command = "sed -i -e \"/^HOSTNAME=/d\" 
$network_file_path; echo \"HOSTNAME=$public_hostname\" >> $network_file_path";
+               my ($sed_exit_status, $sed_output) = 
$self->execute($sed_command);
+               if (!defined($sed_output)) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command to update hostname in $network_file_path on $computer_node_name");
+                       return;
+               }
+               elsif ($sed_exit_status != 0) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to update 
hostname in $network_file_path on $computer_node_name, exit status: 
$sed_exit_status, output:\n" . join("\n", @$sed_output));
+                       $error_occurred = 1;
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "updated hostname in 
$network_file_path on $computer_node_name to '$public_hostname'");
                }
        }
-
-       my $command = "sed -i -e \"/^HOSTNAME=/d\" $network_file_path; echo 
\"HOSTNAME=$public_hostname\" >> $network_file_path";
-       my ($exit_status, $output) = $self->execute($command);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to SSH command to set 
hostname on $computer_node_name to $public_hostname, command: '$command'");
+       else {
+               notify($ERRORS{'DEBUG'}, 0, "$network_file_path not updated on 
$computer_node_name because the file does not exist");
        }
-       elsif ($exit_status == 0) {
-               notify($ERRORS{'OK'}, 0, "set public hostname on 
$computer_node_name to $public_hostname");
+       
+       # Check if hostnamectl exists, this is provided by systemd on 
CentOS/RHEL 7+
+       if ($self->command_exists('hostnamectl')) {
+               my $hostnamectl_command = "hostnamectl set-hostname 
$public_hostname";
+               my ($hostnamectl_exit_status, $hostnamectl_output) = 
$self->execute($hostnamectl_command);
+               if (!defined($hostnamectl_output)) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command to set hostname using hostnamectl command on $computer_node_name to 
$public_hostname");
+                       return;
+               }
+               elsif ($hostnamectl_exit_status != 0) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to set hostname 
using hostnamectl command on $computer_node_name to $public_hostname, exit 
status: $hostnamectl_exit_status, command: '$hostnamectl_command', output:\n" . 
join("\n", @$hostnamectl_output));
+                       $error_occurred = 1;
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "set hostname using 
hostnamectl command on $computer_node_name to $public_hostname");
+               }
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "failed to set public hostname on 
$computer_node_name to $public_hostname, exit status: $exit_status, output:\n" 
. join("\n", @ $output));
+               my $hostname_command = "hostname $public_hostname";
+               my ($hostname_exit_status, $hostname_output) = 
$self->execute($hostname_command);
+               if (!defined($hostname_output)) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to execute 
command to set hostname using hostname command on $computer_node_name to 
$public_hostname");
+                       return;
+               }
+               elsif ($hostname_exit_status != 0) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to set hostname 
using hostname command on $computer_node_name to $public_hostname, exit status: 
$hostname_exit_status, command: '$hostname_command', output:\n" . join("\n", 
@$hostname_output));
+                       $error_occurred = 1;
+               }
+               else {
+                       notify($ERRORS{'OK'}, 0, "set hostname using hostname 
command on $computer_node_name to $public_hostname");
+               }
        }
-
-       return 1;
-
+       
+       return !$error_occurred;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2770,17 +2765,13 @@ sub create_user {
                        notify($ERRORS{'WARNING'}, 0, "failed to process 
grant_connect_method_access for $username");
                }
        }
-
+       
        # Add user to sudoers if necessary
-       if ($self->can("grant_root_access")) {
-               if (!$self->grant_root_access({
-                       username => $username,
-                       root_access => $root_access,
-                       })) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to process 
grant_root_access for $username");
-                       }
+       if ($root_access && !$self->grant_root_access($username)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to process 
grant_root_access for $username");
+               return;
        }
-
+       
        return 1;
 } ## end sub create_user
 
@@ -2790,8 +2781,8 @@ sub create_user {
 =head2 grant_root_access
 
  Parameters  : $username
- Returns     : 1 , 0
- Description : Updates sudoers file for
+ Returns     : boolean
+ Description : Adds the user to the sudoers file.
 
 =cut
 
@@ -2802,45 +2793,22 @@ sub grant_root_access {
                return;
        }
        
-       my $user_parameters = shift;
-       if (!$user_parameters) {
-               notify($ERRORS{'WARNING'}, 0, "unable to grant acess, user 
parameters argument was not provided");
-               return;
-       }
-       elsif (!ref($user_parameters) || ref($user_parameters) ne 'HASH') {
-               notify($ERRORS{'WARNING'}, 0, "unable to grant access, argument 
provided is not a hash reference");
-               return;
-       }
-       
-       my $username = $user_parameters->{username};
+       my $username = shift;
        if (!defined($username)) {
-               notify($ERRORS{'WARNING'}, 0, "argument hash does not contain a 
'username' key:\n" . format_data($user_parameters));
+               notify($ERRORS{'WARNING'}, 0, "username argument was not 
supplied");
                return;
        }
        
-       my $root_access = $user_parameters->{root_access};
-       if (!defined($root_access)) {
-               notify($ERRORS{'WARNING'}, 0, "argument hash does not contain a 
'root_access' key:\n" . format_data($user_parameters));
-               return;
-       }
-
-       if ($root_access) {
-               my $sudoers_file_path = '/etc/sudoers';
-               my $sudoers_line = "$username ALL= NOPASSWD: ALL";
-               if ($self->append_text_file($sudoers_file_path, $sudoers_line)) 
{
-                       notify($ERRORS{'DEBUG'}, 0, "appended line to 
$sudoers_file_path: '$sudoers_line'");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "failed to append line to 
$sudoers_file_path: '$sudoers_line'");
-                       return 1;
-               }
+       my $sudoers_file_path = '/etc/sudoers';
+       my $sudoers_line = "$username ALL= NOPASSWD: ALL";
+       if ($self->append_text_file($sudoers_file_path, $sudoers_line)) {
+               notify($ERRORS{'DEBUG'}, 0, "appended line to 
$sudoers_file_path: '$sudoers_line'");
+               return 1;
        }
        else {
-               notify($ERRORS{'OK'}, 0, "root access for user $username was 
not allowed root_access = $root_access ");
-      return 1;
+               notify($ERRORS{'WARNING'}, 0, "failed to append line to 
$sudoers_file_path: '$sudoers_line'");
+               return 0;
        }
-
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -6095,7 +6063,7 @@ sub get_ssh_public_key_string {
        }
        if ($public_key_string) {
                if ($comment) {
-                       $public_key_string =~ s/(ssh-[^\s]+\s[^\s=]+).*$/$1== 
$comment/g;
+                       $public_key_string =~ s/(ssh-[^\s]+\s[^\s=]+).*$/$1 
$comment/g;
                }
                return $public_key_string;
        }
@@ -6183,6 +6151,63 @@ sub _get_ssh_public_key_string_helper {
        }
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 install_package
+
+ Parameters  : $package_name, $timeout_seconds (optional)
+ Returns     : boolean
+ Description : Installs a Linux package using yum.
+
+=cut
+
+sub install_package {
+       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;
+       }
+       
+       my ($package_name, $timeout_seconds) = @_;
+       if (!$package_name) {
+               notify($ERRORS{'WARNING'}, 0, "package name argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_name = $self->data->get_computer_node_name();
+       
+       if (!$self->command_exists('yum')) {
+               notify($ERRORS{'WARNING'}, 0, "failed to install $package_name 
on $computer_name, yum command is not available");
+               return;
+       }
+       
+       $timeout_seconds = 120 unless $timeout_seconds;
+       
+       my $command = "yum install -q -y $package_name";
+       notify($ERRORS{'DEBUG'}, 0, "attempting to install $package_name using 
yum on $computer_name, timeout seconds: $timeout_seconds");
+       my ($exit_status, $output) = $self->execute({
+               'command' => $command,
+               'display_output' => 0,
+               'timeout_seconds' => $timeout_seconds,
+       });
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
install $package_name using yum on $computer_name");
+               return;
+       }
+       elsif ($exit_status ne 0) {
+               notify($ERRORS{'WARNING'}, 0, "failed to install $package_name 
using yum on $computer_name, exit status: $exit_status, command: '$command', 
output:\n" . join("\n", @$output));
+               return 0;
+       }
+       elsif (grep(/$package_name.+already installed/, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "$package_name is already installed 
on $computer_name, command: '$command', output:\n" . join("\n", @$output));
+               return 1;
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "installed $package_name using yum on 
$computer_name, command: '$command', output:\n" . join("\n", @$output));
+               return 1;
+       }
+}
+
 ##/////////////////////////////////////////////////////////////////////////////
 1;
 __END__


Reply via email to