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/12 21:44:33 UTC

svn commit: r1408451 [3/3] - in /vcl/trunk/managementnode/lib/VCL/Module: OS.pm OS/Linux.pm OS/Linux/Ubuntu.pm OS/Linux/init/ OS/Linux/init/SysV.pm OS/Linux/init/Upstart.pm OS/Linux/init/systemd.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm?rev=1408451&r1=1408450&r2=1408451&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm Mon Nov 12 20:44:32 2012
@@ -22,10 +22,6 @@
 
 VCL::Module::OS::Ubuntu.pm - VCL module to support Ubuntu operating systems
 
-=head1 SYNOPSIS
-
- Needs to be written
-
 =head1 DESCRIPTION
 
  This module provides VCL support for Ubuntu operating systems.
@@ -63,6 +59,14 @@ use VCL::utils;
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 clean_iptables
+
+ Parameters  : 
+ Returns     : 
+ Description : 
+
+=cut
+
 sub clean_iptables {
 	my $self = shift;
    if (ref($self) !~ /ubuntu/i) {
@@ -71,15 +75,15 @@ sub clean_iptables {
    }
 
 	# Check to see if this distro has iptables
-   # If not return 1 so it does not fail
-   if (!($self->file_exists("/sbin/iptables"))) {
-      notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+   if (!$self->service_exists("iptables")) {
+      notify($ERRORS{'WARNING'}, 0, "iptables service does not exist on this OS");
       return 1;
    }
+	
 
    my $computer_node_name = $self->data->get_computer_node_name();
-   my $reservation_id                  = $self->data->get_reservation_id();
-   my $management_node_keys  = $self->data->get_management_node_keys();
+   my $reservation_id = $self->data->get_reservation_id();
+   my $management_node_keys = $self->data->get_management_node_keys();
 	
 
    # Retrieve the iptables file to work on locally 
@@ -128,11 +132,13 @@ sub clean_iptables {
 
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 clean_known_files
 
  Parameters  : 
- Returns     : 1
- Description : Removes or overwrites known files that are not excluded.
+ Returns     : 
+ Description : 
 
 =cut
 
@@ -188,75 +194,50 @@ sub clean_known_files {
 
 =head2 enable_dhcp
 
- Parameters  : 
+ Parameters  : $interface_name (optional)
  Returns     : boolean
- Description : Overwrites interfaces file setting both to dhcp
+ Description : Configures /etc/network/interfaces file so that DHCP is enabled
+               for the interface. If no argument is supplied, DHCP is enabled
+               for the public and private interfaces.
 
 =cut
 
-#/////////////////////////////////////////////////////////////////////////////
-
 sub enable_dhcp {
 	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;
    }
-
-	my $request_id               = $self->data->get_request_id();
-   my $computer_node_name = $self->data->get_computer_node_name();
-	my $management_node_keys     = $self->data->get_management_node_keys();
-   
-   my $interface_name_argument = shift;
-   my @interface_names;
-  # if (!$interface_name_argument) {
-  #    push(@interface_names, $self->get_private_interface_name());
-  #    push(@interface_names, $self->get_public_interface_name());
-  # }
-  # elsif ($interface_name_argument =~ /private/i) {
-  #    push(@interface_names, $self->get_private_interface_name());
-  # }
-  # elsif ($interface_name_argument =~ /public/i) {
-  #    push(@interface_names, $self->get_public_interface_name());
-  # }
-  # else {
-  #    push(@interface_names, $interface_name_argument);
-  # }
-
-	my @array2print;
-	
-	push(@array2print, '# This file describes the network interfaces available on your system'. "\n");
-	push(@array2print, '# and how to activate them. For more information, see interfaces(5).'. "\n");
-	push(@array2print, "\n");
-	push(@array2print, '# The loopback network interface'. "\n");
-	push(@array2print, 'auto lo'. "\n");
-	push(@array2print, 'iface lo inet loopback'. "\n");
-	push(@array2print, "\n");
-	push(@array2print, '# The primary network interface'. "\n");
-	push(@array2print, 'auto eth0 eth1'. "\n");
-	push(@array2print, 'iface eth0 inet dhcp'. "\n");
-	push(@array2print, 'iface eth1 inet dhcp'. "\n");
-
-	   #write to tmpfile
-   my $tmpfile = "/tmp/$request_id.interfaces";
-   if (open(TMP, ">$tmpfile")) {
-      print TMP @array2print;
-      close(TMP);
-   }
-   else {
-      notify($ERRORS{'OK'}, 0, "could not write $tmpfile $!");
-      return 0;
-   }
-
-   #copy to node
-   if (run_scp_command($tmpfile, "$computer_node_name:/etc/network/interfaces", $management_node_keys)) {
-   }
-   else{
-		unlink($tmpfile);
-      return 0;
-   }
 	
-	unlink($tmpfile);
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $interface_name_argument = shift;
+	my @interface_names;
+	if (!$interface_name_argument) {
+		push(@interface_names, $self->get_private_interface_name());
+		push(@interface_names, $self->get_public_interface_name());
+	}
+	elsif ($interface_name_argument =~ /private/i) {
+		push(@interface_names, $self->get_private_interface_name());
+	}
+	elsif ($interface_name_argument =~ /public/i) {
+		push(@interface_names, $self->get_public_interface_name());
+	}
+	else {
+		push(@interface_names, $interface_name_argument);
+	}
+	
+	my $interfaces_file_path = '/etc/network/interfaces';
+	for my $interface_name (@interface_names) {
+		# Remove existing lines from the interfaces file which contain the interface name
+		$self->remove_lines_from_file($interfaces_file_path, $interface_name) || return;
+		
+		# Add line to end of interfaces file
+		my $interface_string = "auto $interface_name\n";
+		$interface_string .= "iface $interface_name inet dhcp\n";
+		$self->append_text_file($interfaces_file_path, $interface_string) || return;
+	}
+	
 	return 1;
 }
 
@@ -318,310 +299,6 @@ sub changepasswd {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 generate_rc_local
-
- Parameters  : none
- Returns     : boolean
- Description : Generate a rc.local file locally, copy to node and make executable.
-
-=cut
-
-sub generate_rc_local {
-        my $self = shift;
-        if (ref($self) !~ /linux/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-                return 0;
-        }    
-   
-   my $request_id               = $self->data->get_request_id();
-   my $management_node_keys     = $self->data->get_management_node_keys();
-   my $computer_short_name      = $self->data->get_computer_short_name();
-   my $computer_node_name       = $self->data->get_computer_node_name();
-   
-   # Determine if /etc/rc.local is a symlink or not
-   my $command = "file /etc/rc.local";
-   my $symlink = 0; 
-   my $rc_local_path;
-   
-   my ($echo_exit_status, $echo_output) = $self->execute($command, 1);
-   if (!defined($echo_output)) {
-        notify($ERRORS{'WARNING'}, 0, "failed to run command to check file of /etc/rc.local");
-   }
-   elsif (grep(/symbolic/, @$echo_output)) {
-        notify($ERRORS{'OK'}, 0, "confirmed /etc/rc.local is symbolic link \n" . join("\n", @$echo_output));
-        $symlink = 1; 
-   }
-   
-   if(!$symlink) {
-      #my $symlink_command = "mv /etc/rc.local /etc/_orig.rc.local ; ln -s /etc/rc.d/rc.local /etc/rc.local";
-      #my ($sym_exit_status, $sym_output) = $self->execute($symlink_command, 1);
-      #if (!defined($sym_output)) {
-      #  notify($ERRORS{'WARNING'}, 0, "failed to run symlink_command $symlink_command on node $computer_node_name");
-      #}   
-      #else {
-      #   notify($ERRORS{'OK'}, 0, "successfully ran $symlink_command on $computer_node_name");
-      #}   
-   
-      $rc_local_path = "/etc/rc.local";
-     
-   }
-   else {
-      $rc_local_path = "/etc/rc.d/rc.local";
-   }
-
-   my @array2print;
-	push(@array2print, '#!/bin/sh' . "\n");
-   push(@array2print, '#' . "\n");
-   push(@array2print, '# This script will be executed after all the other init scripts.' . "\n");
-   push(@array2print, '#' . "\n");
-   push(@array2print, '# WARNING --- VCL IMAGE CREATORS --- WARNING' . "\n");
-   push(@array2print, '#' . "\n");
-   push(@array2print, '# This file will get overwritten during image capture. Any customizations' . "\n");
-   push(@array2print, '# should be put into /etc/init.d/vcl_post_reserve or /etc/init.d/vcl_post_load' . "\n");
-   push(@array2print, '# Note these files do not exist by default.' . "\n");
-   push(@array2print, "\n");
-   push(@array2print, "#Use the /root/.vclcontrol/vcl_exclude_list to prevent vcld from updating this file.");
-   push(@array2print, "\n");
-   push(@array2print, 'touch /var/lock/subsys/local' . "\n");
-   push(@array2print, "\n");
-   push(@array2print, 'IP0=$(ifconfig eth0 | grep inet | awk \'{print $2}\' | awk -F: \'{print $2}\')' . "\n");
-   push(@array2print, 'IP1=$(ifconfig eth1 | grep inet | awk \'{print $2}\' | awk -F: \'{print $2}\')' . "\n");
-   push(@array2print, 'sed -i -e \'/.*AllowUsers .*$/d\' /etc/ssh/sshd_config' . "\n");
-   push(@array2print, 'sed -i -e \'/.*ListenAddress .*/d\' /etc/ssh/sshd_config' . "\n");
-   push(@array2print, 'sed -i -e \'/.*ListenAddress .*/d\' /etc/ssh/external_sshd_config' . "\n");
-   push(@array2print, 'echo "AllowUsers root" >> /etc/ssh/sshd_config' . "\n");
-   push(@array2print, 'echo "ListenAddress $IP0" >> /etc/ssh/sshd_config' . "\n");
-   push(@array2print, 'echo "ListenAddress $IP1" >> /etc/ssh/external_sshd_config' . "\n");
-   push(@array2print, 'service ext_sshd stop' . "\n");
-   push(@array2print, 'service ssh stop' . "\n");
-   push(@array2print, 'sleep 2' . "\n");
-   push(@array2print, 'service ssh start' . "\n");
-   push(@array2print, 'service ext_sshd start' . "\n");
-
-   #write to tmpfile
-   my $tmpfile = "/tmp/$request_id.rc.local";
-   if (open(TMP, ">$tmpfile")) {
-      print TMP @array2print;
-      close(TMP);
-   }
-   else {
-      #print "could not write $tmpfile $!\n";
-      notify($ERRORS{'OK'}, 0, "could not write $tmpfile $!");
-      return 0;
-   }
-   #copy to node
-   if (run_scp_command($tmpfile, "$computer_node_name:$rc_local_path", $management_node_keys)) {
-   }
-   else{
-      return 0;
-   }
-
-   # Assemble the command
-   my $chmod_command = "chmod +rx $rc_local_path";
-
-   # Execute the command
-   my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, $chmod_command, '', '', 1);
-   if (defined($exit_status) && $exit_status == 0) {
-      notify($ERRORS{'OK'}, 0, "executed $chmod_command, exit status: $exit_status");
-   }
-   elsif (defined($exit_status)) {
-      notify($ERRORS{'WARNING'}, 0, "setting rx on $rc_local_path returned a non-zero exit status: $exit_status");
-      return;
-   }
-   else {
-      notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to execute $chmod_command");
-      return 0;
-   }
-
-   unlink($tmpfile);
-
-   # If systemd managed; confirm rc-local.service is enabled
-   if($self->file_exists("/bin/systemctl") ) {
-      my $systemctl_command = "systemctl enable rc-local.service";
-      my ($systemctl_exit_status, $systemctl_output) = $self->execute($systemctl_command, 1);
-         if (!defined($systemctl_output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to run $systemctl_command on node $computer_node_name");
-         }
-         else {
-            notify($ERRORS{'OK'}, 0, "successfully ran $systemctl_command on $computer_node_name \n" . join("\n", @$systemctl_output));
-            #Start rc-local.service
-            if($self->start_service("rc-local")) {
-               notify($ERRORS{'OK'}, 0, "started rc-local.service on $computer_node_name");
-            }
-            else {
-               notify($ERRORS{'OK'}, 0, "failed to start rc-local.service on $computer_node_name");
-               return 0
-            }
-         }
-   }
-   else {
-      #Re-run rc.local
-      my ($rclocal_exit_status, $rclocal_output) = $self->execute("$rc_local_path");
-      if (!defined($rclocal_exit_status)) {
-          notify($ERRORS{'WARNING'}, 0, "failed to run $rc_local_path on node $computer_node_name");
-      }
-      else {
-         notify($ERRORS{'OK'}, 0, "successfully ran $rc_local_path");
-      }
-
-   }
-
-   return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 generate_ext_sshd_sysVinit
-
- Parameters  : none
- Returns     : boolean
- Description :	Creates /etc/init.d/ext_ssh start script and upstart conf file /etc/init/ext_ssh.conf
-
-=cut
-
-sub generate_ext_sshd_sysVinit {
-   my $self = shift;
-   if (ref($self) !~ /ubuntu/i) {
-      notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-      return 0;
-   }  
-   
-   my $request_id               = $self->data->get_request_id();
-   my $management_node_keys     = $self->data->get_management_node_keys();
-   my $computer_short_name      = $self->data->get_computer_short_name();
-   my $computer_node_name       = $self->data->get_computer_node_name();
-   
-   #copy /etc/init.d/ssh to local /tmp for processing
-   my $tmpfile = "/tmp/$request_id.ext_sshd";
-   if (run_scp_command("$computer_node_name:/etc/init.d/ssh", $tmpfile, $management_node_keys)) {
-      notify($ERRORS{'DEBUG'}, 0, "copied sshd init script from $computer_node_name for local processing");
-   }  
-   else{
-      notify($ERRORS{'WARNING'}, 0, "failed to copied ssh init script from $computer_node_name for local processing");
-      return 0;
-   }
-
-   my @ext_ssh_init = read_file_to_array($tmpfile);
-
-   notify($ERRORS{'DEBUG'}, 0, "read file $tmpfile into array ");
-
-   foreach my $l (@ext_ssh_init) {
-		#Search and replace sshd.pid
-		$l =~ s/\/sshd.pid/\/ext_sshd.pid/g;
-		$l =~ s/\/etc\/init\/ssh.conf/\/etc\/init\/ext_sshd.conf/g;
-		$l =~ s/upstart-job\ ssh/upstart-job\ ext_sshd/g;
-		$l =~ s/\/etc\/default\/ssh/\/etc\/default\/ext_sshd/g;
-	
-   }
-
-   #clear temp file
-   unlink($tmpfile);
-
-   #write_array to file
-   if(open(FILE, ">$tmpfile")){
-      print FILE @ext_ssh_init;
-      close(FILE);
-   }
-
-   #copy temp file to node
-   if (run_scp_command($tmpfile, "$computer_node_name:/etc/init.d/ext_sshd", $management_node_keys)) {
-      notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to $computer_node_name:/etc/init.d/ext_sshd");
-      if(run_ssh_command($computer_node_name, $management_node_keys, "chmod +rx /etc/init.d/ext_sshd", '', '', 1)){
-         notify($ERRORS{'DEBUG'}, 0, "setting  $computer_node_name:/etc/init.d/ext_sshd executable");
-      }
-   }
-   else{
-      notify($ERRORS{'WARNING'}, 0, "failed to copied $tmpfile to $computer_node_name:/etc/init.d/ext_sshd");
-   	#delete local tmpfile
-   	unlink($tmpfile);
-      return 0;
-   }
-
-   #delete local tmpfile
-   unlink($tmpfile);
-
-	#Create /etc/default/ext_ssh
-
-   my @default_ext_ssh;
-	push(@default_ext_ssh, '# Default settings for openssh-server. This file is sourced by /bin/sh from');
-	push(@default_ext_ssh, "\n");
-	push(@default_ext_ssh, '# /etc/init.d/ext_sshd.');
-	push(@default_ext_ssh, "\n\n");
-	push(@default_ext_ssh, '# Options to pass to ext_sshd');
-	push(@default_ext_ssh, "\n");
-	push(@default_ext_ssh, 'SSHD_OPTS="-f /etc/ssh/external_sshd_config"');
-	push(@default_ext_ssh, "\n");
-	
-   #write_array to file
-   if(open(FILE, ">$tmpfile")){
-      print FILE @default_ext_ssh;
-      close(FILE);
-   }
-	
-	if (run_scp_command($tmpfile, "$computer_node_name:/etc/default/ext_sshd", $management_node_keys)) {
-      notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to $computer_node_name:/etc/default/ext_sshd");
-      if(run_ssh_command($computer_node_name, $management_node_keys, "chmod +rw /etc/default/ext_sshd", '', '', 1)){
-      }
-   }
-   else{
-      notify($ERRORS{'WARNING'}, 0, "failed to copied $tmpfile to $computer_node_name:/etc/default/ext_sshd");
-   	#delete local tmpfile
-   	unlink($tmpfile);
-      return 0;
-   }	
-
-	
-   #delete local tmpfile
-   unlink($tmpfile);
-		
-	#Create /etc/init/ext_ssh.conf
-   $tmpfile = "/tmp/$request_id.ext_ssh.conf";
-   if (run_scp_command("$computer_node_name:/etc/init/ssh.conf", $tmpfile, $management_node_keys)) {
-      notify($ERRORS{'DEBUG'}, 0, "copied ssh.conf init file from $computer_node_name for local processing");
-   }
-   else{
-      notify($ERRORS{'WARNING'}, 0, "failed to copied ssh.conf init file from $computer_node_name for local processing");
-   	#delete local tmpfile
-   	unlink($tmpfile);
-      return 0;
-   }
-
-   my @ext_ssh_conf_init = read_file_to_array($tmpfile);
-
-	foreach my $l (@ext_ssh_conf_init) {
-		$l =~ s/OpenSSH\ server"/External\ OpenSSH\ server"/g;
-		$l =~ s/\/var\/run\/sshd/\/var\/run\/ext_sshd/g;
-		$l =~ s/exec\ \/usr\/sbin\/sshd\ -D/exec\ \/usr\/sbin\/sshd\ -D\ -f\ \/etc\/ssh\/external_sshd_config/g;
-	}
-
-	#write_array to file
-   if(open(FILE, ">$tmpfile")){
-      print FILE @ext_ssh_conf_init;
-      close(FILE);
-   }
-
-   if (run_scp_command($tmpfile, "$computer_node_name:/etc/init/ext_sshd.conf", $management_node_keys)) {
-      notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to $computer_node_name:/etc/init/ext_sshd.conf");
-      if(run_ssh_command($computer_node_name, $management_node_keys, "chmod +rw /etc/init/ext_sshd.conf", '', '', 1)){
-      }
-   }
-   else{
-      notify($ERRORS{'WARNING'}, 0, "failed to copied $tmpfile to $computer_node_name:/etc/init/ext_sshd.conf");
-   	#delete local tmpfile
-   	unlink($tmpfile);
-      return 0;
-   }
-
-
-   #delete local tmpfile
-   unlink($tmpfile);
-	
-   return 1;
-
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 get_network_configuration
 
  Parameters  : 
@@ -717,7 +394,6 @@ sub get_network_configuration {
 		
 }
 
-
 #/////////////////////////////////////////////////////////////////////////////
 
 =head2 enable_firewall_port
@@ -735,9 +411,9 @@ sub enable_firewall_port {
       return;
    }
 
-	   # If not return 1 so it does not fail
-   if (!($self->service_exists("ufw"))) {
-      notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+	# Check to see if this distro has iptables
+   if (!$self->service_exists("iptables")) {
+      notify($ERRORS{'WARNING'}, 0, "iptables service does not exist on this OS");
       return 1;
    }
 
@@ -760,7 +436,6 @@ sub enable_firewall_port {
 
 }
 
-
 #/////////////////////////////////////////////////////////////////////////////
 
 =head2 disable_firewall_port
@@ -779,9 +454,8 @@ sub disable_firewall_port {
    }
 
    # Check to see if this distro has iptables
-   # If not return 1 so it does not fail
-   if (!($self->service_exists("ufw"))) {
-      notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+   if (!$self->service_exists("iptables")) {
+      notify($ERRORS{'WARNING'}, 0, "iptables service does not exist on this OS");
       return 1;
    }
 
@@ -807,6 +481,8 @@ sub disable_firewall_port {
 
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_firewall_configuration
 
  Parameters  : none
@@ -823,12 +499,6 @@ sub disable_firewall_port {
                     }
                   },
                   "TCP" => {
-                    22 => {
-                      "interface_names" => [
-                        "Local Area Connection 3"
-                      ],
-                      "name" => "sshd"
-                    },
                     3389 => {
                       "name" => "Remote Desktop",
                       "scope" => "192.168.53.54/255.255.255.255"
@@ -846,11 +516,10 @@ sub get_firewall_configuration {
    my $computer_node_name = $self->data->get_computer_node_name();   
    my $firewall_configuration = {};
 
-   # Check to see if this distro has ufw
-   # If not return 1 so it does not fail
-   if (!($self->service_exists("ufw"))) {
-      notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
-      return 1;
+   # Check to see if this distro has iptables
+   if (!$self->service_exists("iptables")) {
+      notify($ERRORS{'WARNING'}, 0, "iptables service does not exist on this OS");
+      return {};
    }
    
    my $port_command = "ufw status numbered";
@@ -1101,24 +770,13 @@ sub set_static_public_address {
       notify($ERRORS{'DEBUG'}, 0, "added default route to $default_gateway on public interface $interface_name on $computer_name, output:\n" . format_data($route_add_output));
    }
 
-   # Remove existing ListenAddress lines using sed
-   # Add ListenAddress line to the end of the file
-   my $ext_sshd_command;
-   $ext_sshd_command .= "sed -i -e \"/ListenAddress .*/d \" /etc/ssh/external_sshd_config 2>&1";
-   $ext_sshd_command .= " && echo \"ListenAddress $ip_address\" >> /etc/ssh/external_sshd_config";
-   $ext_sshd_command .= " && tail -n1 /etc/ssh/external_sshd_config";
-   my ($ext_sshd_exit_status, $ext_sshd_output) = $self->execute($ext_sshd_command);
-   if (!defined($ext_sshd_output)) {
-      notify($ERRORS{'WARNING'}, 0, "failed to run command to update ListenAddress line in /etc/ssh/external_sshd_config on $computer_name: '$ext_sshd_command'");
-      return;
-   }
-   elsif ($ext_sshd_exit_status) {
-      notify($ERRORS{'WARNING'}, 0, "failed to update ListenAddress line in /etc/ssh/external_sshd_config on $computer_name, exit status: $ext_sshd_exit_status\ncommand:\n'$ext_sshd_command'\noutput:\n" . join("\n", @$ext_sshd_output));
-      return;
-   }
-   else {
-      notify($ERRORS{'DEBUG'}, 0, "updated ListenAddress line in /etc/ssh/external_sshd_config on $computer_name, output:\n" . join("\n", @$ext_sshd_output));
-   }
+   my $ext_sshd_config_file_path = '/etc/ssh/external_sshd_config';
+	
+	# Remove existing ListenAddress lines from external_sshd_config
+	$self->remove_lines_from_file($ext_sshd_config_file_path, 'ListenAddress') || return;
+	
+	# Add ListenAddress line to the end of the file
+	$self->append_text_file($ext_sshd_config_file_path, "ListenAddress $ip_address\n") || return;
 
    # Update resolv.conf if DNS server address is configured for the management node
    my $resolv_conf_path = "/etc/resolv.conf";
@@ -1234,7 +892,8 @@ sub activate_interfaces {
 	return 1;
 
 }
-	
+
+#/////////////////////////////////////////////////////////////////////////////
 1;
 __END__
 

Added: 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=1408451&view=auto
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm (added)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm Mon Nov 12 20:44:32 2012
@@ -0,0 +1,536 @@
+#!/usr/bin/perl -w
+###############################################################################
+# $Id$
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###############################################################################
+
+=head1 NAME
+
+VCL::Module::OS::Linux::init::SysV.pm
+
+=head1 DESCRIPTION
+
+ 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
+
+=cut
+
+##############################################################################
+package VCL::Module::OS::Linux::init::SysV;
+
+# Specify the lib path using FindBin
+use FindBin;
+print "$FindBin::Bin/../../../.." . "\n\n";
+exit;
+
+use lib "$FindBin::Bin/../../../..";
+
+# Configure inheritance
+use base qw(VCL::Module::OS::Linux);
+
+# Specify the version of this module
+our $VERSION = '2.3';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+
+use VCL::utils;
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters  : none
+ Returns     : true
+ Description : 
+
+=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;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_exists
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub service_exists {
+	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 $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");
+		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;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 enable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub enable_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Enable the service
+	my $command = "chkconfig $service_name on";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to enable '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service httpdx: No such file or directory'
+		notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(failed|warn|error)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to enable '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "enabled '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub disable_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Disable the service
+	my $command = "chkconfig $service_name off";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to disable '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service httpdx: No such file or directory'
+		notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(failed|warn|error)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to disable '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "disabled '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_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/.
+
+=cut
+
+sub add_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 argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Add the service
+	my $command = "chkconfig --add $service_name";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to add '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(error|No such file)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to add '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "added '$service_name' service on $computer_node_name");
+		return 1;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_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/.
+
+=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 argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Delete the service
+	my $command = "chkconfig --del $service_name";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to delete '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service xxx: No such file or directory'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not exist on $computer_node_name");
+	}
+	elsif ($exit_status ne '0') {
+		notify($ERRORS{'WARNING'}, 0, "failed to delete '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+	
+	# Delete the service configuration file
+	my $service_file_path = "/etc/rc.d/init.d/$service_name";
+	if (!$self->delete_file($service_file_path)) {
+		return;
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "deleted '$service_name' service on $computer_node_name");
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 start_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub start_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 argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "service $service_name start";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to start '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service xxx: No such file or directory'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not exist on $computer_node_name");
+	}
+	elsif (grep(/Starting $service_name:.*FAIL/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "started '$service_name' service on $computer_node_name");
+		return 1;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 stop_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub stop_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 argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "service $service_name stop";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to stop '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service xxx: No such file or directory'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return 1;
+	}
+	elsif (grep(/Stopping $service_name:.*FAIL/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to stop '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "stopped '$service_name' service on $computer_node_name, output:\n" . join("\n", @$output));
+		return 1;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 restart_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub restart_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 argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "service $service_name restart";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to restart '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/(error reading information|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'error reading information on service xxx: No such file or directory'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not exist on $computer_node_name");
+	}
+	elsif (grep(/Starting $service_name:.*FAIL/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to restart '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "restarted '$service_name' service on $computer_node_name, output:\n" . join("\n", @$output));
+		return 1;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_ext_sshd_service
+
+ Parameters  : none
+ Returns     : boolean
+ Description :
+
+=cut
+
+sub add_ext_sshd_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 0;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $sshd_service_file_path     = '/etc/rc.d/init.d/sshd';
+	my $ext_sshd_service_file_path = '/etc/rc.d/init.d/ext_sshd';
+	my $ext_sshd_config_file_path = '/etc/ssh/external_sshd_config';
+	
+	# Get the contents of the sshd service startup file already on the computer
+	my @sshd_service_file_contents = $self->get_file_contents($sshd_service_file_path);
+	if (!@sshd_service_file_contents) {
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve contents of $sshd_service_file_path from $computer_node_name");
+		return;
+	}
+	
+	my $ext_sshd_service_file_contents = join("\n", @sshd_service_file_contents);
+	
+	# Replace: OpenSSH --> externalOpenSSH
+	$ext_sshd_service_file_contents =~ s|( OpenSSH)| external$1|g;
+	
+	# Replace: openssh-daemon --> external-openssh-daemon
+	$ext_sshd_service_file_contents =~ s| (openssh-daemon)| external-$1|g;
+	
+	# Replace: sshd --> ext_sshd, exceptions:
+	# /bin/sshd
+	# /sshd_config
+	$ext_sshd_service_file_contents =~ s|(?<!bin/)sshd(?!_config)|ext_sshd|g;
+	
+	# Replace: sshd_config --> external_sshd_config
+	$ext_sshd_service_file_contents =~ s|(?:ext_)?(sshd_config)|external_$1|g;
+	
+	# Add config file path argument to '$SSHD $OPTIONS'
+	$ext_sshd_service_file_contents =~ s|(\$SSHD)\s+(\$OPTIONS)|$1 -f $ext_sshd_config_file_path $2|g;
+	
+	# Replace 'pidfileofproc $SSHD' and 'killproc $SSHD'
+	$ext_sshd_service_file_contents =~ s/(pidfileofproc|killproc)\s+\$SSHD/$1 \$prog/g;
+	
+	if (!$self->create_text_file($ext_sshd_service_file_path, $ext_sshd_service_file_contents)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create ext_sshd service file on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	if (!$self->set_file_permissions($ext_sshd_service_file_path, '755')) {
+		notify($ERRORS{'WARNING'}, 0, "failed to set permissions on ext_sshd service file to 755 on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	# Add the service
+	return unless $self->add_service('ext_sshd');
+	
+	return $self->enable_service('ext_sshd');
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+1;
+__END__
+
+=head1 SEE ALSO
+
+L<http://cwiki.apache.org/VCL/>
+
+=cut

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/SysV.pm
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Added: 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=1408451&view=auto
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm (added)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm Mon Nov 12 20:44:32 2012
@@ -0,0 +1,427 @@
+#!/usr/bin/perl -w
+###############################################################################
+# $Id$
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###############################################################################
+
+=head1 NAME
+
+VCL::Module::OS::Linux::init::Upstart.pm
+
+=head1 DESCRIPTION
+
+ This module provides VCL support for the Upstart Linux init daemon used in
+ distributions including:
+ Ubuntu 6.10+
+
+=cut
+
+##############################################################################
+package VCL::Module::OS::Linux::init::Upstart;
+
+# Specify the lib path using FindBin
+use FindBin;
+use lib "$FindBin::Bin/../../../..";
+
+# Configure inheritance
+use base qw(VCL::Module::OS::Linux);
+
+# Specify the version of this module
+our $VERSION = '2.3';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+
+use VCL::utils;
+
+##############################################################################
+
+=head1 CLASS VARIABLES
+
+=cut
+
+=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.
+
+=cut
+
+our $SERVICE_NAME_MAPPINGS = {
+	'sshd' => 'ssh',
+	'ext_sshd' => 'ext_ssh',
+};
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters  : none
+ Returns     : boolean
+ Description : 
+
+=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 {
+	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 $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 $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");
+		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;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_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/.
+
+=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 argument was not supplied");
+		return;
+	}
+	$service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || $service_name;
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	$self->stop_service($service_name) || return;
+	
+	# Delete the service configuration file
+	my $service_file_path = "/etc/init/$service_name.conf";
+	$self->delete_file($service_file_path) || return;
+	
+	notify($ERRORS{'DEBUG'}, 0, "deleted '$service_name' service on $computer_node_name");
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 start_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub start_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 argument was not supplied");
+		return;
+	}
+	$service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || $service_name;
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "initctl start $service_name";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to start '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/Unknown job/i, @$output)) {
+		# Output if the service doesn't exist: 'initctl: Unknown job: <service name>'
+		notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return;
+	}
+	elsif (grep(/already running/i, @$output)) {
+		# Output if the service is already running: 'initctl: Job is already running: <service name>'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' is already running on $computer_node_name");
+		return 1;
+	}
+	elsif (grep(/process \d+/i, @$output)) {
+		# Output if the service was started: '<service name> start/running, process <PID>'
+		notify($ERRORS{'DEBUG'}, 0, "started '$service_name' service on $computer_node_name");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 stop_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub stop_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 argument was not supplied");
+		return;
+	}
+	$service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || $service_name;
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "initctl stop $service_name";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to stop '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/Unknown job/i, @$output)) {
+		# Output if the service doesn't exist: 'initctl: Unknown job: <service name>'
+		notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return 1;
+	}
+	elsif (grep(/Unknown instance/i, @$output)) {
+		# Output if the service is not running: 'initctl: Unknown instance:'
+		notify($ERRORS{'DEBUG'}, 0, "'$service_name' is already stopped on $computer_node_name");
+		return 1;
+	}
+	elsif (grep(/ stop\//i, @$output)) {
+		# Output if the service was stopped: '<service name> stop/waiting'
+		notify($ERRORS{'DEBUG'}, 0, "stopped '$service_name' service on $computer_node_name");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to stop '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 restart_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub restart_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 argument was not supplied");
+		return;
+	}
+	$service_name = $SERVICE_NAME_MAPPINGS->{$service_name} || $service_name;
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "initctl restart $service_name";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to restart '$service_name' service on $computer_node_name");
+		return;
+	}
+	elsif (grep(/Unknown job/i, @$output)) {
+		# Output if the service doesn't exist: 'initctl: Unknown job: <service name>'
+		notify($ERRORS{'WARNING'}, 0, "'$service_name' service does not exist on $computer_node_name");
+		return;
+	}
+	elsif (grep(/Unknown instance/i, @$output)) {
+		# Output if the service is not running: 'initctl: Unknown instance:'
+		return $self->start_service($service_name);
+	}
+	elsif (grep(/process \d+/i, @$output)) {
+		# Output if the service was restarted: '<service name> start/running, process <PID>'
+		notify($ERRORS{'DEBUG'}, 0, "restarted '$service_name' service on $computer_node_name");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to restart '$service_name' service on $computer_node_name, exit status: $exit_status, command: '$command', output:\n" . join("\n", @$output));
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_ext_sshd_service
+
+ Parameters  : none
+ Returns     : boolean
+ Description :
+
+=cut
+
+sub add_ext_sshd_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 0;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $sshd_service_file_path     = '/etc/init/ssh.conf';
+	my $ext_sshd_service_file_path = '/etc/init/ext_ssh.conf';
+	my $ext_sshd_config_file_path = '/etc/ssh/external_sshd_config';
+	
+	# Get the contents of the sshd service startup file already on the computer
+	my @sshd_service_file_contents = $self->get_file_contents($sshd_service_file_path);
+	if (!@sshd_service_file_contents) {
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve contents of $sshd_service_file_path from $computer_node_name");
+		return;
+	}
+	
+	my $ext_sshd_service_file_contents = join("\n", @sshd_service_file_contents);
+	
+	# Replace: OpenSSH --> external OpenSSH
+	$ext_sshd_service_file_contents =~ s|(OpenSSH)|external $1|g;
+	
+	# Replace: ' ssh ' --> ' ext_ssh '
+	$ext_sshd_service_file_contents =~ s| ssh | ext_ssh |g;
+	
+	# Add config file path argument
+	$ext_sshd_service_file_contents =~ s|(exec.*/sshd .*)|$1 -f $ext_sshd_config_file_path|g;
+	
+	# Replace /var/run/sshd --> /var/run/ext_sshd
+	$ext_sshd_service_file_contents =~ s|(/var/run/)sshd|$1ext_sshd|g;
+	
+	if (!$self->create_text_file($ext_sshd_service_file_path, $ext_sshd_service_file_contents)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create ext_sshd service file on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	if (!$self->set_file_permissions($ext_sshd_service_file_path, '644')) {
+		notify($ERRORS{'WARNING'}, 0, "failed to set permissions on ext_sshd service file to 644 on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+1;
+__END__
+
+=head1 SEE ALSO
+
+L<http://cwiki.apache.org/VCL/>
+
+=cut

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/Upstart.pm
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Added: 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=1408451&view=auto
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm (added)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm Mon Nov 12 20:44:32 2012
@@ -0,0 +1,548 @@
+#!/usr/bin/perl -w
+###############################################################################
+# $Id$
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###############################################################################
+
+=head1 NAME
+
+VCL::Module::OS::Linux::init::systemd.pm
+
+=head1 DESCRIPTION
+
+ This module provides VCL support for the systemd Linux init daemon used in
+ distributions such as:
+ Fedora 15+
+ openSUSE 12.1+
+
+=cut
+
+##############################################################################
+package VCL::Module::OS::Linux::init::systemd;
+
+# Specify the lib path using FindBin
+use FindBin;
+use lib "$FindBin::Bin/../../../..";
+
+# Configure inheritance
+use base qw(VCL::Module::OS::Linux);
+
+# Specify the version of this module
+our $VERSION = '2.3';
+
+# Specify the version of Perl to use
+use 5.008000;
+
+use strict;
+use warnings;
+use diagnostics;
+
+use VCL::utils;
+
+##############################################################################
+
+=head1 OBJECT METHODS
+
+=cut
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 initialize
+
+ Parameters  : none
+ Returns     : boolean
+ Description : 
+
+=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;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 service_exists
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl list-unit-files' the output is parsed to
+               determine if the service exists.
+
+=cut
+
+sub service_exists {
+	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 $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");
+		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;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 enable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl enable' to enable the service specified by the
+               argument.
+
+=cut
+
+sub enable_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Enable the service
+	my $command = "systemctl --no-reload enable $service_name.service";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to enable '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(Failed to issue method call|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'Failed to issue method call: No such file or directory'
+		notify($ERRORS{'WARNING'}, 0, "unable to enable '$service_name' service because it does not exist on $computer_node_name");
+		return;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to enable '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "enabled '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 disable_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl disable' to disable the service specified by the
+					argument.
+
+=cut
+
+sub disable_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "systemctl --no-reload disable $service_name.service";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to disable '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(Failed to issue method call|No such file)/i, @$output)) {
+		# Output if the service doesn't exist: 'Failed to issue method call: No such file or directory'
+		notify($ERRORS{'WARNING'}, 0, "unable to disable '$service_name' service because it does not exist on $computer_node_name");
+		return;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to disable '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "disabled '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Disables the service and deletes the service file from
+               /lib/systemd/system/.
+
+=cut
+
+sub delete_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Disable the service before deleting it
+	if ($self->service_exists($service_name)) {
+		$self->stop_service($service_name) || return;
+		$self->disable_service($service_name) || return;
+	}
+	
+	# Delete the service configuration file
+	my $service_file_path = "/lib/systemd/system/$service_name.service";
+	if (!$self->delete_file($service_file_path)) {
+		return;
+	}
+	
+	$self->_daemon_reload();
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 start_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl start' to start the service specified by the
+               argument.
+
+=cut
+
+sub start_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# start the service
+	my $command = "systemctl start $service_name.service";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to start '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(Failed to issue method call|No such file)/i, @$output)) {
+		# Output if the service doesn't exist
+		# Failed to issue method call: Unit httpdx.service failed to load: No such file or directory.
+		notify($ERRORS{'WARNING'}, 0, "unable to start '$service_name' service because it does not exist on $computer_node_name");
+		return;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "started '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 stop_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl stop' to stop the service specified by the
+               argument.
+
+=cut
+
+sub stop_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# stop the service
+	my $command = "systemctl stop $service_name.service";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to stop '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(Failed to issue method call|No such file)/i, @$output)) {
+		# Output if the service doesn't exist
+		# Failed to issue method call: Unit httpdx.service failed to load: No such file or directory.
+		notify($ERRORS{'WARNING'}, 0, "unable to stop '$service_name' service because it does not exist on $computer_node_name");
+		return 1;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to stop '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "stopped '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 restart_service
+
+ Parameters  : $service_name
+ Returns     : boolean
+ Description : Calls 'systemctl restart' to restart the service specified by the
+               argument.
+
+=cut
+
+sub restart_service {
+	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 0;
+	}
+	
+	my $service_name = shift;
+	if (!$service_name) {
+		notify($ERRORS{'WARNING'}, 0, "service name argument was not supplied");
+		return;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	# Restart the service
+	my $command = "systemctl restart $service_name.service";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to restart '$service_name' service on $computer_node_name: $command");
+		return;
+	}
+	elsif (grep(/(Failed to issue method call|No such file)/i, @$output)) {
+		# Output if the service doesn't exist
+		# Failed to issue method call: Unit httpdx.service failed to load: No such file or directory.
+		notify($ERRORS{'WARNING'}, 0, "unable to restart '$service_name' service because it does not exist on $computer_node_name");
+		return;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to restart '$service_name' service on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "restarted '$service_name' service on $computer_node_name");
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_ext_sshd_service
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Constructs the ext_sshd service configuration file:
+               /lib/systemd/system/ext_sshd.service
+
+=cut
+
+sub add_ext_sshd_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 0;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $sshd_service_file_path     = '/lib/systemd/system/sshd.service';
+	my $ext_sshd_service_file_path = '/lib/systemd/system/ext_sshd.service';
+	
+	# Get the contents of the sshd service configuration file already on the computer
+	my @sshd_service_file_contents = $self->get_file_contents($sshd_service_file_path);
+	if (!@sshd_service_file_contents) {
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve contents of $sshd_service_file_path from $computer_node_name");
+		return;
+	}
+	
+	my $ext_sshd_service_file_contents = join("\n", @sshd_service_file_contents);
+	
+	# Replace: OpenSSH --> External OpenSSH
+	$ext_sshd_service_file_contents =~ s|(OpenSSH)|external $1|g;
+	
+	# Replace: sshd --> ext_sshd, exceptions:
+	# /bin/sshd
+	# /sshd_config
+	$ext_sshd_service_file_contents =~ s|(?<!bin/)sshd(?!_config)|ext_sshd|g;
+	
+	# Replace: $OPTIONS --> -f /etc/ssh/external_sshd_config
+	$ext_sshd_service_file_contents =~ s|(ExecStart=.+)\s+\$OPTIONS|$1 -f /etc/ssh/external_sshd_config|g;
+	
+	# Set EnvironmentFile to /dev/null, service won't start if the file doesn't exist
+	$ext_sshd_service_file_contents =~ s|(EnvironmentFile)=.*|$1=/dev/null|g;
+	
+	$ext_sshd_service_file_contents .= "\n";
+	
+	if (!$self->create_text_file($ext_sshd_service_file_path, $ext_sshd_service_file_contents)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create ext_sshd service file on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	if (!$self->set_file_permissions($ext_sshd_service_file_path, '644')) {
+		notify($ERRORS{'WARNING'}, 0, "failed to set permissions of ext_sshd service file to 644 on $computer_node_name: $ext_sshd_service_file_path");
+		return;
+	}
+	
+	$self->_daemon_reload();
+	
+	return $self->enable_service('ext_sshd');
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _daemon_reload
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Runs 'systemctl --system daemon-reload'. This is necessary when
+               adding or deleting services or else systemctl will complain:
+               Warning: Unit file changed on disk, 'systemctl --system daemon-reload' recommended.
+
+=cut
+
+sub _daemon_reload {
+	my $self = shift;
+	if (ref($self) !~ /linux/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+	
+	my $computer_node_name = $self->data->get_computer_node_name();
+	
+	my $command = "systemctl --system daemon-reload";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to reload systemd manager configuration on $computer_node_name: $command");
+		return;
+	}
+	elsif ($exit_status ne 0 || grep(/(failed)/i, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to reload systemd manager configuration on $computer_node_name, exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "reloaded systemd manager configuration on $computer_node_name");
+	}
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+1;
+__END__
+
+=head1 SEE ALSO
+
+L<http://cwiki.apache.org/VCL/>
+
+=cut

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/init/systemd.pm
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id