sub add_user_accounts()

in managementnode/lib/VCL/Module/OS.pm [368:504]


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 $use_public_keys = $reservation_users->{$user_id}{usepublickeys};
		
		# If the $use_public_keys flag is set, retrieve the keys
		my $ssh_public_keys;
		if ($use_public_keys) {
			$ssh_public_keys = $reservation_users->{$user_id}{sshpublickeys};
		}
		
		my $password;
		
		# Check if entry needs to be added to the useraccounts table
		if (defined($reservation_accounts->{$user_id}) && ($request_state_name =~ /servermodified/)) {
			# Entry already exists in useraccounts table and is servermodified, assume everything is correct skip to next user
			notify($ERRORS{'DEBUG'}, 0, "entry already exists in useraccounts table for $username (ID: $user_id) and request_state_name = $request_state_name");
			
			# Make sure user's root access is correct - may have been moved from admin to access group, and vice versa
			if ($root_access) {
				$self->grant_administrative_access($username) if ($self->can('grant_administrative_access'));
			}
			else {
				$self->revoke_administrative_access($username) if ($self->can('revoke_administrative_access'));
			}
			
			next RESERVATION_USER;
		}
		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;
			}

			# 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)");
				}
				
				return;
			}
		}
	}
	
	# 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;
}