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 2013/05/31 22:32:43 UTC

svn commit: r1488390 - in /vcl/trunk/managementnode/lib/VCL/Module: OS.pm OS/Linux.pm

Author: arkurth
Date: Fri May 31 20:32:43 2013
New Revision: 1488390

URL: http://svn.apache.org/r1488390
Log:
VCL-698
Updated Linux.pm::delete_user to use 'df -T' to determine if a home directory is on a network drive.

Fixed problems with OS.pm::remove_lines_from_file. It wasn't handling all patterns passed to it.  Simplified the subroutine.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1488390&r1=1488389&r2=1488390&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Fri May 31 20:32:43 2013
@@ -2024,39 +2024,28 @@ sub remove_lines_from_file {
 	
 	my $computer_short_name = $self->data->get_computer_short_name();
 	
-	# Assemble the command, grep the pattern to retrieve the number of times the pattern exists in the file before and after
-	# This is used to verify that the pattern doesn't exist afterwards
-	my $command = "echo -n \"before:\" ; grep -c \"$pattern\" $file_path 2>&1 ; sed -i -e \"/$pattern/d\" $file_path 2>&1 ; echo -n \"after:\" ; grep -c \"$pattern\" $file_path 2>&1";
-	my ($exit_status, $output) = $self->execute($command, 0);
-	if (!defined($output)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to execute command to remove lines containing '$pattern' from '$file_path' on $computer_short_name\ncommand: $command");
-		return;
-	}
-	elsif (grep(/No such file/i, @$output)) {
-		notify($ERRORS{'WARNING'}, 0, "file does NOT exist on $computer_short_name: $file_path");
-		return;
-	}
+	my @lines_removed;
+	my @lines_retained;
 	
-	my $output_string = join("\n", @$output);
-	my ($before_count) = $output_string =~ /before:(\d+)/;
-	my ($after_count) = $output_string =~ /after:(\d+)/;
-
-	if (!defined($before_count) || (!defined($after_count) && $before_count != 0)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to remove lines containing '$pattern' from '$file_path' on $computer_short_name\ncommand: $command\noutput:\n$output_string");
-		return;
-	}
-	elsif ($before_count == 0) {
-		notify($ERRORS{'DEBUG'}, 0, "'$file_path' does not contain any lines matching '$pattern'");
-		return 1;
+	my @lines = $self->get_file_contents($file_path);
+	for my $line (@lines) {
+		if ($line =~ /$pattern/) {
+			push @lines_removed, $line;
+		}
+		else {
+			push @lines_retained, $line;
+		}
 	}
-	elsif ($after_count != 0) {
-		notify($ERRORS{'WARNING'}, 0, "failed to remove lines containing '$pattern' from '$file_path' on $computer_short_name, file still appears to have lines containing the pattern, command: '$command', output:\n$output_string");
-		return;
+	
+	if (@lines_removed) {
+		my $lines_removed_count = scalar(@lines_removed);
+		notify($ERRORS{'DEBUG'}, 0, "removed $lines_removed_count line" . ($lines_removed_count > 1 ? 's' : '') . " from $file_path matching pattern: '$pattern'\n" . join("\n", @lines_removed));
+		$self->create_text_file($file_path, join("\n", @lines_retained)) || return;	
 	}
 	else {
-		notify($ERRORS{'OK'}, 0, "removed $before_count line" . ($before_count > 1 ? 's' : '') . " containing '$pattern' from '$file_path'");
-		return 1;
+		notify($ERRORS{'DEBUG'}, 0, "$file_path does NOT contain any lines matching pattern: '$pattern'");
 	}
+	return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -2297,7 +2286,8 @@ sub execute_new {
 				);
 				
 				if ($ssh) {
-					notify($ERRORS{'DEBUG'}, 0, "created " . ref($ssh) . " object to control $computer_name, options: $ssh_options");
+					
+					notify($ERRORS{'DEBUG'}, 0, "created " . ref($ssh) . " object to control $computer_name, SSH options: $ssh_options");
 				}
 				else {
 					notify($ERRORS{'WARNING'}, 0, "failed to create Net::SSH::Expect object to control $computer_name, $!");
@@ -2310,7 +2300,7 @@ sub execute_new {
 				}
 				
 				#$ssh->exec("stty -echo");
-				$ssh->exec("stty raw -echo");
+				#$ssh->exec("stty raw -echo");
 				
 				# Set the timeout counter behaviour:
 				# If true, sets the timeout to "inactivity timeout"

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=1488390&r1=1488389&r2=1488390&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Fri May 31 20:32:43 2013
@@ -328,13 +328,13 @@ sub post_load {
 	my $mn_private_ip         = $self->mn_os->get_private_ip_address();
 	
 	notify($ERRORS{'OK'}, 0, "initiating Linux post_load: $image_name on $computer_short_name");
-	
+
 	# Wait for computer to respond to SSH
-	if (!$self->wait_for_response(30, 600, 10)) {
+	if (!$self->wait_for_response(5, 600, 10)) {
 		notify($ERRORS{'WARNING'}, 0, "$computer_node_name never responded to SSH");
 		return 0;
 	}
-	
+
 	# Configure sshd to only listen on the private interface and add ext_sshd service listening on the public interface
 	if (!$self->configure_ext_sshd()) {
 		notify($ERRORS{'WARNING'}, 0, "failed to configure ext_sshd on $computer_node_name");
@@ -901,83 +901,103 @@ sub delete_user {
 	$user_login_id = $self->data->get_user_login_id() if (!$user_login_id);
 	if (!$user_login_id) {
 		notify($ERRORS{'WARNING'}, 0, "user could not be determined");
-		return 0;
+		return;
 	}
 	
-	# Make sure the user login ID was passed
-	my $computer_node_name = shift;
-	$computer_node_name = $self->data->get_computer_node_name() if (!$computer_node_name);
-	if (!$computer_node_name) {
-		notify($ERRORS{'WARNING'}, 0, "computer node name could not be determined");
-		return 0;
-	}
+	my $computer_node_name = $self->data->get_computer_node_name();
 	
-	# Make sure the identity key was passed
-	my $image_identity = shift;
-	$image_identity = $self->data->get_image_identity() if (!$image_identity);
-	if (!$image_identity) {
-		notify($ERRORS{'WARNING'}, 0, "image identity keys could not be determined");
-		return 0;
+	# Make sure the user exists
+	if (!$self->user_exists($user_login_id)) {
+		notify($ERRORS{'DEBUG'}, 0, "user NOT deleted from $computer_node_name because it does not exist: $user_login_id");
+		return 1;
 	}
 	
-	
+	# Check if the user is logged in
 	if ($self->user_logged_in($user_login_id)) {
-		notify($ERRORS{'OK'}, 0, "user $user_login_id is logged in, logging of user");
-		if ($self->logoff_user($user_login_id)) {
-		
+		if (!$self->logoff_user($user_login_id)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to delete user $user_login_id from $computer_node_name, user appears to be logged in but could NOT be logged off");
+			return;
 		}
 	}
-
-	#Clean out any public ssh identity keys 
-	my $home_network_share_cmd = "df /home/$user_login_id";
-   my ($exit_status, $output) = $self->execute($home_network_share_cmd);
-   if(grep(/dev/, @$output)){
-     # confirm .ssh directory exists
-     # Make directory
-     my $rm_keys_cmd = "/bin/rm /home/$user_login_id/.ssh/authorized_keys";
-     if ($self->execute($rm_keys_cmd)) {
-         notify($ERRORS{'DEBUG'}, 0, "removed /home/$user_login_id/.ssh/authorized_keys file");
-     }
+	
+	# Run df to determine if home directory is on a local device or network share
+	my $home_directory_path = "/home/$user_login_id";
+	my $df_command = "df -T -P $home_directory_path";
+	my ($df_exit_status, $df_output) = $self->execute($df_command);
+	if (!defined($df_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to determine if home directory is mounted on a network share, command: '$df_command'");
+		return;
+	}
+	elsif (grep(/(no such file|no file system)/i, @$df_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "home directory does NOT exist on $computer_node_name: $home_directory_path");
+	}
+	elsif (grep(/[\t\s]+nfs/, @$df_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "home directory is mounted on a network share, command: '$df_command', output:\n" . join("\n", @$df_output));
 	}
 	else {
-		notify($ERRORS{'DEBUG'}, 0, "Detected network mounted home directory, will not remove authorized_keys: @$output");
+		notify($ERRORS{'DEBUG'}, 0, "home directory is NOT mounted on a network share, command: '$df_command', output:\n" . join("\n", @$df_output));
+		
+		# Delete the user's authorized keys file
+		my $authorized_keys_path = "$home_directory_path/.ssh/authorized_keys";
+		$self->delete_file($authorized_keys_path);
 	}
 	
-	# Use userdel to delete the user
-	# Do not use userdel -r, it will affect HPC user storage for HPC installs
-	my $user_delete_command = "/usr/sbin/userdel $user_login_id";
-	my @user_delete_results = $self->execute($user_delete_command);
-	foreach my $user_delete_line (@{$user_delete_results[1]}) {
-		if ($user_delete_line =~ /currently logged in/) {
-			notify($ERRORS{'WARNING'}, 0, "user not deleted, $user_login_id currently logged in");
-			return 0;
-		}
+	# Call userdel to delete the user
+	# Do not use userdel -r or -f, it could remove a user's home directory on a network share
+	my $userdel_command = "/usr/sbin/userdel $user_login_id";
+	my ($userdel_exit_status, $userdel_output) = $self->execute($userdel_command);
+	if (!defined($userdel_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to delete user from $computer_node_name: $user_login_id");
+		return;
 	}
-	
-	# Delete the group
-	my $user_group_cmd = "/usr/sbin/groupdel $user_login_id";
-	if ($self->execute($user_delete_command)) {
-		notify($ERRORS{'DEBUG'}, 0, "attempted to delete usergroup for $user_login_id");
+	elsif (grep(/does not exist/i, @$userdel_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "user '$user_login_id' NOT deleted from $computer_node_name because it does not exist");
+	}
+	elsif (grep(/userdel: /i, @$userdel_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to delete user '$user_login_id' from $computer_node_name, command: '$userdel_command', output:\n" . join("\n", @$userdel_output));
+		return;
+	}
+	else {
+		notify($ERRORS{'OK'}, 0, "deleted user '$user_login_id' from $computer_node_name");
 	}
 	
-	my $imagemeta_rootaccess = $self->data->get_imagemeta_rootaccess();
-	
-	# Remove user from  external_sshd_config
-	my $rem_user_sshd_cmd = "sed -i -e \"/AllowUsers/s/$user_login_id//\" /etc/ssh/external_sshd_config"; 
-	if ($self->execute($rem_user_sshd_cmd)) {
-		if (!$self->restart_service("ext_sshd")) {
-      	notify($ERRORS{'WARNING'}, 0, "failed to restart ext_sshd service on $computer_node_name after updating /etc/ssh/external_sshd_config");
-   	}	
+	# Call groupdel to delete the user's group
+	my $groupdel_command = "/usr/sbin/groupdel $user_login_id";
+	my ($groupdel_exit_status, $groupdel_output) = $self->execute($groupdel_command);
+	if (!defined($groupdel_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to delete group from $computer_node_name: $user_login_id");
+		return;
+	}
+	elsif (grep(/does not exist/i, @$groupdel_output)) {
+		notify($ERRORS{'DEBUG'}, 0, "group '$user_login_id' NOT deleted from $computer_node_name because it does not exist");
+	}
+	elsif (grep(/groupdel: /i, @$groupdel_output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to delete group '$user_login_id' from $computer_node_name, command: '$groupdel_command', output:\n" . join("\n", @$groupdel_output));
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "Failed to remove user_login_id from external_sshd_config");
+		notify($ERRORS{'OK'}, 0, "deleted group '$user_login_id' from $computer_node_name");
 	}
 	
+	# Remove username from AllowUsers lines in ssh/external_sshd_config
+	my $external_sshd_config_file_path = '/etc/ssh/external_sshd_config';
+	my @lines = $self->get_file_contents($external_sshd_config_file_path);
+	my $new_file_contents;
+	for my $line (@lines) {
+		if ($line =~ /AllowUsers/) {
+			$line =~ s/\s*$user_login_id//g;
+			# If user was only username listed on line, don't add empty AllowUsers line back to file
+			if ($line !~ /AllowUsers\s+\w/) {
+				next;
+			}
+		}
+		$new_file_contents .= "$line\n";
+	}
+	$self->create_text_file("$external_sshd_config_file_path\_new", $new_file_contents) || return;
+	
 	# Remove lines from sudoers
-	$self->remove_lines_from_file('/etc/sudoers', "^$user_login_id .*") || return;
+	$self->remove_lines_from_file('/etc/sudoers', "^\\s*$user_login_id\\s+") || return;
 	
 	return 1;
-
 } ## end sub delete_user
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -3999,26 +4019,26 @@ sub user_exists {
 		$username = $self->data->get_user_login_id();
 	}
 	
-	notify($ERRORS{'DEBUG'}, 0, "checking if user $username exists on $computer_node_name");
+	notify($ERRORS{'DEBUG'}, 0, "checking if user exists on $computer_node_name: $username");
 	
 	# Attempt to query the user account
 	my $query_user_command = "id $username";
-	my ($query_user_exit_status, $query_user_output) = $self->execute($query_user_command, 1);
+	my ($query_user_exit_status, $query_user_output) = $self->execute($query_user_command, 0);
 	
 	if (grep(/uid/, @$query_user_output)) {
-		notify($ERRORS{'DEBUG'}, 0, "user $username exists on $computer_node_name");
+		notify($ERRORS{'DEBUG'}, 0, "user exists on $computer_node_name: $username");
 		return 1;
 	}
 	elsif (grep(/No such user/i, @$query_user_output)) {
-		notify($ERRORS{'DEBUG'}, 0, "user $username does not exist on $computer_node_name");
+		notify($ERRORS{'DEBUG'}, 0, "user does not exist on $computer_node_name: $username");
 		return 0;
 	}
 	elsif (defined($query_user_exit_status)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to determine if user $username exists on $computer_node_name, exit status: $query_user_exit_status, output:\n@{$query_user_output}");
+		notify($ERRORS{'WARNING'}, 0, "failed to determine if user exists on $computer_node_name: $username, exit status: $query_user_exit_status, output:\n@{$query_user_output}");
 		return;
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if user $username exists on $computer_node_name");
+		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if user exists on $computer_node_name: $username");
 		return;
 	}
 }