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 2014/12/17 20:17:13 UTC

svn commit: r1646314 - in /vcl/trunk/managementnode/lib/VCL: Module/OS.pm Module/OS/Linux.pm Module/OS/Linux/Ubuntu.pm Module/OS/Windows.pm Module/State.pm inuse.pm reclaim.pm reserved.pm utils.pm

Author: arkurth
Date: Wed Dec 17 19:17:12 2014
New Revision: 1646314

URL: http://svn.apache.org/r1646314
Log:
VCL-785
(VCL timings)
Updated reserved.pm to add 'acknowledgetimeout' just prior to ack checking, and to delete it after the checking. Added 'noinitialconnection' immediately after ack checking.

Updated utils.pm::delete_computerloadlog_reservation to accept a regex for more versatility.

Updated inuse.pm::process to use the initialconnecttimeout and reconnecttimeout variables.

Added call to insert computerloadlog 'connecttimeout' entry in inuse.pm before connection checking and call to remove it afterwards.

Updated State.pm::state_exit to delete computerloadlog entries correctly, as late as possible.


VCL-702
(Rework code and cleanup)
Reworked OS.pm::manage_server_access. Renamed it to add_user_accounts. This is called from OS.pm::reserve. Removed call to manage_server_access from reserved.pm. Everything now is handled by reserve which makes the sequence the same for all reservations.

Replaced update_reservation_accounts with separate add_reservation_account and delete_reservation_account subroutines in utils.pm.

Added OS.pm::delete_user_accounts.

Updated Linux.pm and Windows.pm create_user to only accept a hash reference containing the required user information.

Updated Linux.pm::reserve to not handle any "standalone" logic. Added Linux.pm::should_set_user_password, which is called from OS.pm::reserve to handle the "standalone" logic.

Updated sanitize in Linux.pm and Windows.pm to delete all user accounts, not just the request owner. Commented out section in reclaim.pm which caused server reservations to always be reloaded. This shouldn't be necessary now that all user accounts are being removed by sanitize.

Renamed changepasswd to set_password in Linux.pm and Ubuntu.pm.

Removed unused OS.pm::check_reservation_password.

Updated Linux.pm::disable_firewall_port to not fail if an attempt to disable TCP/22 is made. Instead of returning null, it now calls enable_firewall_port to enable the port only to the management node's private IP address.

Other
Updated OS.pm::is_ssh_responding to not display output.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
    vcl/trunk/managementnode/lib/VCL/Module/State.pm
    vcl/trunk/managementnode/lib/VCL/inuse.pm
    vcl/trunk/managementnode/lib/VCL/reclaim.pm
    vcl/trunk/managementnode/lib/VCL/reserved.pm
    vcl/trunk/managementnode/lib/VCL/utils.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=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed Dec 17 19:17:12 2014
