You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2012/11/14 20:09:01 UTC

svn commit: r1409301 - in /vcl/trunk/managementnode/lib/VCL/Module/OS: Linux.pm Linux/init/SysV.pm Linux/init/Upstart.pm Linux/init/systemd.pm

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