Author: arkurth
Date: Wed Nov 14 19:09:00 2012
New Revision: 1409301

URL: http://svn.apache.org/viewvc?rev=1409301&view=rev
Log:
VCL-582
Reworked Linux init daemon module code to handle OS's which use multiple init 
daemons such as systemd and SysV.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm

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=1409301&r1=1409300&r2=1409301&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed Nov 14 19:09:00 2012
@@ -98,7 +98,7 @@ sub get_node_configuration_directory {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 init
+=head2 get_init_modules
 
  Parameters  : none
  Returns     : Linux init module reference
@@ -110,14 +110,14 @@ sub get_node_configuration_directory {
 
 =cut
 
-sub init {
+sub get_init_modules {
        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;
        }
 
-       return $self->{init} if $self->{init};
+       return @{$self->{init_modules}} if $self->{init_modules};
        
        notify($ERRORS{'DEBUG'}, 0, "beginning Linux init daemon module 
initialization");
        
@@ -130,50 +130,80 @@ sub init {
        # Get a list of all *.pm files in the init module directory
        my @init_module_paths = $self->mn_os->find_files($init_directory_path, 
'*.pm');
        
-       # Find the position of the SysV.pm file
-       my ($sysv_index) = grep { $init_module_paths[$_] =~ /SysV\.pm/ } 
0..$#init_module_paths;
-       
-       # Move the SysV.pm file to the end of the array
-       push(@init_module_paths, splice(@init_module_paths, $sysv_index, 1));
-
        # Attempt to create an initialize an object for each init module
-       # Use the first init module successfully initialized
-       for my $init_module_path (@init_module_paths) {
+       my %init_module_hash;
+       INIT_MODULE: for my $init_module_path (@init_module_paths) {
                my $init_name = fileparse($init_module_path, qr/\.pm$/i);
                my $init_perl_package = 
"VCL::Module::OS::Linux::init::$init_name";
                
-               # Create and initialize the init object
+               # Attempt to load the init module
                notify($ERRORS{'DEBUG'}, 0, "attempting to load $init_name init 
module: $init_perl_package");
                eval "use $init_perl_package";
-               if ($EVAL_ERROR) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to load 
$init_name init module: $init_perl_package, error: $EVAL_ERROR");
-                       next;
+               if ($EVAL_ERROR || $@) {
+                       notify($ERRORS{'CRITICAL'}, 0, "failed to load 
$init_name init module: $init_perl_package, error: $EVAL_ERROR");
+                       next INIT_MODULE;
                }
-               notify($ERRORS{'DEBUG'}, 0, "loaded $init_name init module: 
$init_perl_package");
                
+               # Attempt to create an init module object
+               # The 'new' constructor will automatically call the module's 
initialize subroutine
+               # initialize will check the computer to determine if it 
contains the corresponding Linux init daemon installed
+               # If not installed, the constructor will return false
                my $init;
                eval { $init = ($init_perl_package)->new({data_structure => 
$self->data, os => $self}) };
                if ($init) {
-                       notify($ERRORS{'OK'}, 0, "$init_name init object 
created and initialized to control $computer_node_name");
-                       $self->{init} = $init;
-                       $self->{init_name} = $init_name;
-                       last;
+                       my @required_commands = eval "@" . $init_perl_package . 
"::REQUIRED_COMMANDS";
+                       if ($EVAL_ERROR) {
+                               notify($ERRORS{'CRITICAL'}, 0, 
"\@REQUIRED_COMMANDS variable is not defined in the $init_perl_package Linux 
init daemon module");
+                               next INIT_MODULE;
+                       }
+                       
+                       for my $command (@required_commands) {
+                               if (!$self->command_exists($command)) {
+                                       next INIT_MODULE;
+                               }
+                       }
+                       
+                       # init object successfully created, retrieve the 
module's $INIT_DAEMON_ORDER variable
+                       # An OS may have/support multiple Linux init daemons, 
services may be registered under different init daemons
+                       # In some cases, need to try multple init modules to 
control a service
+                       # This $INIT_DAEMON_ORDER integer determines the order 
in which the modules are tried
+                       my $init_daemon_order = eval '$' . $init_perl_package . 
'::INIT_DAEMON_ORDER';
+                       if ($EVAL_ERROR) {
+                               notify($ERRORS{'CRITICAL'}, 0, 
"\$INIT_DAEMON_ORDER variable is not defined in the $init_perl_package Linux 
init daemon module");
+                               next INIT_MODULE;
+                       }
+                       elsif ($init_module_hash{$init_daemon_order}) {
+                               notify($ERRORS{'CRITICAL'}, 0, "multiple Linux 
init daemon modules are configured to use 
\$INIT_DAEMON_ORDER=$init_daemon_order: " . 
ref($init_module_hash{$init_daemon_order}) . ", " . ref($init) . ", the value 
of this variable must be unique");
+                               next INIT_MODULE;
+                       }
+                       else {
+                               notify($ERRORS{'DEBUG'}, 0, "$init_name init 
object created and initialized to control $computer_node_name, order: 
$init_daemon_order");
+                               $init_module_hash{$init_daemon_order} = $init;
+                       }
                }
                elsif ($EVAL_ERROR) {
-                       notify($ERRORS{'WARNING'}, 0, "$init_name init object 
could not be created: type: $init_perl_package, error:\n$EVAL_ERROR");
+                       notify($ERRORS{'WARNING'}, 0, "$init_perl_package init 
object could not be created, error:\n$EVAL_ERROR");
                }
                else {
                        notify($ERRORS{'DEBUG'}, 0, "$init_name init object 
could not be initialized to control $computer_node_name");
                }
        }
        
-       # Make sure the init module object was successfully initialized
-       if (!$self->{init}) {
+       # Make sure at least 1 init module object was successfully initialized
+       if (!%init_module_hash) {
                notify($ERRORS{'WARNING'}, 0, "failed to create Linux init 
daemon module");
                return;
        }
        
-       return $self->{init};
+       # Construct an array of init module objects from highest to lowest 
$INIT_DAEMON_ORDER
+       $self->{init_modules} = [];
+       my $init_module_order_string;
+       for my $init_daemon_order (sort {$a <=> $b} keys %init_module_hash) {
+               push @{$self->{init_modules}}, 
$init_module_hash{$init_daemon_order};
+               $init_module_order_string .= "$init_daemon_order: " . 
ref($init_module_hash{$init_daemon_order}) . "\n";
+       }
+       notify($ERRORS{'DEBUG'}, 0, "constructed array containing init module 
objects which may be used to control 
$computer_node_name:\n$init_module_order_string");
+       return @{$self->{init_modules}};
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2552,10 +2582,34 @@ EOF
 =head2 service_exists
 
  Parameters  : $service_name
- Returns     : If service exists: 1
-               If service does not exist: 0
-               If error occurred: undefined
- Description : 
+ Returns     : If called in scalar/boolean context: boolean
+               If called in array context: array
+ Description : Checks if the service exists on the computer. The return value
+               differs depending on if this subroutine was called in
+               scalar/boolean or array context.
+               
+               Scalar/boolean context returns either '0' or '1':
+               if ($self->service_exists('xxx'))
+               
+               Array context returns an array with a single, integer element.
+               The value of this integer is the index of the init module
+               returned by get_init_modules which controls the service. This is
+               done so the calling subroutine doesn't need to perform the same
+               steps to determine which init module to use when controlling
+               services. The value of the array element may be 0, meaning the
+               service exists and is controlled by the first init module
+               returned by get_init_modules. Therefore, be sure to check if the
+               return value is defined and not whether it is true/false when
+               called in array context.
+               
+               my ($init_module_index) = $self->service_exists('xxx');
+               
+               if (defined($init_module_index))... means service exists,
+               $init_module_index may be 0 or another positive integer.
+               
+               if ($init_module_index)... WRONG! This will evaluate to false if
+               the service does not exist or if it does exist and the first 
init
+               module controls it.
 
 =cut
 
@@ -2572,7 +2626,35 @@ sub service_exists {
                return;
        }
        
-       return $self->init->service_exists($service_name);
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my @init_modules = $self->get_init_modules();
+       my $init_module_index = 0;
+       for my $init (@init_modules) {
+               my ($init_module_name) = ref($init) =~ /([^:]+)$/;
+               
+               # Check if the service names have already been retrieved by 
this particular init module object
+               my @service_names;
+               if ($init->{service_names}) {
+                       @service_names = @{$init->{service_names}};
+               }
+               else {
+                       @service_names = $init->get_service_names();
+                       $init->{service_names} = \@service_names;
+               }
+               
+               if (grep(/^$service_name$/, @service_names)) {
+                       notify($ERRORS{'DEBUG'}, 0, "'$service_name' service 
exists on $computer_node_name, controlled by $init_module_name init module 
($init_module_index)");
+                       return (wantarray) ? ($init_module_index) : 1;
+               }
+               else {
+                       notify($ERRORS{'DEBUG'}, 0, "'$service_name' service is 
not controlled by $init_module_name init module ($init_module_index)");
+               }
+               $init_module_index++;
+       }
+       
+       notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not exist on 
$computer_node_name");
+       return (wantarray) ? () : 0;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2598,7 +2680,16 @@ sub start_service {
                return;
        }
        
-       return $self->init->start_service($service_name);
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to start '$service_name' 
service because it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       return $init_module->start_service($service_name);
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2623,9 +2714,17 @@ sub stop_service {
                notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
                return;
        }
-       my $command;
        
-       return $self->init->stop_service($service_name);
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'DEBUG'}, 0, "unable to stop '$service_name' 
service because it does not exist on $computer_node_name");
+               return 1;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       return $init_module->stop_service($service_name);
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2650,9 +2749,60 @@ sub restart_service {
                notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
                return;
        }
-       my $command;
        
-       return $self->init->restart_service($service_name);
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to restart 
'$service_name' service because it does not exist on $computer_node_name");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       return $init_module->restart_service($service_name);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub delete_service {
+       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 $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
+       my $computer_node_name = $self->data->get_computer_node_name();
+       
+       my ($init_module_index) = $self->service_exists($service_name);
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'DEBUG'}, 0, "unable to delete '$service_name' 
service because it does not exist on $computer_node_name");
+               return 1;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       if ($init_module->delete_service($service_name)) {
+               # Delete the cached service name array
+               delete $init_module->{service_names};
+       }
+       else {
+               return;
+       }
+       
+       return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -3874,32 +4024,6 @@ sub user_exists {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 delete_service
-
- Parameters  : $service_name
- Returns     : boolean
- Description : 
-
-=cut
-
-sub delete_service {
-       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 ($service_name) = @_;
-       if (!$service_name) {
-               notify($ERRORS{'WARNING'}, 0, "service name pattern argument 
was not supplied");
-               return;
-       }
-       
-       return $self->init->delete_service($service_name);
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 stop_external_sshd
 
  Parameters  : none
@@ -4082,14 +4206,14 @@ sub configure_sshd_config_file {
  Parameters  : none
  Returns     : boolean
  Description : Generates /etc/ssh/external_sshd_config based off of
-                                       /etc/ssh/sshd_config currently residing 
on the computer with the
-                                       following parameters overridden:
-                                       PidFile /var/run/ext_sshd.pid
-                                       PermitRootLogin no
-                                       X11Forwarding yes
-                                       PasswordAuthentication yes
-                                       AllowUsers 
-                                       ListenAddress => <public IP aaddress>
+               /etc/ssh/sshd_config currently residing on the computer with the
+               following parameters overridden:
+               PidFile /var/run/ext_sshd.pid
+               PermitRootLogin no
+               X11Forwarding yes
+               PasswordAuthentication yes
+               AllowUsers 
+               ListenAddress => <public IP aaddress>
 
 =cut
 
@@ -4148,14 +4272,14 @@ sub configure_default_sshd {
        my $computer_node_name = $self->data->get_computer_node_name();
        
        # Stop existing external sshd process if it is running
-       $self->init->stop_service('ext_sshd');
+       $self->stop_service('ext_sshd');
        if (!$self->stop_external_sshd()) {
                notify($ERRORS{'WARNING'}, 0, "unable to configure default sshd 
state, problem occurred attempting to kill external sshd process");
                return;
        }
        
        # Delete the ext_sshd service
-       $self->init->delete_service('ext_sshd') || return;
+       $self->delete_service('ext_sshd') || return;
        
        # Delete the external sshd configuration file
        $self->delete_file('/etc/ssh/ext*ssh*');
@@ -4216,8 +4340,21 @@ sub configure_ext_sshd {
                return;
        }
        
+       # Deterine which init module is currently controlling sshd, use the 
same module to control ext_sshd
+       my ($init_module_index) = $self->service_exists('sshd');
+       if (!defined($init_module_index)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to configure ext_sshd, 
init module controlling sshd could not be determined");
+               return;
+       }
+       
+       my $init_module = ($self->get_init_modules())[$init_module_index];
+       
        # Add the ext_sshd service
-       if (!$self->init->add_ext_sshd_service()) {
+       if ($init_module->add_ext_sshd_service()) {
+               # Delete the cached service name array
+               delete $init_module->{service_names};
+       }
+       else {
                notify($ERRORS{'WARNING'}, 0, "unable to configure ext_sshd, 
failed to add the ext_sshd service to $computer_node_name");
                return;
        }
@@ -4320,7 +4457,7 @@ sub command_exists {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       my ($exit_status, $output) = $self->execute("which $shell_command");
+       my ($exit_status, $output) = $self->execute("which $shell_command", 0);
        if (!defined($output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if the '$shell_command' shell command exists on $computer_node_name");
                return;

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm?rev=1409301&r1=1409300&r2=1409301&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm Wed Nov 14 
19:09:00 2012
@@ -26,8 +26,8 @@ VCL::Module::OS::Linux::init::SysV.pm
 
  This module provides VCL support for the SysV-style Linux init daemon used in
  distributions such as:
- Red Hat Enterprise Linux 5.x, 6.x
- CentOS 5.x, 6.x
+    Red Hat Enterprise Linux 5.x, 6.x
+    CentOS 5.x, 6.x
 
 =cut
 
@@ -36,10 +36,7 @@ package VCL::Module::OS::Linux::init::Sy
 
 # Specify the lib path using FindBin
 use FindBin;
-print "$FindBin::Bin/../../../.." . "\n\n";
-exit;
-
-use lib "$FindBin::Bin/../../../..";
+use lib "$FindBin::Bin/../../../../..";
 
 # Configure inheritance
 use base qw(VCL::Module::OS::Linux);
@@ -58,47 +55,54 @@ use VCL::utils;
 
 ##############################################################################
 
-=head1 OBJECT METHODS
+=head1 CLASS VARIABLES
 
 =cut
 
-#/////////////////////////////////////////////////////////////////////////////
+=head2 $INIT_DAEMON_ORDER
 
-=head2 initialize
+ Data type   : integer
+ Value       : 50
+ Description : Determines the order in which Linux init daemon modules are used
+               if an OS supports multiple init daemons. Lower values are used
+               first. SysV has a higher value than other init modules because 
it
+               is older than other, newer init daemons. The newer init daemon
+               modules should be tried first.
 
- Parameters  : none
- Returns     : true
- Description : 
+=cut
+
+our $INIT_DAEMON_ORDER = 50;
+
+=head2 @REQUIRED_COMMANDS
+
+ Data type   : array
+ Values      : chkconfig, service
+ Description : List of commands used within this module to configure and 
control
+               SysV services. This module will not be used if any of these
+               commands are unavailable on the computer.
 
 =cut
 
-sub initialize {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $computer_node_name = $self->data->get_computer_node_name();
-       
-       # Don't do anything, this is the default init module
-       # It should be used if all others can't be initialized
-       
-       notify($ERRORS{'DEBUG'}, 0, "SysV Linux init module successfully 
initialized to control $computer_node_name");
-       return 1;
-}
+our @REQUIRED_COMMANDS = ('chkconfig', 'service');
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 service_exists
+=head2 get_service_names
 
- Parameters  : $service_name
- Returns     : boolean
- Description : 
+ Parameters  : none
+ Returns     : array
+ Description : Calls 'chkconfig --list' to retrieve the list of services
+               controlled by SysV on the computer.
 
 =cut
 
-sub service_exists {
+sub get_service_names {
        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");
@@ -107,25 +111,23 @@ sub service_exists {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       my $service_name = shift;
-       if (!$service_name) {
-               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
-               return;
-       }
        my $command = "chkconfig --list";
        my ($exit_status, $output) = $self->execute($command, 0);
        if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service exists on $computer_node_name");
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
list SysV services on $computer_node_name");
                return;
        }
-       elsif (grep(/^$service_name[\s\t]/, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists on 
$computer_node_name");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
-               return 0;
+       
+       # Format out chkconfig --list output lines:
+       # sshd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
+       my %service_name_hash;
+       for my $line (@$output) {
+               my ($service_name) = $line =~ /^([^\s\t]+)/;
+               $service_name_hash{$service_name} = 1 if $service_name;
        }
+       my @service_names = sort(keys %service_name_hash);
+       notify($ERRORS{'DEBUG'}, 0, "retrieved SysV service names from 
$computer_node_name: " . join(", ", @service_names));
+       return @service_names;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -134,7 +136,8 @@ sub service_exists {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'chkconfig <$service_name> on' to configure the service to
+               start automatically. Does not start the service.
 
 =cut
 
@@ -182,7 +185,8 @@ sub enable_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'chkconfig <$service_name> off' to prevent the service 
from
+               starting automatically. Does not stop the service.
 
 =cut
 
@@ -230,9 +234,9 @@ sub disable_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : Calls 'chkconfig --add' to add the service specified by the
-               argument. The service file must already reside in
-               /etc/rc.d/init.d/.
+ Description : Calls 'chkconfig --add <$service_name>' to add the service
+               specified by the argument. The service file must already reside
+               in /etc/rc.d/init.d/.
 
 =cut
 
@@ -274,8 +278,9 @@ sub add_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : Calls 'chkconfig --del' to delete the service specified by the
-               argument. Deletes the service file from /etc/rc.d/init.d/.
+ Description : Calls 'chkconfig --del <$service_name>' to delete the service
+               specified by the argument. Deletes the service file from
+               /etc/rc.d/init.d/.
 
 =cut
 
@@ -326,7 +331,7 @@ sub delete_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'service <$service_name> start' to start the service.
 
 =cut
 
@@ -371,7 +376,7 @@ sub start_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'service <$service_name> stop' to start the service.
 
 =cut
 
@@ -417,7 +422,7 @@ sub stop_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'service <$service_name> restart' to start the service.
 
 =cut
 
@@ -462,7 +467,10 @@ sub restart_service {
 
  Parameters  : none
  Returns     : boolean
- Description :
+ Description : Adds the ext_sshd service to the computer. Generates and
+               configures /etc/rc.d/init.d/ext_sshd based off of the existing
+               /etc/rc.d/init.d/sshd file. Adds the ext_sshd service and
+               configures it to start automatically.
 
 =cut
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm?rev=1409301&r1=1409300&r2=1409301&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm Wed Nov 14 
19:09:00 2012
@@ -35,7 +35,7 @@ package VCL::Module::OS::Linux::init::Up
 
 # Specify the lib path using FindBin
 use FindBin;
-use lib "$FindBin::Bin/../../../..";
+use lib "$FindBin::Bin/../../../../..";
 
 # Configure inheritance
 use base qw(VCL::Module::OS::Linux);
@@ -58,11 +58,34 @@ use VCL::utils;
 
 =cut
 
+=head2 $INIT_DAEMON_ORDER
+
+ Data type   : integer
+ Value       : 10
+ Description : Determines the order in which Linux init daemon modules are 
used.
+               Lower values are used first.
+
+=cut
+
+our $INIT_DAEMON_ORDER = 10;
+
+=head2 @REQUIRED_COMMANDS
+
+ Data type   : array
+ Values      : initctl
+ Description : List of commands used within this module to configure and 
control
+               Upstart services. This module will not be used if any of these
+               commands are unavailable on the computer.
+
+=cut
+
+our @REQUIRED_COMMANDS = ('initctl');
+
 =head2 $SERVICE_NAME_MAPPINGS
 
  Data type   : hash reference
  Description : Contains a mapping of common service names to the names used by
-                                       Upstart distibutions. Example, sshd is 
called ssh on Ubuntu.
+               Upstart distibutions. Example, sshd is called ssh on Ubuntu.
 
 =cut
 
@@ -79,59 +102,16 @@ our $SERVICE_NAME_MAPPINGS = {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 initialize
+=head2 get_service_names
 
  Parameters  : none
- Returns     : boolean
- Description : 
+ Returns     : array
+ Description : Calls 'initctl list' to retrieve the list of services controlled
+               by Upstart on the computer.
 
 =cut
 
-sub initialize {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $computer_node_name = $self->data->get_computer_node_name();
-       
-       # Check to see if required commands exist
-       my @required_commands = (
-               'initctl',
-       );
-       
-       my @missing_commands;
-       for my $command (@required_commands) {
-               if (!$self->command_exists($command)) {
-                       push @missing_commands, $command;
-               }
-       }
-       
-       if (@missing_commands) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to initialize Upstart Linux 
init module to control $computer_node_name, the following commands are not 
available:\n" . join("\n", @missing_commands));
-               return;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "Upstart Linux init module 
successfully initialized to control $computer_node_name");
-               return 1;
-       }
-       
-       notify($ERRORS{'DEBUG'}, 0, "Upstart Linux init module successfully 
initialized to control $computer_node_name");
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 service_exists
-
- Parameters  : $service_name
- Returns     : boolean
- Description : 
-
-=cut
-
-sub service_exists {
+sub get_service_names {
        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");
@@ -140,27 +120,30 @@ sub service_exists {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       my $service_name = shift;
-       if (!$service_name) {
-               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
-               return;
-       }
-       $service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || 
$service_name;
+       my $service_info = {};
        
        my $command = "initctl list";
        my ($exit_status, $output) = $self->execute($command, 0);
        if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service exists on $computer_node_name");
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
list Upstart services on $computer_node_name");
                return;
        }
-       elsif (grep(/^$service_name[\s\t]/, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists on 
$computer_node_name");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
-               return 0;
+       
+       # Format of initctl list output lines:
+       # splash-manager stop/waiting
+       # Add to hash then extract keys to remove duplicates
+       my %service_name_hash;
+       my %service_name_mappings_reversed = reverse %$SERVICE_NAME_MAPPINGS;
+       for my $line (@$output) {
+               my ($service_name) = $line =~ /^([^\s\t]+)/;
+               $service_name_hash{$service_name} = 1 if $service_name;
+               if (my $service_name_mapping = 
$service_name_mappings_reversed{$service_name}) {
+                       $service_name_hash{$service_name_mapping} = 1;
+               }
        }
+       my @service_names = sort(keys %service_name_hash);
+       notify($ERRORS{'DEBUG'}, 0, "retrieved Upstart service names from 
$computer_node_name: " . join(", ", @service_names));
+       return @service_names;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -169,8 +152,8 @@ sub service_exists {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : Calls 'chkconfig --del' to delete the service specified by the
-               argument. Deletes the service file from /etc/rc.d/init.d/.
+ Description : Stops the service if it is running. Deletes the
+               '/etc/init/<$service_name>.conf' file.
 
 =cut
 
@@ -206,7 +189,7 @@ sub delete_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'initctl start <$service_name>' to start the service.
 
 =cut
 
@@ -259,7 +242,7 @@ sub start_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'initctl stop <$service_name>' to stop the service.
 
 =cut
 
@@ -312,7 +295,7 @@ sub stop_service {
 
  Parameters  : $service_name
  Returns     : boolean
- Description : 
+ Description : Calls 'initctl restart <$service_name>' to restart the service.
 
 =cut
 
@@ -364,7 +347,9 @@ sub restart_service {
 
  Parameters  : none
  Returns     : boolean
- Description :
+ Description : Generates and configures '/etc/init/ext_ssh.conf' based off of
+               the existing '/etc/init/ext_ssh.conf' file. Adds the ext_ssh
+               service to the computer.
 
 =cut
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm?rev=1409301&r1=1409300&r2=1409301&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm Wed Nov 14 
19:09:00 2012
@@ -26,8 +26,8 @@ VCL::Module::OS::Linux::init::systemd.pm
 
  This module provides VCL support for the systemd Linux init daemon used in
  distributions such as:
- Fedora 15+
- openSUSE 12.1+
+    Fedora 15+
+    openSUSE 12.1+
 
 =cut
 
@@ -36,7 +36,7 @@ package VCL::Module::OS::Linux::init::sy
 
 # Specify the lib path using FindBin
 use FindBin;
-use lib "$FindBin::Bin/../../../..";
+use lib "$FindBin::Bin/../../../../..";
 
 # Configure inheritance
 use base qw(VCL::Module::OS::Linux);
@@ -55,63 +55,51 @@ use VCL::utils;
 
 ##############################################################################
 
-=head1 OBJECT METHODS
+=head1 CLASS VARIABLES
 
 =cut
 
-#/////////////////////////////////////////////////////////////////////////////
+=head2 $INIT_DAEMON_ORDER
 
-=head2 initialize
+ Data type   : integer
+ Value       : 20
+ Description : Determines the order in which Linux init daemon modules are 
used.
+               Lower values are used first.
 
- Parameters  : none
- Returns     : boolean
- Description : 
+=cut
+
+our $INIT_DAEMON_ORDER = 20;
+
+=head2 @REQUIRED_COMMANDS
+
+ Data type   : array
+ Values      : systemctl
+ Description : List of commands used within this module to configure and 
control
+               systemd services. This module will not be used if any of these
+               commands are unavailable on the computer.
 
 =cut
 
-sub initialize {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $computer_node_name = $self->data->get_computer_node_name();
-       
-       # Check to see if required commands exist
-       my @required_commands = (
-               'systemctl',
-       );
-       
-       my @missing_commands;
-       for my $command (@required_commands) {
-               if (!$self->command_exists($command)) {
-                       push @missing_commands, $command;
-               }
-       }
-       
-       if (@missing_commands) {
-               notify($ERRORS{'DEBUG'}, 0, "unable to initialize systemd Linux 
init module to control $computer_node_name, the following commands are not 
available:\n" . join("\n", @missing_commands));
-               return;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "systemd Linux init module 
successfully initialized to control $computer_node_name");
-               return 1;
-       }
-}
+our @REQUIRED_COMMANDS = ('systemctl');
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 service_exists
+=head2 get_service_names
 
- Parameters  : $service_name
- Returns     : boolean
- Description : Calls 'systemctl list-unit-files' the output is parsed to
-               determine if the service exists.
+ Parameters  : none
+ Returns     : array
+ Description : Calls 'systemctl list-unit-files' to retrieve the list of
+               services controlled by systemd on the computer.
 
 =cut
 
-sub service_exists {
+sub get_service_names {
        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");
@@ -120,30 +108,24 @@ sub service_exists {
        
        my $computer_node_name   = $self->data->get_computer_node_name();
        
-       my $service_name = shift;
-       if (!$service_name) {
-               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
-               return;
-       }
        my $command = "systemctl --no-pager list-unit-files";
        my ($exit_status, $output) = $self->execute($command, 0);
        if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service exists on $computer_node_name");
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
retrieve systemd service names on $computer_node_name");
                return;
        }
        
-       if (grep(/^$service_name\.service/, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists on 
$computer_node_name");
-               return 1;
-       }
-       elsif (grep(/\.service/, @$output)) {
-               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
-               return 0;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service exists, exit status: $exit_status, output:\n" . 
join("\n", @$output));
-               return;
+       # Format of systemctl list output lines:
+       # ssyslog.target                          static
+       # Add to hash then extract keys to remove duplicates
+       my %service_name_hash;
+       for my $line (@$output) {
+               my ($service_name) = $line =~ /^(.+)\.service/;
+               $service_name_hash{$service_name} = 1 if $service_name;
        }
+       my @service_names = sort(keys %service_name_hash);
+       notify($ERRORS{'DEBUG'}, 0, "retrieved systemd service names from 
$computer_node_name: " . join(", ", @service_names));
+       return @service_names;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -202,7 +184,7 @@ sub enable_service {
  Parameters  : $service_name
  Returns     : boolean
  Description : Calls 'systemctl disable' to disable the service specified by 
the
-                                       argument.
+               argument.
 
 =cut
 


Reply via email to