@@ -133,7 +133,10 @@ sub pre_capture {
 
  Parameters  : none
  Returns     : boolean
- Description : Performs common OS steps to reserve the computer for a user.
+ Description : Performs common OS steps to reserve the computer for a user. The
+               public IP address is updated if necessary. User accounts are
+               added. The 'reserve' subroutine should never open the firewall
+               for a connection. This is done by the 'grant_access' subroutine.
 
 =cut
 
@@ -150,11 +153,246 @@ sub reserve {
 		return;
 	}
 	
+	# Add user accounts to the computer
+	if (!$self->add_user_accounts()) {
+		notify($ERRORS{'WARNING'}, 0, "unable to reserve computer, failed add user accounts");
+		return;
+	}
+	
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 add_user_accounts
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Adds all user accounts to the computer for a reservation. The
+               reservationaccounts table is checked. If the user already exists
+               in the table, it is assumed the user was previously created and
+               nothing is done. If the user doesn't exist in the table it is
+               added. If an entry for a user exists in the reservationaccounts
+               table but the user is not assigned to the reservation, the user
+               is deleted from the computer.
+
+=cut
+
+sub add_user_accounts {
+	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_user_id  = $self->data->get_user_id();
+	my $request_state_name  = $self->data->get_request_state_name();
+	my $reservation_id = $self->data->get_reservation_id();
+	my $reservation_users = $self->data->get_reservation_users();
+	my $reservation_password = $self->data->get_reservation_password(0);
+	my $computer_node_name = $self->data->get_computer_node_name();
+
+	# Collect users in reservationaccounts table
+	my $reservation_accounts = get_reservation_accounts($reservation_id);
+	
+	# Add users
+	RESERVATION_USER: foreach my $user_id (sort keys %$reservation_users) {
+		my $username = $reservation_users->{$user_id}{unityid};
+		my $uid = $reservation_users->{$user_id}{uid};
+		my $root_access = $reservation_users->{$user_id}{ROOTACCESS};
+		my $ssh_public_keys = $reservation_users->{$user_id}{user_info}{sshpublickeys};
+		my $password;
+		
+		# Check if entry needs to be added to the useraccounts table
+		if (defined($reservation_accounts->{$user_id})) {
+			# Entry already exists in useraccounts table, assume everything is correct
+			notify($ERRORS{'DEBUG'}, 0, "entry already exists in useraccounts table for $username (ID: $user_id)");
+			
+			# This is normal, user should exist unless state is reinstall
+			# If reinstall, proceed to try to create the user
+			# Otherwise, proceed to next user
+			if ($request_state_name !~ /(reinstall)/) {
+				next RESERVATION_USER;
+			}
+			$password = $reservation_accounts->{$user_id}{password};
+		}
+		else {
+			notify($ERRORS{'DEBUG'}, 0, "entry does not already exist in useraccounts table for $username (ID: $user_id)");
+			
+			# Determine whether or not the user account's password should be set
+			my $should_set_user_password = 1;
+			if ($self->can('should_set_user_password')) {
+				$should_set_user_password = $self->should_set_user_password($user_id);
+				if (!defined($should_set_user_password)) {
+					notify($ERRORS{'CRITICAL'}, 0, "failed to determine if user account password should be set, user ID $user_id, assuming password should be set");
+					$should_set_user_password = 1;
+				}
+			}
+			
+			if ($should_set_user_password) {
+				# Check if this is the request owner user ID and the reservation password has already been set
+				if ($user_id eq $request_user_id) {
+					if ($reservation_password) {
+						$password = $reservation_password;
+						notify($ERRORS{'DEBUG'}, 0, "user $username (ID: $user_id) is request owner, using existing reservation password: $password");
+					}
+					else {
+						# Generate a new random password
+						$password = getpw();
+						$self->data->set_reservation_password($password);
+						notify($ERRORS{'DEBUG'}, 0, "user $username (ID: $user_id) is request owner, generated new password: $password");
+						
+						# Update the password in the reservation table
+						if (!update_reservation_password($reservation_id, $password)) {
+							$self->reservation_failed("failed to update password in the reservation table");
+							return;
+						}
+					}
+				}
+				else {
+					# Generate a new random password
+					$password = getpw();
+					notify($ERRORS{'DEBUG'}, 0, "user $username (ID: $user_id) is not the request owner, generated new password: $password");
+				}
+			}
+			
+			# Add an entry to the useraccounts table
+			if (!add_reservation_account($reservation_id, $user_id, $password)) {
+				notify($ERRORS{'CRITICAL'}, 0, "failed to add entry to reservationaccounts table for $username (ID: $user_id)");
+				return;
+			}
+			
+			# Make sure the user doesn't already exist on the computer
+			if ($self->user_exists($username)) {
+				if ($password) {
+					notify($ERRORS{'WARNING'}, 0, "user '$username' already exists on $computer_node_name, password will be reset");
+					if (!$self->set_password($username, $password)) {
+						notify($ERRORS{'WARNING'}, 0, "user '$username' already exists on $computer_node_name, failed to reset password");
+					}
+				}
+				else {
+					notify($ERRORS{'WARNING'}, 0, "user '$username' already exists on $computer_node_name");
+				}
+				
+				next RESERVATION_USER;
+			}
+		}
+		
+		# Create user on the OS
+		if (!$self->create_user({
+				username => $username,
+				password => $password,
+				root_access => $root_access,
+				uid => $uid,
+				ssh_public_keys => $ssh_public_keys,
+		})) {
+			notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, removing entry added to reservationaccounts table");
+			
+			# Delete entry to the useraccounts table
+			if (!delete_reservation_account($reservation_id, $user_id)) {
+				notify($ERRORS{'CRITICAL'}, 0, "failed to delete entry from reservationaccounts table for $username (ID: $user_id)");
+			}
+		}
+	}
+	
+	# Remove anyone listed in reservationaccounts that is not a reservation user
+	foreach my $user_id (sort keys %$reservation_accounts) {
+		if (defined($reservation_users->{$user_id})) {
+			next;
+		}
+		
+		my $username = $reservation_accounts->{$user_id}{username};
+		
+		notify($ERRORS{'OK'}, 0, "user $username (ID: $user_id) exists in reservationsaccounts table but is not assigned to this reservation, attempting to delete user");
+		
+		# Delete the user from OS
+		if (!$self->delete_user($username)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to delete user $username (ID: $user_id) from $computer_node_name");
+			next;
+		}
+		
+		# Delete entry from reservationaccounts
+		if (!delete_reservation_account($reservation_id, $user_id)) {
+			notify($ERRORS{'CRITICAL'}, 0, "failed to delete entry from reservationaccounts table for user $username (ID: $user_id)");
+		}
+	}
+	
 	return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 delete_user_accounts
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Deletes all user accounts from the computer which are assigned to
+               the reservation or an entry exists in the reservationaccounts
+               table.
+
+=cut
+
+sub delete_user_accounts {
+	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 $reservation_id = $self->data->get_reservation_id();
+	my $computer_node_name = $self->data->get_computer_node_name();
+	my $reservation_users = $self->data->get_reservation_users();
+
+	# Collect users in reservationaccounts table
+	my $reservation_accounts = get_reservation_accounts($reservation_id);
+	
+	my $errors = 0;
+	
+	# Delete users
+	foreach my $user_id (sort keys %$reservation_users) {
+		my $username = $reservation_users->{$user_id}{unityid};
+		
+		# Delete the key from reservation accounts, these will be processed next
+		delete $reservation_accounts->{$user_id};
+		
+		# Delete user on the OS
+		if (!$self->delete_user($username)) {
+			$errors = 1;
+			notify($ERRORS{'WARNING'}, 0, "failed to delete user on $computer_node_name");
+			
+			# Delete entry to the useraccounts table
+			if (!delete_reservation_account($reservation_id, $user_id)) {
+				notify($ERRORS{'CRITICAL'}, 0, "failed to delete entry from reservationaccounts table for $username (ID: $user_id)");
+			}
+		}
+	}
+	
+	foreach my $user_id (sort keys %$reservation_accounts) {
+		my $username = $reservation_accounts->{$user_id}{username};
+		
+		# Delete the user from OS
+		if (!$self->delete_user($username)) {
+			$errors = 1;
+			notify($ERRORS{'WARNING'}, 0, "failed to delete user $username (ID: $user_id) from $computer_node_name");
+			next;
+		}
+		
+		# Delete entry from reservationaccounts
+		if (!delete_reservation_account($reservation_id, $user_id)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to delete entry from reservationaccounts table for user $username (ID: $user_id)");
+		}
+	}
+	
+	if ($errors) {
+		return 0;
+	}
+	else {
+		return 1;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_source_configuration_directories
 
  Parameters  : None
@@ -316,9 +554,9 @@ sub get_currentimage_txt_contents {
 		$l =~ s/[\r\n]*//g;
 		my ($a, $b) = split(/=/, $l);
 		if (defined $b) {
-         $output{$a} = $b; 
-      }   
-   }
+			$output{$a} = $b; 
+		}   
+	}
 	
 	return %output;
 } ## end sub get_currentimage_txt_contents
@@ -328,14 +566,14 @@ sub get_currentimage_txt_contents {
 =head2 get_current_image_info
 
  Parameters  : optional 
-					id,computer_hostname,computer_id,current_image_name,imagerevision_datecreated,imagerevision_id,prettyname,vcld_post_load 
+               id,computer_hostname,computer_id,current_image_name,imagerevision_datecreated,imagerevision_id,prettyname,vcld_post_load 
  Returns     : If successful: 
-					if no parameter return the imagerevision_id
-					return the value of parameter input
+               if no parameter return the imagerevision_id
+               return the value of parameter input
                If failed: false
  Description : Collects currentimage hash on a computer and returns a
                value containing of the input paramter or the imagerevision_id if no inputs.
-					This also updates the DataStructure.pm so data matches what is currently loaded.
+               This also updates the DataStructure.pm so data matches what is currently loaded.
 =cut
 
 sub get_current_image_info {
@@ -714,8 +952,8 @@ sub is_ssh_responding {
 			node => $computer_node_name,
 			command => "echo \"testing ssh on $computer_node_name\"",
 			max_attempts => $max_attempts,
-			output_level => 0,
-			timeout_seconds => 30,
+			display_output => 0,
+			timeout_seconds => 10,
 		});
 		
 		# The exit status will be 0 if the command succeeded
@@ -2172,7 +2410,7 @@ sub execute {
 			$computer_name = $argument->{node} if (!$computer_name);
 			$command = $argument->{command};
 			$display_output = $argument->{display_output};
-			$timeout_seconds = $argument->{timeout};
+			$timeout_seconds = $argument->{timeout_seconds};
 			$max_attempts = $argument->{max_attempts};
 			$port = $argument->{port};
 			$user = $argument->{user};
@@ -2234,7 +2472,7 @@ sub execute {
 		return ($exit_status, $output);
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to run command on $computer_name: $command");
+		notify($ERRORS{'WARNING'}, 0, "failed to run command on $computer_name: $command") if $display_output;
 		return;
 	}
 }
@@ -2278,7 +2516,7 @@ sub execute_new {
 			$computer_name = $argument->{node} if (!$computer_name);
 			$command = $argument->{command};
 			$display_output = $argument->{display_output};
-			$timeout_seconds = $argument->{timeout};
+			$timeout_seconds = $argument->{timeout_seconds};
 			$max_attempts = $argument->{max_attempts};
 			$port = $argument->{port};
 			$user = $argument->{user};
@@ -2554,141 +2792,6 @@ sub get_os_type {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 manage_server_access
-
- Parameters  : None
- Returns     : 
- Description : 
-
-=cut
-
-sub manage_server_access {
-
-	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 $computer_node_name          = $self->data->get_computer_node_name() || return;
-	my $reservation_id              = $self->data->get_reservation_id();
-	my $server_request_id           = $self->data->get_server_request_id();
-	my $server_request_admingroupid = $self->data->get_server_request_admingroupid();
-	my $server_request_logingroupid = $self->data->get_server_request_logingroupid();
-	my $user_login_id_owner         = $self->data->get_user_login_id();
-	my $user_ssh_public_keys        = $self->data->get_user_ssh_public_keys(0);
-	my $user_id_owner               = $self->data->get_user_id();
-	my $image_os_type               = $self->data->get_image_os_type();
-	my $request_laststate_name      = $self->data->get_request_laststate_name();
-	my $reservation_users           = $self->data->get_reservation_users();
-
-	# Build list of users.
-	# If in admin group set admin flag
-	# If in both login and admin group, only use admin setting
-	# Check if user is in reserverationaccounts table, add user if needed
-	# Check if user exists on server, add if needed
-	
-	my %user_hash = %{$reservation_users};
-
-	# Collect users in reservationaccounts table
-	my %res_accounts = get_reservation_accounts($reservation_id);
-	my $not_standalone_list = $self->data->get_management_node_not_standalone();
-	#notify($ERRORS{'WARNING'}, 0, "request_laststate_name= $request_laststate_name Res account info" . format_data(%res_accounts));
-	#notify($ERRORS{'WARNING'}, 0, "request_laststate_name= $request_laststate_name User_hash info" . format_data(%user_hash));
-
-	#Add users
-	foreach my $userid (sort keys %user_hash) {
-		next if (!($userid));
-		#Skip reservation owner, this account is processed in the new and reserved states
-		if ($userid eq $user_id_owner) {
-			next;
-		}
-		my $standalone = $user_hash{$userid}{user_info}{STANDALONE};
-
-		if (!$self->user_exists($user_hash{$userid}{username})) {
-			delete($res_accounts{$userid});
-		}
-		
-		if (!exists($res_accounts{$userid}) || $request_laststate_name eq "reinstall" ) {
-			if($request_laststate_name ne "reinstall" ){	
-				
-				$user_hash{$userid}{"passwd"} = 0;
-				# Generate password if linux and standalone affiliation
-				unless ($image_os_type =~ /linux/ && !$standalone) {
-					$user_hash{$userid}{"passwd"} = getpw();
-				}
-				
-				if (update_reservation_accounts($reservation_id,$userid,$user_hash{$userid}{passwd},"add")) {
-					notify($ERRORS{'OK'}, 0, "Inserted $reservation_id,$userid into reservationsaccounts table");
-				}
-			}
-			# if reinstall and standalone check for existing password
-			if ($request_laststate_name eq "reinstall") {
-				#notify($ERRORS{'OK'}, 0, "Reinstall mode for $user_hash{$userid}{unityid}" . format_data(%res_accounts));
-				if ( $res_accounts{$userid}{password} ) {
-					$user_hash{$userid}{passwd} = $res_accounts{$userid}{password};
-				}
-				else {
-					#should have password for standalone accounts
-					unless ($image_os_type =~ /linux/ && !$standalone) {
-						$user_hash{$userid}{"passwd"} = getpw();
-					}
-					
-					if (update_reservation_accounts($reservation_id,$userid,0,"delete")) {
-					}
-					if (update_reservation_accounts($reservation_id,$userid,$user_hash{$userid}{passwd},"add")) {
-						notify($ERRORS{'OK'}, 0, "Inserted new password for $reservation_id,$userid into reservationsaccounts table");
-					}
-				}
-			}
-	
-			# Create user on the OS
-			if ($self->create_user(
-					$user_hash{$userid}{unityid},
-					$user_hash{$userid}{passwd},
-					$user_hash{$userid}{uid},
-					$user_hash{$userid}{ROOTACCESS},
-					$standalone,
-					$user_hash{$userid}{user_info}{sshpublickeys}
-			)) {
-				notify($ERRORS{'OK'}, 0, "Successfully created user $user_hash{$userid}{unityid} on $computer_node_name");
-			}
-			else {
-				notify($ERRORS{'WARNING'}, 0, "Failed to create user on $computer_node_name ");
-			}
-		}
-		else {
-			notify($ERRORS{'DEBUG'}, 0, "$userid exists in reservationaccounts table, assuming it exists on OS");
-		}
-	}
-
-	#Remove anyone listed in reservationaccounts list that is not in user_hash
-	foreach my $res_userid (sort keys %res_accounts) {
-		#notify($ERRORS{'OK'}, 0, "res_userid= $res_userid username= $res_accounts{$res_userid}{username}");
-		#Skip reservation owner, this account is not to be removed from the reservation.
-      if ($res_userid eq $user_login_id_owner) {
-			#Skip group checks as the owner may not be a member
-			next;
-		}
-		if (!exists($user_hash{$res_userid})) {
-			notify($ERRORS{'OK'}, 0, "username= $res_accounts{$res_userid}{username} is not listed in reservationsaccounts, attempting to delete");
-			#Delete from reservationaccounts
-			if (update_reservation_accounts($reservation_id,$res_accounts{$res_userid}{userid},0,"delete")) {
-				notify($ERRORS{'OK'}, 0, "Deleted $reservation_id,$res_accounts{$res_userid}{userid} from reservationsaccounts table");
-			}
-			#Delete from OS
-			if ($self->delete_user($res_accounts{$res_userid}{username},0,0)) {
-				notify($ERRORS{'OK'}, 0, "Successfully removed user= $res_accounts{$res_userid}{username}");	
-			}	
-			next;
-		}
-	}
-	
-	return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 process_connect_methods
 
  Parameters  : $remote_ip (optional), $overwrite
@@ -2783,7 +2886,7 @@ sub process_connect_methods {
 				if (!$self->stop_service($service_name)) {
 					notify($ERRORS{'WARNING'}, 0, "failed to stop '$service_name' service for '$name' connect method on $computer_node_name");
 				}
-         }
+			}
 			
 			# Close the firewall ports
 			if ($self->can('disable_firewall_port')) {
@@ -2792,6 +2895,7 @@ sub process_connect_methods {
 					my $port = $connect_method->{connectmethodport}{$connect_method_port_id}{port};
 					if (!$self->disable_firewall_port($protocol, $port, $remote_ip, 1)) {
 						notify($ERRORS{'WARNING'}, 0, "failed to close firewall port $protocol/$port on $computer_node_name for $remote_ip $name connect method");
+						return;
 					}
 				}
 			}
@@ -3376,10 +3480,10 @@ sub get_tools_file_paths {
 sub update_fixed_ip_info {
 
 	my $self = shift;
-   unless (ref($self) && $self->isa('VCL::Module')) {
-     notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module:: module object method");
-     return;
-   }
+	unless (ref($self) && $self->isa('VCL::Module')) {
+	  notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module:: module object method");
+	  return;
+	}
 	
 	my $server_request_id           = $self->data->get_server_request_id();
 	if (!$server_request_id) {
@@ -3388,7 +3492,7 @@ sub update_fixed_ip_info {
 	}
 
 	my $variable_name = "fixedIPsr" . $server_request_id; 	
-   my $server_variable_data;
+	my $server_variable_data;
 
 	if (is_variable_set($variable_name)) {
 		#fetch variable
@@ -3416,12 +3520,12 @@ sub update_fixed_ip_info {
 =head2 get_timings
 
    Parameters  : $self
-   Returns     : hash of timings
+   Returns     : integer
    Description : Check for cached information or pulls from variable table
    Acceptable variables are:
       acknowledgetimeout
-      wait_for_connect
-      wait_for_reconnect
+      initialconnecttimeout
+      reconnecttimeout
       general_inuse_check
       server_inuse_check
       general_end_notice_first
@@ -3437,24 +3541,23 @@ sub get_timings {
 	my $variable = shift;
 	my $affiliation_name = $self->data->get_user_affiliation_name(0);
 
-   my %timing_defaults = (
-      acknowledgetimeout => '900',
-      connecttimeout => '900',
-      wait_for_connect => '900',
-      wait_for_reconnect => '900',
-      general_inuse_check => '300',
-      server_inuse_check => '900',
-      cluster_inuse_check => '900',
-      general_end_notice_first => '600',
-      general_end_notice_second => '300',
-      ignore_connections_gte => '1440'
-   );
+	my %timing_defaults = (
+		acknowledgetimeout => '900',
+		initialconnecttimeout => '900',
+		reconnecttimeout => '900',
+		general_inuse_check => '300',
+		server_inuse_check => '900',
+		cluster_inuse_check => '900',
+		general_end_notice_first => '600',
+		general_end_notice_second => '300',
+		ignore_connections_gte => '1440'
+	);
 
 	#Check for affiliation, if nothing return default timings
-   if (!defined($variable) || !(exists($timing_defaults{$variable}))) {
+	if (!defined($variable) || !(exists($timing_defaults{$variable}))) {
 		notify($ERRORS{'WARNING'}, 0, " input variable is not acceptable, returning 900 as value"); 
-      return '900';
-   }
+		return '900';
+	}
 
 	my $db_timing_variable_value = get_variable("$variable|$affiliation_name", 0) || get_variable("$variable", 0) || $timing_defaults{$variable} ;
 	return $db_timing_variable_value;
@@ -3545,47 +3648,6 @@ sub run_scripts {
 	
 	return 1;
 }
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 check_reservation_password
-
- Parameters  : none
- Returns     : boolean
- Description : Checks if a reservation password has already been generated. If
-               not, a password is generated, the reservation table is updated,
-               and the DataStructure is updated.
-
-=cut
-
-sub check_reservation_password {
-	my $self = shift;
-	if (ref($self) !~ /VCL::Module/) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return;
-	}
-	
-	if ($self->data->get_reservation_password(0)) {
-		notify($ERRORS{'DEBUG'}, 0, "reservation password has already been generated");
-		return 1;
-	}
-	
-	my $reservation_id = $self->data->get_reservation_id();
-	
-	# Create a random password for the reservation
-	my $reservation_password = getpw();
-	
-	# Update the password in the reservation table
-	if (!update_reservation_password($reservation_id, $reservation_password)) {
-		$self->reservation_failed("failed to update password in the reservation table");
-		return;
-	}
-	
-	# Set the password in the DataStructure object
-	$self->data->set_reservation_password($reservation_password);
-	
-	return 1;
-}
 
 #/////////////////////////////////////////////////////////////////////////////
 

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=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed Dec 17 19:17:12 2014
@@ -446,7 +446,7 @@ sub post_load {
 	}
 	
 	# Change password
-	if (!$self->changepasswd("root")) {
+	if (!$self->set_password("root")) {
 		notify($ERRORS{'OK'}, 0, "failed to edit root password on $computer_node_name");
 	}
 	
@@ -1092,10 +1092,7 @@ sub logoff_user {
  Parameters  : none
  Returns     : boolean
  Description : Performs the steps necessary to reserve a computer for a user.
-               If the user "standalone" flag = 1, a random reservation password
-               is generated. Existing "AllowUsers" lines are removed from
-               /etc/ssh/external_sshd_config. A "vcl" user group is added to the
-               computer -The user account is created
+               A "vcl" user group is added to the.
 
 =cut
 
@@ -1106,20 +1103,9 @@ sub reserve {
 		return 0;
 	}
 	
-	# Call OS.pm's reserve subroutine
-	$self->SUPER::reserve() || return;
+	notify($ERRORS{'OK'}, 0, "beginning Linux reserve tasks");
 	
 	my $computer_node_name = $self->data->get_computer_node_name();
-	my $user_standalone = $self->data->get_user_standalone();
-
-	# Generate a reservation password if "standalone" (not using Kerberos authentication)
-	if ($user_standalone) {
-		# Generate a reservation password
-		if (!$self->check_reservation_password()) {
-			notify($ERRORS{'WARNING'}, 0, "failed to generate a reservation password");
-			return;
-		}
-	}
 	
 	# Configure sshd to only listen on the private interface and add ext_sshd service listening on the public interface
 	# This needs to be done after update_public_ip_address is called
@@ -1132,12 +1118,10 @@ sub reserve {
 		notify($ERRORS{'WARNING'}, 0, "failed to add vcl user group to $computer_node_name");
 	}
 	
-	if (!$self->create_user()) {
-		notify($ERRORS{'CRITICAL'}, 0, "failed to add user to $computer_node_name");
-		return;
-	}
+	notify($ERRORS{'OK'}, 0, "Linux reserve tasks complete");
 	
-	return 1;
+	# Call OS.pm's reserve subroutine
+	return unless $self->SUPER::reserve();
 } ## end sub reserve
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1253,7 +1237,7 @@ sub synchronize_time {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 changepasswd
+=head2 set_password
 
  Parameters  : $username, $password (optional)
  Returns     : boolean
@@ -1263,7 +1247,7 @@ sub synchronize_time {
 
 =cut
 
-sub changepasswd {
+sub set_password {
 	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");
@@ -1333,8 +1317,8 @@ sub sanitize {
 	}
 	
 	# Delete all user associated with the reservation
-	if (!$self->delete_user()) {
-		notify($ERRORS{'WARNING'}, 0, "failed to delete users from $computer_node_name");
+	if (!$self->delete_user_accounts()) {
+		notify($ERRORS{'WARNING'}, 0, "failed to delete all users from $computer_node_name");
 		return 0;
 	}
 	
@@ -2551,7 +2535,7 @@ sub shutdown {
 
 =head2 create_user
 
- Parameters  : $username, $password, $uid, $root_access, $user_standalone, $user_ssh_public_keys
+ Parameters  : 
  Returns     : boolean
  Description : 
 
@@ -2565,102 +2549,84 @@ sub create_user {
 	}
 	
 	my $computer_node_name = $self->data->get_computer_node_name();
-	my $imagemeta_root_access = $self->data->get_imagemeta_rootaccess();
 	
-	# Check if username argument was supplied
-	my $user_login_id = shift;
-	my $password = shift;
-	my $uid = shift;
-	my $root_access = shift;
-	my $user_standalone = shift;
-	my $user_ssh_public_keys = shift;
-	
-	my $reservation_user_login_id = $self->data->get_user_login_id();
-	
-	# If argument was supplied, check if it matches the reservation user
-	# Only retrieve user settings from $self->data if no argument was supplied or if the argument matches the reservation user
-	if (!$user_login_id || $user_login_id eq $reservation_user_login_id) {
-		$user_login_id = $reservation_user_login_id;
-		
-		$password = $self->data->get_reservation_password(0) unless defined $password;
-		$uid = $self->data->get_user_uid() unless defined $uid;
-		$root_access = $self->data->get_imagemeta_rootaccess() unless defined $root_access;
-		$user_standalone = $self->data->get_user_standalone() unless defined $user_standalone;
-		$user_ssh_public_keys = $self->data->get_user_ssh_public_keys(0) unless defined $user_ssh_public_keys;
+	my $user_parameters = shift;
+	if (!$user_parameters) {
+		notify($ERRORS{'WARNING'}, 0, "unable to create user, user parameters argument was not provided");
+		return;
+	}
+	elsif (!ref($user_parameters) || ref($user_parameters) ne 'HASH') {
+		notify($ERRORS{'WARNING'}, 0, "unable to create user, argument provided is not a hash reference");
+		return;
 	}
 	
-	$root_access = 1 unless defined $root_access;
-	$user_standalone = 1 unless defined $user_standalone;
+	my $username = $user_parameters->{username};
+	if (!defined($username)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, argument hash does not contain a 'username' key:\n" . format_data($user_parameters));
+		return;
+	}
 	
-	# Make sure the password was determined
-	if ($user_standalone) {
-		if (!defined($password)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to create user '$user_login_id', user standalone = $user_standalone, password argument was not supplied and reservation password is not configured");
-			return;
-		}
+	my $root_access = $user_parameters->{root_access};
+	if (!defined($root_access)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, argument hash does not contain a 'root_access' key:\n" . format_data($user_parameters));
+		return;
 	}
-	else {
-		# user standalone is false, undefine the password
-		undef($password);
+	
+	my $password = $user_parameters->{password};
+	my $uid = $user_parameters->{uid};
+	my $ssh_public_keys = $user_parameters->{ssh_public_keys};
+	
+	# Check if user already exists
+	if ($self->user_exists($username)) {
+		notify($ERRORS{'WARNING'}, 0, "unable to create user '$username' on $computer_node_name, the user already exists");
+		return;
 	}
 	
 	notify($ERRORS{'DEBUG'}, 0, "creating user on $computer_node_name:\n" .
-		"login ID: $user_login_id\n" .
-		"UID: " . ($uid ? $uid : '<not set>') . "\n" .
-		"root access: $root_access\n" .
-		"standalone: $user_standalone\n" .
+		"username: $username\n" .
 		"password: " . (defined($password) ? $password : '<not set>') . "\n" .
-		"SSH public keys: " . (defined($user_ssh_public_keys) ? $user_ssh_public_keys : '<not set>')
+		"UID: " . ($uid ? $uid : '<not set>') . "\n" .
+		"root access: " . ($root_access ? 'yes' : 'no') . "\n" .
+		"SSH public keys: " . (defined($ssh_public_keys) ? $ssh_public_keys : '<not set>')
 	);
 	
-	my $home_directory_path = "/home/$user_login_id";
 	my $home_directory_root = "/home";
+	my $home_directory_path = "$home_directory_root/$username";
 	my $home_directory_on_local_disk = $self->is_file_on_local_disk($home_directory_root);
 	if ($home_directory_on_local_disk ) {
-
-	my $useradd_command = "/usr/sbin/useradd -s /bin/bash -m -d /home/$user_login_id -g vcl";
-	$useradd_command .= " -u $uid" if ($uid);
-	$useradd_command .= " $user_login_id";
-	my ($useradd_exit_status, $useradd_output) = $self->execute($useradd_command);
-	
-	# Check if the output indicates that the user already exists
-	# useradd: warning: the home directory already exists
-	# useradd: user ibuser exists
-	
-	if ($useradd_output && grep(/ exists(\s|$)/i, @$useradd_output)) {
-		if (!$self->delete_user($user_login_id)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to add user '$user_login_id' to $computer_node_name, user with same name already exists and could not be deleted");
+		my $useradd_command = "/usr/sbin/useradd -s /bin/bash -m -d /home/$username -g vcl";
+		$useradd_command .= " -u $uid" if ($uid);
+		$useradd_command .= " $username";
+		
+		my ($useradd_exit_status, $useradd_output) = $self->execute($useradd_command);
+		if (!defined($useradd_output)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to execute command to add user '$username' to $computer_node_name: '$useradd_command'");
 			return;
 		}
-		($useradd_exit_status, $useradd_output) = $self->execute($useradd_command);
-	}
-	
-	if (!defined($useradd_output)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to execute command to add user '$user_login_id' to $computer_node_name: '$useradd_command'");
-		return;
-	}
-	elsif (grep(/^useradd: /, @$useradd_output)) {
-		notify($ERRORS{'WARNING'}, 0, "warning on add user '$user_login_id' to $computer_node_name\ncommand: '$useradd_command'\noutput:\n" . join("\n", @$useradd_output));
-	}
-	else {
-		notify($ERRORS{'OK'}, 0, "added user '$user_login_id' to $computer_node_name");
-	}
+		elsif (grep(/^useradd: /, @$useradd_output)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to add user '$username' to $computer_node_name\ncommand: '$useradd_command'\noutput:\n" . join("\n", @$useradd_output));
+			return;
+		}
+		else {
+			notify($ERRORS{'OK'}, 0, "added user '$username' to $computer_node_name");
+		}
 	}
 	else {
 		notify($ERRORS{'OK'}, 0, "$home_directory_path is NOT on local disk, skipping useradd attempt");	
 	}
 	
-	if ($user_standalone) {
+	# Set the password
+	if ($password) {
 		# Set password
-		if (!$self->changepasswd($user_login_id, $password)) {
-			notify($ERRORS{'CRITICAL'}, 0, "Failed to set password on useracct: $user_login_id on $computer_node_name");
+		if (!$self->set_password($username, $password)) {
+			notify($ERRORS{'CRITICAL'}, 0, "failed to set password of user '$username' on $computer_node_name");
 			return;
 		}
 	}
 	
 	# Append AllowUsers line to the end of the file
 	my $external_sshd_config_file_path = '/etc/ssh/external_sshd_config';
-	my $allow_users_line = "AllowUsers $user_login_id";
+	my $allow_users_line = "AllowUsers $username\n";
 	if ($self->append_text_file($external_sshd_config_file_path, $allow_users_line)) {
 		notify($ERRORS{'DEBUG'}, 0, "added line to $external_sshd_config_file_path: '$allow_users_line'");
 	}
@@ -2671,61 +2637,52 @@ sub create_user {
 	
 	$self->restart_service('ext_sshd') || return;
 	
-	# Check image profile for allowed root access
-	# If the imagemeta root access is disable don't allow manage_server_access to override
-	if (defined($imagemeta_root_access) && $imagemeta_root_access) {
-		if ($root_access == 1) {
-			my $sudoers_file_path = '/etc/sudoers';
-			my $sudoers_line = "$user_login_id ALL= NOPASSWD: ALL";
-			if ($self->append_text_file($sudoers_file_path, $sudoers_line)) {
-				notify($ERRORS{'DEBUG'}, 0, "added line to $sudoers_file_path: '$sudoers_line'");
-			}
-			else {
-				notify($ERRORS{'WARNING'}, 0, "failed to add line to $sudoers_file_path: '$sudoers_line'");
-				return;
-			}
+	# Add user to sudoers if necessary
+	if ($root_access) {
+		my $sudoers_file_path = '/etc/sudoers';
+		my $sudoers_line = "$username ALL= NOPASSWD: ALL\n";
+		if ($self->append_text_file($sudoers_file_path, $sudoers_line)) {
+			notify($ERRORS{'DEBUG'}, 0, "appended line to $sudoers_file_path: '$sudoers_line'");
 		}
 		else {
-			notify($ERRORS{'DEBUG'}, 0, "root access NOT granted to $user_login_id");
+			notify($ERRORS{'WARNING'}, 0, "failed to append line to $sudoers_file_path: '$sudoers_line'");
+			return;
 		}
 	}
 	else {
-		notify($ERRORS{'DEBUG'}, 0, "root access NOT granted to $user_login_id, imagemeta_root_access set to $imagemeta_root_access");
+		notify($ERRORS{'DEBUG'}, 0, "root access not granted to $username");
 	}
-
-	# Add user's public ssh identity keys if exists
-	my $ssh_directory_path = "$home_directory_path/.ssh";
-	my $authorized_keys_file_path = "$ssh_directory_path/authorized_keys";
 	
-	if ($user_ssh_public_keys) {
-		# Determine if home directory is on a local device or network share
-		$home_directory_on_local_disk = $self->is_file_on_local_disk($home_directory_path);
+	# Add user's public ssh identity keys if exists
+	if ($ssh_public_keys) {
+		my $ssh_directory_path = "$home_directory_path/.ssh";
+		my $authorized_keys_file_path = "$ssh_directory_path/authorized_keys";
 		
+		# Determine if home directory is on a local device or network share
 		# Only add keys to home directories that are local,
-		# Don'd add keys to network mounted filesystems
-		
+		# Don't add keys to network mounted filesystems
+		$home_directory_on_local_disk = $self->is_file_on_local_disk($home_directory_path);
 		if ($home_directory_on_local_disk) {
 			# Create the .ssh directory
 			$self->create_directory($ssh_directory_path);
 			
-			if ($self->append_text_file($authorized_keys_file_path, $user_ssh_public_keys)) {
-				notify($ERRORS{'DEBUG'}, 0, "added user's public keys to $authorized_keys_file_path");
+			if ($self->append_text_file($authorized_keys_file_path, "$ssh_public_keys\n")) {
+				notify($ERRORS{'DEBUG'}, 0, "added user's public SSH keys to $authorized_keys_file_path");
 			}
 			else {
-				notify($ERRORS{'WARNING'}, 0, "failed to add user's public keys to $authorized_keys_file_path");
+				notify($ERRORS{'WARNING'}, 0, "failed to add user's public SSH keys to $authorized_keys_file_path");
 			}
 
-			if (!$self->set_file_owner($home_directory_path, $user_login_id, 'vcl', 1)) {
+			if (!$self->set_file_owner($home_directory_path, $username, 'vcl', 1)) {
 				notify($ERRORS{'WARNING'}, 0, "failed to set owner of user's home directory: $home_directory_path");
 				return;
-		}
+			}
 		}
 		else {
-			notify($ERRORS{'DEBUG'}, 0, "skipping adding user's public keys to $authorized_keys_file_path, home directory is on a network share");
+			notify($ERRORS{'DEBUG'}, 0, "user's public SSH keys not added to $authorized_keys_file_path, home directory is on a network share");
 		}
 	}
 	
-
 	return 1;
 } ## end sub create_user
 
@@ -2733,7 +2690,7 @@ sub create_user {
 
 =head2 delete_user
 
- Parameters  :
+ Parameters  : $username
  Returns     :
  Description :
 
@@ -3880,8 +3837,9 @@ sub disable_firewall_port {
 		return;
 	}
 	elsif ($port eq '22') {
-		notify($ERRORS{'WARNING'}, 0, "disabling firewall port 22 is not allowed because it will cut off access from the management node");
-		return;
+		my $mn_private_ip = $self->mn_os->get_private_ip_address();
+		notify($ERRORS{'OK'}, 0, "disabling firewall port 22 is not allowed because it will cut off access from the management node, enabling port 22 to only the management node's private IP address: $mn_private_ip");
+		return $self->enable_firewall_port("tcp", 22, $mn_private_ip, 1);
 	}
 	
 	my $chain = "INPUT";
@@ -5357,6 +5315,48 @@ sub enable_ip_forwarding {
 	}
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 should_set_user_password
+
+ Parameters  : $user_id
+ Returns     : boolean
+ Description : Determines whether or not a user account's password should be set
+               on the computer being loaded. The "STANDALONE" flag is used to
+               determine this.
+
+=cut
+
+sub should_set_user_password {
+	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 ($user_id) = shift;
+	if (!$user_id) {
+		notify($ERRORS{'WARNING'}, 0, "user ID argument was not supplied");
+		return;
+	}
+	
+	my $user_info = get_user_info($user_id);
+	if (!$user_info) {
+		notify($ERRORS{'WARNING'}, 0, "unable to determine if user password should be set, user info could not be retrieved for user ID $user_id");
+		return;
+	}
+	
+	my $user_standalone = $user_info->{STANDALONE};
+	
+	# Generate a reservation password if "standalone" (not using Kerberos authentication)
+	if ($user_standalone) {
+		return 1;
+	}
+	else {
+		return 0;
+	}
+}
+
 ##/////////////////////////////////////////////////////////////////////////////
 1;
 __END__

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=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/Ubuntu.pm Wed Dec 17 19:17:12 2014
@@ -240,7 +240,7 @@ sub enable_dhcp {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 changepasswd
+=head2 set_password
 
  Parameters  : $username, $password (optional)
  Returns     : boolean
@@ -250,7 +250,7 @@ sub enable_dhcp {
 
 =cut
 
-sub changepasswd {
+sub set_password {
 	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");

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Wed Dec 17 19:17:12 2014
@@ -925,31 +925,18 @@ sub reserve {
 	
 	notify($ERRORS{'OK'}, 0, "beginning Windows reserve tasks");
 	
-	# Generate a reservation password
-	if (!$self->check_reservation_password()) {
-		notify($ERRORS{'WARNING'}, 0, "failed to generate a reservation password");
-		return;
-	}
-	
-	my $request_forimaging = $self->data->get_request_forimaging();
-	my $reservation_password = $self->data->get_reservation_password();
-	
 	# Check if this is an imaging request or not
-	if ($request_forimaging) {
-		# Imaging request, don't create account, set the Administrator password
+	if ($self->data->get_request_forimaging()) {
+		my $reservation_password = $self->data->get_reservation_password();
+		
+		# Imaging request, set the Administrator password
 		if (!$self->set_password('Administrator', $reservation_password)) {
 			notify($ERRORS{'WARNING'}, 0, "unable to set password for Administrator account");
-			return 0;
-		}
-	}
-	else {
-		# Add the user to the computer
-		if (!$self->create_user()) {
-			notify($ERRORS{'WARNING'}, 0, "unable to add user to computer");
-			return 0;
+			return;
 		}
 	}
 	
+	notify($ERRORS{'OK'}, 0, "Windows reserve tasks complete");
 	return 1;
 } ## end sub reserve
 
@@ -1064,12 +1051,12 @@ sub sanitize {
 		return 0;
 	}
 
-	# Delete the request user
-	if ($self->delete_user()) {
-		notify($ERRORS{'OK'}, 0, "user deleted from $computer_node_name");
+	# Delete the reservation users
+	if ($self->delete_user_accounts()) {
+		notify($ERRORS{'OK'}, 0, "users deleted from $computer_node_name");
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to delete user from $computer_node_name");
+		notify($ERRORS{'WARNING'}, 0, "failed to delete users from $computer_node_name");
 		return 0;
 	}
 
@@ -1743,9 +1730,13 @@ sub user_exists {
 
 =head2 create_user
 
- Parameters  : 
- Returns     : 
- Description : 
+ Parameters  : hash reference
+ Returns     : boolean
+ Description : Creates a user on the computer. The argument must be a hash
+               reference to user parameters. The hash must contain the keys:
+               - username
+               - password
+               - root_access
 
 =cut
 
@@ -1755,50 +1746,44 @@ sub create_user {
 		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 $system32_path        = $self->get_system32_path() || return;
 	
-	my $imagemeta_rootaccess = $self->data->get_imagemeta_rootaccess();
+	my $computer_node_name = $self->data->get_computer_node_name();
+	my $system32_path      = $self->get_system32_path() || return;
 	
-	# Attempt to get the username from the arguments
-	# If no argument was supplied, use the user specified in the DataStructure
-	my $username = shift;
-	my $password = shift;
-	my $uid = shift || 0;
-	my $adminoverride = shift || 0;
-
-	if (!$username) {
-		$username = $self->data->get_user_login_id();
+	my $user_parameters = shift;
+	if (!$user_parameters) {
+		notify($ERRORS{'WARNING'}, 0, "unable to create user, user parameters argument was not provided");
+		return;
 	}
-	if (!$password) {
-		$password = $self->data->get_reservation_password() || return;
+	elsif (!ref($user_parameters) || ref($user_parameters) ne 'HASH') {
+		notify($ERRORS{'WARNING'}, 0, "unable to create user, argument provided is not a hash reference");
+		return;
 	}
 	
-	# If imagemeta allows rootaccess, check the adminoverride variable
-	# Does not allow for override called from manage_server_access 
-	# 1 - allow admin access, set $imagemeta_rootaccess=1
-	# 2 - disallow admin access, set $imagemeta_rootaccess=0
-	if ($imagemeta_rootaccess) {
-		if ($adminoverride eq '1') {
-			$imagemeta_rootaccess = 1;
-		}
-		elsif ($adminoverride eq '2') {
-			$imagemeta_rootaccess = 0;
-		}
+	my $username = $user_parameters->{username};
+	if (!defined($username)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, argument hash does not contain a 'username' key:\n" . format_data($user_parameters));
+		return;
 	}
-
+	
+	my $password = $user_parameters->{password};
+	if (!defined($password)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, argument hash does not contain a 'password' key:\n" . format_data($user_parameters));
+		return;
+	}
+	
+	my $root_access = $user_parameters->{root_access};
+	if (!defined($root_access)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create user on $computer_node_name, argument hash does not contain a 'root_access' key:\n" . format_data($user_parameters));
+		return;
+	}
+	
 	# Check if user already exists
 	if ($self->user_exists($username)) {
-		notify($ERRORS{'OK'}, 0, "user $username already exists on $computer_node_name, attempting to delete user");
-
-		# Attempt to delete the user
-		if (!$self->delete_user($username)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to add user $username to $computer_node_name, user already exists and could not be deleted");
-			return 0;
-		}
+		notify($ERRORS{'WARNING'}, 0, "unable to create user '$username' on $computer_node_name, the user already exists");
+		return;
 	}
-
+	
 	notify($ERRORS{'DEBUG'}, 0, "attempting to add user $username to $computer_node_name ($password)");
 
 	# Attempt to add the user account
@@ -1806,14 +1791,14 @@ sub create_user {
 	$add_user_command .= " && $system32_path/net.exe localgroup \"Remote Desktop Users\" \"$username\" /ADD";
 	
 	# Add the user to the Administrators group if imagemeta.rootaccess isn't 0
-	if (defined($imagemeta_rootaccess) && $imagemeta_rootaccess eq '0') {
-		notify($ERRORS{'DEBUG'}, 0, "user will NOT be added to the Administrators group");
-	}
-	else {
+	if ($root_access) {
 		notify($ERRORS{'DEBUG'}, 0, "user will be added to the Administrators group");
 		$add_user_command .= " && $system32_path/net.exe localgroup \"Administrators\" \"$username\" /ADD";
 	}
-
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "user will NOT be added to the Administrators group");
+	}
+	
 	my ($add_user_exit_status, $add_user_output) = $self->execute($add_user_command, '1');
 	if (defined($add_user_exit_status) && $add_user_exit_status == 0) {
 		notify($ERRORS{'OK'}, 0, "added user $username ($password) to $computer_node_name");

Modified: vcl/trunk/managementnode/lib/VCL/Module/State.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/State.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/State.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/State.pm Wed Dec 17 19:17:12 2014
@@ -225,6 +225,8 @@ sub initialize {
 		notify($ERRORS{'DEBUG'}, 0, "child reservation, not updating request state to 'pending'");
 	}
 	
+	notify($ERRORS{'DEBUG'}, 0, "computerloadlog states after state object is initialized:\n" . format_data(get_request_loadstate_names($request_id)));
+	
 	return 1;
 } ## end sub initialize
 
@@ -722,15 +724,6 @@ sub state_exit {
 				}
 			}
 		}
-
-		if ($request_state_name_old =~ /complete|timeout|deleted/) {
-			
-			delete_computerloadlog_reservation(\@reservation_ids,0,1);
-		}
-		
-		# Delete all computerloadlog rows with loadstatename = 'begin' for all reservations in this request
-		# beginacknowledgetimeout required for web gui
-		delete_computerloadlog_reservation(\@reservation_ids, 'begin',1);
 		
 		# Update log.ending if this is the parent reservation and argument was supplied
 		if ($request_log_ending) {
@@ -752,6 +745,18 @@ sub state_exit {
 		}
 	}
 	
+	# Clean computerloadlog as late as possible
+	if ($is_parent_reservation) {
+		if ($request_state_name_old =~ /(new|reserved)/) {
+			# Only delete computerloadlog entries with loadstatename = 'begin' for all reservations in this request
+			delete_computerloadlog_reservation(\@reservation_ids, '(begin)');
+		}
+		else {
+			# Delete all computerloadlog entries for all reservations in this request
+			delete_computerloadlog_reservation(\@reservation_ids);
+		}
+	}
+	
 	# Insert a computerloadlog 'exited' entry
 	# This is used by the parent cluster reservation
 	insertloadlog($reservation_id, $computer_id, "exited", "vcld process exiting");
@@ -801,6 +806,7 @@ sub DESTROY {
 			my @reservation_ids = $self->data->get_reservation_ids();
 			if (@reservation_ids && $request_id) {
 				$self->state_exit();
+				notify($ERRORS{'DEBUG'}, 0, "computerloadlog states remaining after process exits:\n" . format_data(get_request_loadstate_names($request_id)));
 			}
 			elsif (!$SETUP_MODE) {
 				notify($ERRORS{'WARNING'}, 0, "failed to retrieve the reservation ID, computerloadlog 'begin' rows not removed");

Modified: vcl/trunk/managementnode/lib/VCL/inuse.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/inuse.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/inuse.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/inuse.pm Wed Dec 17 19:17:12 2014
@@ -116,7 +116,17 @@ sub process {
 	my $is_parent_reservation   = $self->data->is_parent_reservation();
 	my $computer_id             = $self->data->get_computer_id();
 	my $computer_short_name     = $self->data->get_computer_short_name();
-	my $connect_timeout_seconds = $self->os->get_timings('connecttimeout');
+	
+	
+	my $connect_timeout_seconds;
+	if ($request_laststate_name eq 'reserved') {
+		$connect_timeout_seconds = $self->os->get_timings('initialconnecttimeout');
+		notify($ERRORS{'DEBUG'}, 0, "checking for initial user connection, using 'initialconnecttimeout' variable: $connect_timeout_seconds seconds");
+	}
+	else {
+		$connect_timeout_seconds = $self->os->get_timings('reconnecttimeout');
+		notify($ERRORS{'DEBUG'}, 0, "checking for subsequent connection, using 'reconnecttimeout' variable: $connect_timeout_seconds seconds");
+	}
 
 	# Make sure connect timeout is long enough
 	# It has to be a bit longer than the ~5 minute period between inuse checks due to cluster reservations
@@ -142,14 +152,12 @@ sub process {
 	
 	# Check if server reservation has been modified
 	if ($request_state_name =~ /servermodified/) {
-		if (!$self->os->manage_server_access()) {
+		if (!$self->os->add_user_accounts()) {
 			notify($ERRORS{'CRITICAL'}, 0, "failed to update server access");
       }
-		
 		$self->state_exit('inuse', 'inuse');
 	}
 	
-	
 	my $now_epoch_seconds = time;
 	
 	my $request_start_epoch_seconds = convert_to_epoch_seconds($request_start);
@@ -298,12 +306,23 @@ sub process {
 		$self->state_exit('inuse', 'inuse');
 	}
 	
+	# Insert connecttimeout immediately before beginning to check for user connection
+	# Web uses timestamp of this to determine when next to refresh the page
+	# Important because page should refresh as soon as possible to reservation timing out
+	if ($request_laststate_name eq 'reserved') {
+		insertloadlog($reservation_id, $computer_id, "connecttimeout", "begin initial connection timeout ($connect_timeout_seconds seconds)");
+	}
+	else {
+		insertloadlog($reservation_id, $computer_id, "connecttimeout", "begin reconnection timeout ($connect_timeout_seconds seconds)");
+	}
+	
 	# Check to see if user is connected. user_connected will true(1) for servers and requests > 24 hours
-	if (!$self->code_loop_timeout(sub{$self->user_connected()}, [], "waiting for user to connect to $computer_short_name", ($connect_timeout_minutes*60), 15)) {
-		
-		# Remove rows from computerloadlog for this reservation if connected, don't remove the loadstate=begin row
-		delete_computerloadlog_reservation($reservation_id, '!beginacknowledgetimeout');
-
+	my $user_connected = $self->code_loop_timeout(sub{$self->user_connected()}, [], "waiting for user to connect to $computer_short_name", $connect_timeout_seconds, 15);
+	
+	# Delete the connecttimeout immediately after acknowledgement loop ends
+	delete_computerloadlog_reservation($reservation_id, 'connecttimeout');
+	
+	if (!$user_connected) {
 		if (!$imagemeta_checkuser || !$request_checkuser) {
 			notify($ERRORS{'OK'}, 0, "never detected user connection, skipping timeout, imagemeta checkuser: $imagemeta_checkuser, request checkuser: $request_checkuser");
 		}
@@ -386,9 +405,7 @@ sub user_connected {
 	
 	# Check if this is an imaging request, causes process to exit if state or laststate = image
 	$self->_check_imaging_request();
-
-	delete_computerloadlog_reservation($reservation_id, '!beginacknowledgetimeout',1);
-
+	
 	# Check if this is a server request, causes process to exit if server request
 	if ($server_request_id) {
 		notify($ERRORS{'DEBUG'}, 0, "server reservation detected, set as user is connected");
@@ -397,7 +414,7 @@ sub user_connected {
 	}
 	
 	# If duration is >= 24 hrs set as connected and return
-	if ($request_duration_hrs >= $ignore_connections_gte ) {
+	if ($request_duration_hrs >= $ignore_connections_gte) {
 		notify($ERRORS{'OK'}, 0, "reservation duration is $request_duration_hrs hrs is >= to ignore_connections setting $ignore_connections_gte hrs, skipping inuse checks");
 		insertloadlog($reservation_id, $computer_id, "connected", "user connected to $computer_short_name");
 		return 1;

Modified: vcl/trunk/managementnode/lib/VCL/reclaim.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reclaim.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reclaim.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reclaim.pm Wed Dec 17 19:17:12 2014
@@ -101,9 +101,6 @@ sub process {
 	my $public_ip_configuration             = $self->data->get_management_node_public_ip_configuration() || return;
 	my @reservation_ids                     = $self->data->get_reservation_ids();
 
-	# Delete all computerloadlog rows with loadstatename = 'beginacknowledgetimeout' for all reservations in this request
-	delete_computerloadlog_reservation(\@reservation_ids,0,1);
-
 	# Remove related fixedIPsr variable, if it exists
 	if ($server_request_id) {
 		my $variable_name = "fixedIPsr" . $server_request_id;
@@ -168,12 +165,12 @@ sub process {
 	elsif ($request_laststate_name =~ /reserved/) {
 		notify($ERRORS{'DEBUG'}, 0, "request laststate is $request_laststate_name, checking if computer table current image matches image currently loaded on $computer_shortname");
 		
-		# If server reservations and in reserved - reload
-		if ($server_request_id) {
-			notify($ERRORS{'DEBUG'}, 0, "Detected server reservations, computer will be reloaded");
-			$self->insert_reload_and_exit();
-		}
-
+		## If server reservations and in reserved - reload
+		#if ($server_request_id) {
+		#	notify($ERRORS{'DEBUG'}, 0, "Detected server reservations, computer will be reloaded");
+		#	$self->insert_reload_and_exit();
+		#}
+		
 		# Make sure computer current image name was retrieved from the database
 		if (!$computer_currentimage_name) {
 			notify($ERRORS{'WARNING'}, 0, "failed to retrieve computer current image name from the database, computer will be reloaded");

Modified: vcl/trunk/managementnode/lib/VCL/reserved.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reserved.pm Wed Dec 17 19:17:12 2014
@@ -102,8 +102,6 @@ sub process {
 	my $is_parent_reservation       = $self->data->is_parent_reservation();
 	my $server_request_id           = $self->data->get_server_request_id();
 	my $acknowledge_timeout_seconds = $self->os->get_timings('acknowledgetimeout');
-
-	insertloadlog($reservation_id, $computer_id, "beginacknowledgetimeout", "begin connect timeout");
 	
 	# Update the log loaded time to now for this request
 	update_log_loaded_time($request_logid);
@@ -113,21 +111,27 @@ sub process {
 	update_computer_state($computer_id, 'reserved');
 	insertloadlog($reservation_id, $computer_id, "reserved", "$computer_short_name successfully reserved");
 	
+	# Insert acknowledgetimeout immediately before beginning to check user clicked Connect
+	# Web uses timestamp of this to determine when next to refresh the page
+	# Important because page should refresh as soon as possible to reservation timing out
+	insertloadlog($reservation_id, $computer_id, "acknowledgetimeout", "begin acknowledge timeout ($acknowledge_timeout_seconds seconds)");
+	
 	# Wait for the user to acknowledge the request by clicking Connect button or from API
-	if (!$self->code_loop_timeout(sub{$self->user_acknowledged()}, [], 'waiting for user acknowledgement', $acknowledge_timeout_seconds, 1, 10)) {
+	my $user_acknowledged = $self->code_loop_timeout(sub{$self->user_acknowledged()}, [], 'waiting for user acknowledgement', $acknowledge_timeout_seconds, 1, 10);
+	
+	# Add noinitialconnection and then delete acknowledgetimeout
+	insertloadlog($reservation_id, $computer_id, "noinitialconnection", "user clicked Connect");
+	delete_computerloadlog_reservation($reservation_id, 'acknowledgetimeout');
+	
+	if (!$user_acknowledged) {
 		$self->_notify_user_timeout($request_data);
 		switch_state($request_data, 'timeout', 'timeout', 'noack', 1);
 	}
-
+	
 	# Call OS module's grant_access() subroutine which adds user accounts to computer
 	if ($self->os->can("grant_access") && !$self->os->grant_access()) {
 		$self->reservation_failed("OS module grant_access failed");
 	}
-
-	# Add additional user accounts, perform other configuration tasks if this is a server request
-	if ($server_request_id && !$self->os->manage_server_access()) {
-		$self->reservation_failed("OS module manage_server_access failed");
-	}
 	
 	# User acknowledged request
 	# Add the cluster information to the loaded computers if this is a cluster reservation

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1646314&r1=1646313&r2=1646314&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Wed Dec 17 19:17:12 2014
@@ -93,6 +93,7 @@ our @ISA = qw(Exporter);
 our @EXPORT = qw(
 	_pingnode
 	add_imageid_to_newimages
+	add_reservation_account
 	check_blockrequest_time
 	check_endtimenotice_interval
 	check_ssh
@@ -106,6 +107,7 @@ our @EXPORT = qw(
 	database_select
 	delete_computerloadlog_reservation
 	delete_request
+	delete_reservation_account
 	delete_variable
 	determine_remote_connection_target
 	escape_file_path
@@ -267,7 +269,6 @@ our @EXPORT = qw(
 	update_preload_flag
 	update_request_checkuser
 	update_request_state
-	update_reservation_accounts
 	update_reservation_lastcheck
 	update_reservation_password
 	update_sublog_ipaddress
@@ -280,6 +281,7 @@ our @EXPORT = qw(
 	$DAEMON_MODE
 	$DATABASE
 	$DEFAULTHELPEMAIL
+	$EXECUTE_NEW
 	$FQDN
 	$LOGFILE
 	$MYSQL_SSL
@@ -344,6 +346,7 @@ our $VERBOSE;
 our $CONF_FILE_PATH;
 our $DAEMON_MODE;
 our $SETUP_MODE;
+our $EXECUTE_NEW;
 
 
 INIT {
@@ -375,6 +378,7 @@ INIT {
 		'help' => \&help,
 		'setup!' => \$SETUP_MODE,
 		'verbose!' => \$VERBOSE,
+		'exn!' => \$EXECUTE_NEW,
 	);
 	
 	my %parameters = (
@@ -475,6 +479,10 @@ INIT {
 	elsif (!defined($DAEMON_MODE)) {
 		$DAEMON_MODE = 1;
 	}
+	elsif (!defined($EXECUTE_NEW)) {
+		$EXECUTE_NEW = 0;
+	}
+	$ENV{execute_new} = $EXECUTE_NEW;
 	
 	# Set boolean variables to 0 or 1, they may be set to 'no' or 'yes' in the conf file
 	for ($MYSQL_SSL, $JABBER, $VERBOSE, $DAEMON_MODE, $SETUP_MODE) {
@@ -1768,8 +1776,8 @@ sub is_request_imaging {
 
 =head2 get_reservation_accounts
 
- Parameters  : $reservationid
- Returns     : 
+ Parameters  : $reservation_id
+ Returns     : hash reference
  Description : Used for server loads, provides list of users for group access
 
 =cut
@@ -1781,43 +1789,38 @@ sub get_reservation_accounts {
 		return 0;
 	}
 	
-	my $select_statement = "
-		SELECT DISTINCT
-		reservationaccounts.userid AS reservationaccounts_userid,
-		reservationaccounts.password AS reservationaccounts_password,
-		affiliation.name AS affiliation_name,
-		user.unityid AS user_name
-		FROM
-		reservationaccounts,
-		affiliation,
-		user
-		WHERE
-		user.id = reservationaccounts.userid AND
-		affiliation.id = user.affiliationid AND
-		reservationaccounts.reservationid = $reservation_id
-	";
+	my $select_statement = <<EOF;
+SELECT DISTINCT
+reservationaccounts.userid AS reservationaccounts_userid,
+reservationaccounts.password AS reservationaccounts_password,
+affiliation.name AS affiliation_name,
+user.unityid AS user_name
+
+FROM
+reservationaccounts,
+affiliation,
+user
+
+WHERE
+user.id = reservationaccounts.userid
+AND affiliation.id = user.affiliationid
+AND reservationaccounts.reservationid = $reservation_id
+EOF
 	
 	# Call the database select subroutine
 	# This will return an array of one or more rows based on the select statement
 	my @selected_rows = database_select($select_statement);
 	
-	my @ret_array;
-	my %user_info;
-	
-	# Check to make sure 1 or more rows were returned
-	if (scalar @selected_rows > 0) {
-		# It contains a hash
-		for (@selected_rows) {
-			my %reservation_acct= %{$_};
-			my $userid = $reservation_acct{reservationaccounts_userid};
-			$user_info{$userid}{"userid"} = $userid;
-			$user_info{$userid}{"password"} = $reservation_acct{reservationaccounts_password};
-			$user_info{$userid}{"affiliation"} = $reservation_acct{affiliation_name};
-			$user_info{$userid}{"username"} = $reservation_acct{user_name};
-		}
-		return %user_info;
+	my $reservation_accounts = {};
+	for my $row (@selected_rows) {
+		my $user_id = $row->{reservationaccounts_userid};
+		$reservation_accounts->{$user_id}{"userid"} = $user_id;
+		$reservation_accounts->{$user_id}{"password"} = $row->{reservationaccounts_password};
+		$reservation_accounts->{$user_id}{"affiliation"} = $row->{affiliation_name};
+		$reservation_accounts->{$user_id}{"username"} = $row->{user_name};
 	}
-	return ();
+	
+	return $reservation_accounts;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1879,42 +1882,35 @@ EOF
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 update_reservation_accounts
+=head2 add_reservation_account
 
- Parameters  : $reservation_id, $userid, $password, $mode
+ Parameters  : $reservation_id, $userid, $password
  Returns     : boolean
- Description : 
+ Description : Adds an entry to the reservationaccounts table.
 
 =cut
 
-sub update_reservation_accounts {
-	my $reservation_id = shift;
-	my $user_id = shift;
-	my $password = shift;
-	my $mode = shift;
-	
-	if (!$mode) {
-		notify($ERRORS{'WARNING'}, 0, "mode argument was not specified, it must be either add or delete");
-		return;
-	}
+sub add_reservation_account {
+	my ($reservation_id, $user_id, $password) = @_;
 	
 	if (!$reservation_id) {
 		notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not specified");
 		return;
 	}
-	
-	if (!$user_id) {
+	elsif (!$user_id) {
 		notify($ERRORS{'WARNING'}, 0, "user ID argument was not specified");
 		return;
 	}
 	
-	if (!$password) {
-		$password = '';
+	my $password_string;
+	if ($password) {
+		$password_string = "'$password'";
+	}
+	else {
+		$password_string = 'NULL';
 	}
 	
-	my $statement;
-	if ($mode =~ /add/i) {
-		$statement = <<EOF;
+	my $statement = <<EOF;
 INSERT IGNORE INTO 
 reservationaccounts
 (
@@ -1926,31 +1922,53 @@ VALUES
 (
 	'$reservation_id',
 	'$user_id',
-	'$password'
+	$password_string
 )
-ON DUPLICATE KEY UPDATE password = '$password'
+ON DUPLICATE KEY UPDATE password = $password_string
 EOF
+	
+	if (!database_execute($statement)) {
+		notify($ERRORS{'OK'}, 0, "failed to add user $user_id to reservationaccounts table");
+		return;
 	}
-	elsif ($mode =~ /delete/i) {
-		$statement = <<EOF;
-DELETE 
-reservationaccounts
-FROM
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 delete_reservation_account
+
+ Parameters  : $reservation_id, $userid
+ Returns     : boolean
+ Description : Deletes an entry from the reservationaccounts table.
+
+=cut
+
+sub delete_reservation_account {
+	my ($reservation_id, $user_id) = @_;
+	
+	if (!$reservation_id) {
+		notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not specified");
+		return;
+	}
+	elsif (!$user_id) {
+		notify($ERRORS{'WARNING'}, 0, "user ID argument was not specified");
+		return;
+	}
+	
+	my $statement = <<EOF;
+DELETE FROM
 reservationaccounts
 WHERE
-reservationid = '$reservation_id' AND
-userid = '$user_id' 
+reservationid = '$reservation_id'
+AND userid = '$user_id' 
 EOF
+
+	if (!database_execute($statement)) {
+		notify($ERRORS{'OK'}, 0, "failed to delete user $user_id from reservationaccounts table");
+		return;
 	}
-	
-	if (database_execute($statement)) {
-		#notify($ERRORS{'OK'}, 0, "executed $statement $reservation_id $user_id");
-		return 1;
-	}
-	else {
-		notify($ERRORS{'OK'}, 0, "failed to to execute statement to update reservationaccounts table:\n$statement");
-		return 0;
-	}
+	return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -3964,7 +3982,7 @@ sub run_ssh_command {
 		$port = $arguments->{port} || '22';
 		$output_level = $arguments->{output_level};
 		$max_attempts = $arguments->{max_attempts} || 3;
-		$timeout_seconds = $arguments->{timeout};
+		$timeout_seconds = $arguments->{timeout_seconds};
 	}
 	
 	# Determine the output level if it was specified
@@ -4224,7 +4242,7 @@ sub run_ssh_command {
 			}
 		}
 		elsif ($exit_status == 255 && $ssh_command !~ /(vmware-cmd|vim-cmd|vmkfstools|vmrun)/i) {
-			notify($ERRORS{'WARNING'}, 0, "attempt $attempts/$max_attempts: failed to execute SSH command on $node_string: '$command', exit status: $exit_status, SSH exits with the exit status of the remote command or with 255 if an error occurred, output:\n$ssh_output_formatted") if $output_level;
+			notify($ERRORS{'WARNING'}, 0, "attempt $attempts/$max_attempts: failed to execute SSH command on $node_string: '$command', exit status: $exit_status, SSH exits with the exit status of the remote command or with 255 if an error occurred, output $output_level:\n$ssh_output_formatted") if $output_level;
 			next;
 		}
 		else {
@@ -5519,30 +5537,37 @@ EOF
 
 =head2 delete_computerloadlog_reservation
 
- Parameters  : $reservation_id, $loadstatename (optional), $immediate (optional)
+ Parameters  : $reservation_id_argument, $loadstate_regex (optional)
  Returns     : boolean
- Description : Deletes rows from the computerloadlog table. A loadstatename
-               argument can be specified to limit the rows removed to a
-               certain loadstatename value. To delete all rows except those
-               matching a certain loadstatename, begin the loadstatename
-               with a !. The $reservation_id argument may either be a single
-               integer or an array reference. A immediate option can be specified 
-					to clear all entries
+ Description : Deletes rows from the computerloadlog table.
+               
+               The $reservation_id argument may be either a single integer ID or
+               a reference to an array of integer IDs.
+               
+               A $loadstate_regex argument can be specified to limit the rows
+               removed to a certain loadstate names. The regex does not allow
+               all of the functionality of a Perl regex such as (?!...).
+               
+               To delete multiple loadstate names, pass something such as:
+               (begin|info)
+               
+               To delete all entries except certain loadstate names, precede the
+               expression with an exclaimation mark:
+               !(begin|info)              
 
 =cut
 
 sub delete_computerloadlog_reservation {
 	my $reservation_id_argument = shift;
-	my $loadstatename = shift;
-	my $immediate = shift;
-
+	my $loadstate_regex = shift;
 
 	# Check the passed parameter
-	unless (defined($reservation_id_argument) ) {
-		notify($ERRORS{'WARNING'}, 0, "reservation_id_argument argument were not specified");
+	if (!defined($reservation_id_argument)) {
+		notify($ERRORS{'WARNING'}, 0, "reservation ID argument were not specified");
 		return;
 	}
 	
+	# Check if a single reservation ID was specified or an array of IDs
 	my $reservation_id_string;
 	if (ref($reservation_id_argument)) {
 		$reservation_id_string = join(', ', @$reservation_id_argument);
@@ -5550,11 +5575,6 @@ sub delete_computerloadlog_reservation {
 	else {
 		$reservation_id_string = $reservation_id_argument;
 	}
-
-	if (!defined($immediate)) {
-		$immediate =0;
-	}
-
 	
 	# Construct the SQL statement
 	my $sql_statement = <<EOF;
@@ -5569,40 +5589,29 @@ computerloadlog.reservationid IN ($reser
 AND computerloadlog.loadstateid = computerloadstate.id
 EOF
 	
+	
 	# Check if loadstateid was specified
 	# If so, only delete rows matching the loadstateid
-	if ($loadstatename && $loadstatename !~ /^!/) {
-		notify($ERRORS{'DEBUG'}, 0, "removing computerloadlog entries matching loadstate = $loadstatename");
-		$sql_statement .= "AND computerloadstate.loadstatename = \'$loadstatename\'";
-	}
-	elsif ($loadstatename) {
-		# Remove the first character of loadstatename, it is !
-		my $modified_loadstatename = substr($loadstatename, 1);
-		notify($ERRORS{'DEBUG'}, 0, "removing computerloadlog entries NOT matching loadstate = $modified_loadstatename");
-		$sql_statement .= "AND computerloadstate.loadstatename != \'$modified_loadstatename\'";
-	}
-	else {
-		notify($ERRORS{'DEBUG'}, 0, "removing all computerloadlog entries for reservation");
-	}
-
-	#Only remove entries older than 2 minutes	unless the immediate flag
-	unless ($immediate) {
-		$sql_statement .= " AND timestamp <= (NOW() - INTERVAL 2 Minute);";
+	my $regex_string = '';
+	if ($loadstate_regex) {
+		if ($loadstate_regex =~ /^\!/) {
+			$loadstate_regex =~ s/^\!//;
+			$regex_string = " NOT matching loadstate regex '$loadstate_regex'";
+			$sql_statement .= "AND computerloadstate.loadstatename NOT REGEXP '$loadstate_regex'";
+		}
+		else {
+			$regex_string = " matching loadstate regex '$loadstate_regex'";
+			$sql_statement .= "AND computerloadstate.loadstatename REGEXP '$loadstate_regex'";
+		}
 	}
 	
 	# Call the database execute subroutine
 	if (database_execute($sql_statement)) {
-		if ($loadstatename) {
-			notify($ERRORS{'OK'}, 0, "deleted rows from computerloadlog matching loadstate '$loadstatename' for reservation IDs: $reservation_id_string");
-		}
-		else {
-			notify($ERRORS{'OK'}, 0, "deleted all rows from computerloadlog for reservation IDs: $reservation_id_string");
-		}
-		
+		notify($ERRORS{'OK'}, 0, "deleted rows from computerloadlog$regex_string for reservation IDs: $reservation_id_string");
 		return 1;
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "unable to delete from computerloadlog table for reservation IDs: $reservation_id_string");
+		notify($ERRORS{'WARNING'}, 0, "failed to delete from computerloadlog table for reservation IDs: $reservation_id_string");
 		return 0;
 	}
 } ## end sub delete_computerloadlog_reservation