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