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 2015/12/10 21:45:35 UTC

svn commit: r1719206 [1/2] - in /vcl/trunk: managementnode/lib/VCL/ mysql/

Author: arkurth
Date: Thu Dec 10 20:45:35 2015
New Revision: 1719206

URL: http://svn.apache.org/viewvc?rev=1719206&view=rev
Log:
VCL-919
Added DataStructure.pm::can subroutine.

Updated utils.pm::get_calling_subroutine to go up another level if the caller is _ANON_. This allows it to return something useful for automethod subroutines from DataStructure.pm.

Updated utils.pm::get_affiliation_info to accept an affiliation name or ID argument instead of only an ID.

Changed utils.pm::set_variable to not alter the value by escaping backslashes. This was causing inconsistency in the user message text variables.

Added subroutines to Module.pm:
_get_message_variable
get_user_message
get_user_short_message
get_admin_message
set_admin_message_variable
set_user_message_variable

Removed hard-coded message text from the following and replaced with calls to the new Module.pm subroutines:
image.pm
inuse.pm
makeproduction.pm
reserved.pm

Modified:
    vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    vcl/trunk/managementnode/lib/VCL/Module.pm
    vcl/trunk/managementnode/lib/VCL/image.pm
    vcl/trunk/managementnode/lib/VCL/inuse.pm
    vcl/trunk/managementnode/lib/VCL/makeproduction.pm
    vcl/trunk/managementnode/lib/VCL/reserved.pm
    vcl/trunk/managementnode/lib/VCL/utils.pm
    vcl/trunk/mysql/update-vcl.sql
    vcl/trunk/mysql/vcl.sql

Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Thu Dec 10 20:45:35 2015
@@ -764,7 +764,7 @@ sub _initialize : Init {
 
 =head2 automethod
 
- Parameters  : None
+ Parameters  : $show_warnings (optional)
  Returns     : Data based on the method name, 0 if method was not handled
  Description : This subroutine is automatically invoked when an class method is
                called on a DataStructure object but the method isn't explicitly
@@ -808,11 +808,21 @@ sub _automethod : Automethod {
 	elsif ($mode =~ /get/ && defined $args[0] && !$args[0]) {
 		$show_warnings = 0;
 	}
-
+	
+	my $calling_subroutine = get_calling_subroutine();
+	
 	# Check if the sub name is defined in the subroutine mappings hash
 	# Return if it isn't
 	if (!defined $SUBROUTINE_MAPPINGS{$data_identifier}) {
-		notify($ERRORS{'WARNING'}, 0, "unsupported subroutine name: $method_name");
+		if ($calling_subroutine eq 'VCL::DataStructure::can') {
+			return;
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "unsupported subroutine name: $method_name");
+			return sub { };
+		}
+	}
+	elsif ($calling_subroutine eq 'VCL::DataStructure::can') {
 		return sub { };
 	}
 
@@ -888,20 +898,20 @@ sub _automethod : Automethod {
 			# Just attempt to retrieve the value from the hash path
 			$return_value = eval $hash_path;
 		}
-
+		
 		if (!defined $return_value) {
 			if ($show_warnings && $method_name !~ /^(get_management_node_keys)$/) {
 				notify($ERRORS{'WARNING'}, 0, "corresponding data is undefined for $method_name: $hash_path");
 			}
 			return sub { };
 		}
-
+		
 		# Return the data
 		return sub {$return_value;};
 	} ## end if ($mode =~ /get/)
 	elsif ($mode =~ /set/) {
 		eval $hash_path . ' = $set_data';
-
+		
 		# Make sure the value was set in the hash
 		my $check_value = eval $hash_path;
 		if ($check_value eq $set_data) {
@@ -931,6 +941,35 @@ sub get_request_data {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 can
+
+ Parameters  : $function_name
+ Returns     : boolean
+ Description : Determines if this module supports a particular function.
+
+=cut
+
+sub can {
+	my $self = shift;
+	
+	my $function_name = shift;
+	if (!defined($function_name)) {
+		notify($ERRORS{'WARNING'}, 0, "function name argument is not implemented");
+		return;
+	}
+	
+	if ($self->SUPER::can($function_name)) {
+		#notify($ERRORS{'DEBUG'}, 0, "function is implemented: $function_name");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "function is NOT implemented: $function_name");
+		return 0;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 =head2 refresh
 

Modified: vcl/trunk/managementnode/lib/VCL/Module.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Thu Dec 10 20:45:35 2015
@@ -82,6 +82,9 @@ use 5.008000;
 use strict;
 use warnings;
 use diagnostics;
+
+no warnings 'redefine';
+
 use English '-no_match_vars';
 use Digest::SHA1 qw(sha1_hex);
 
@@ -1557,6 +1560,418 @@ sub does_semaphore_exist {
 }
 
 #/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_admin_message_variable
+
+ Parameters  : $admin_message_key, $subject, $message, $substitution_hashref (optional)
+ Returns     : boolean
+ Description : Sets an administrative message variable in the database.
+
+=cut
+
+sub set_admin_message_variable {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($admin_message_key, $subject, $message, $substitution_hashref) = @_;
+	if (!defined($admin_message_key)) {
+		notify($ERRORS{'WARNING'}, 0, "message key argument was not supplied");
+		return;
+	}
+	elsif (!defined($subject)) {
+		notify($ERRORS{'WARNING'}, 0, "subject argument was not supplied\n" . format_data(\@_));
+		return;
+	}
+	elsif (!defined($message)) {
+		notify($ERRORS{'WARNING'}, 0, "message argument was not supplied");
+		return;
+	}
+	
+	my $variable_name = "adminmessage|$admin_message_key";
+	
+	my $variable_value = {
+		subject => $subject,
+		message => $message,
+		substitutions => $substitution_hashref,
+	};
+	
+	if (!set_variable($variable_name, $variable_value)) {
+		return;
+	}
+	
+	# Test retrieving the variable
+	return $self->get_admin_message($admin_message_key, $substitution_hashref);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 set_user_message_variable
+
+ Parameters  : $user_message_key, $affiliation_identifier, $subject, $message, $short_message (optional), $substitution_hashref (optional)
+ Returns     : boolean
+ Description : Sets a user message variable in the database.
+
+=cut
+
+sub set_user_message_variable {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($user_message_key, $affiliation_identifier, $subject, $message, $short_message, $substitution_hashref) = @_;
+	if (!defined($user_message_key)) {
+		notify($ERRORS{'WARNING'}, 0, "key argument was not supplied");
+		return;
+	}
+	elsif (!defined($affiliation_identifier)) {
+		notify($ERRORS{'WARNING'}, 0, "affiliation identifier argument was not supplied");
+		return;
+	}
+	elsif (!defined($subject)) {
+		notify($ERRORS{'WARNING'}, 0, "subject argument was not supplied\n" . format_data(\@_));
+		return;
+	}
+	elsif (!defined($message)) {
+		notify($ERRORS{'WARNING'}, 0, "message argument was not supplied");
+		return;
+	}
+	
+	
+	# Determine the affiliation name from the $affiliation_identifier argument
+	my $affiliation_info = get_affiliation_info($affiliation_identifier);
+	if (!$affiliation_info) {
+		notify($ERRORS{'WARNING'}, 0, "failed to set user message variable, affiliation info could not be retrieved for identifier argument: '$affiliation_identifier'");
+		return;
+	}
+	my $affiliation_name = $affiliation_info->{name};
+	
+	my $variable_name = "usermessage|$user_message_key|$affiliation_name";
+	
+	my $variable_value = {
+		subject => $subject,
+		message => $message,
+		short_message => $short_message,
+		substitutions => $substitution_hashref,
+	};
+	
+	if (!set_variable($variable_name, $variable_value)) {
+		return;
+	}
+	
+	# Test retrieving the variable
+	return $self->_get_message_variable($user_message_key, $substitution_hashref);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_message_variable
+
+ Parameters  : $message_key, $substitution_hashref (optional), $return_short_message (optional), $admin_message (optional)
+ Returns     : array context, array: ($subject, $message)
+               scalar context, string: $message
+ Description : Retrieves message components from the variable table in the
+               database. This is a helper subroutine and should not be called
+               directly from outside this module file.
+               
+               The composition of the variable.name field varies based on
+               whether the message is intended for end users or for
+               administrators of the VCL system. variable.name will begin with
+               either of the following:
+               usermessage|
+               adminmessage|
+               
+               The $message_key argument is a string that identifies the
+               message to retrieve. It is treated the same for both user and
+               admin-intended messages.
+               
+               Admin-intended messages cannot be customized per affiliation. The
+               composition of variable.name is as follows:
+               adminmessage|<Message Key>
+               
+               Example:
+               adminmessage|image_creation_failed
+               
+               User-intended messages may be customized based on the user's
+               affiliation and the variable.name field contains an additional
+               affiliation name component:
+               usermessage|<Message Key>|<Affiliation Name>
+               
+               Example:
+               usermessage|timeout_inactivity|Global
+               
+               The database schema contains default message entries for the
+               'Global' affiliation. For user-intended messages, if there is an
+               entry that matches the user's affiliation name, that message will
+               be returned. If not, the Global affiliation message will be
+               returned by default.
+               
+               The variable.value field contains a YAML-encoded hash data
+               structure. The following hash keys are recognized:
+               * subject (required)
+               * message (required)
+               * short_message (optional)
+               * substitutions (optional)
+               
+               The subject and message values will be used when sending email
+               messages. The short_message key is optional and will be used when
+               sending console, desktop, or IM messages to users.
+               
+               The substitutions key is optional and is intended to only be used
+               to verify when message variables added or modified in the
+               database. Ideally, every variable entry which has custom
+               (uppercase) substitution strings in subject, message, or
+               short_message should have corresponding substitutions hash keys
+               and values:
+               variable.name: 'usermessage|TestKey|Global'
+               variable.value:
+               {
+                  'message' => "[MY_USERNAME]'s reservation will timeout in [NOTICE_INTERVAL]",
+                  'substitutions' => {
+                     'MY_USERNAME' => 'some-default-username',
+                     'NOTICE_INTERVAL' => 'xxx minutes',
+                  },
+               }
+               
+               The $substitution_hashref argument must be provided if subject,
+               message, or short_message contains custom strings to be replaced.
+               There must be a $substitution_hashref key for every custom,
+               upper-case replacement string. For example:
+               my $message = $self->_get_message_variable('TestKey', { 'MY_USERNAME' => 'slappy', NOTICE_INTERVAL' => '5 minutes' });
+               
+               ...would return the string:
+               "slappy's reservation will timeout in 5 minutes"
+               
+               The $return_short_message argument controls whether to return the
+               value of message (default) or short_message.
+               
+               The $admin_message argument controls whether to retrieve
+               messages with a variable.name beginning with 'usermessage'
+               (default) or 'adminmessage'.
+
+=cut
+
+sub _get_message_variable {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($message_key, $substitution_hashref, $return_short_message, $admin_message) = @_;
+	if (!defined($message_key)) {
+		notify($ERRORS{'WARNING'}, 0, "key argument was not supplied");
+		return;
+	}
+	
+	# Initialize hash reference if argument was not supplied
+	if (defined($substitution_hashref)) {
+		my $type = ref($substitution_hashref);
+		if (!$type || $type ne 'HASH') {
+			notify($ERRORS{'WARNING'}, 0, "substitution argument is not a hash reference:\n" . format_data($substitution_hashref));
+			return;
+		}
+		elsif (keys(%$substitution_hashref)) {
+			notify($ERRORS{'DEBUG'}, 0, "substitution hash reference was specified:\n" . format_data($substitution_hashref));
+		}
+	}
+	else {
+		$substitution_hashref = {};
+	}
+	
+	# Set common substitution values
+	$substitution_hashref->{PID} = $$;
+	
+	my $message_type = ($admin_message ? 'admin' : 'user');
+	
+	# Assemble the variable name
+	my $variable_name;
+	if ($admin_message) {
+		# Assemble admin message variable name
+		$variable_name= "adminmessage|$message_key";
+	}
+	else {
+		# Assemble user message variable name
+		my $user_affiliation_name = $self->data->get_user_affiliation_name();
+		$variable_name= "usermessage|$message_key|$user_affiliation_name";
+		
+		# Check if the affiliation-specific variable is set, if not revert to Global
+		if (!is_variable_set($variable_name)) {
+			notify($ERRORS{'DEBUG'}, 0, "affiliation-specific variable is NOT set in database: $variable_name");
+			$variable_name = "usermessage|$message_key|Global";
+		}
+	}
+	
+	# Retrieve the variable from the database
+	my $variable = get_variable($variable_name);
+	if (!defined($variable)) {
+		notify($ERRORS{'WARNING'}, 0, "unable to retrieve $message_type message variable, failed to retieve variable matching name: '$variable_name'");
+		return;
+	}
+	
+	# Make sure the variable contains subject key
+	my $subject = $variable->{subject};
+	if (!defined($subject)) {
+		notify($ERRORS{'WARNING'}, 0, "unable to retrieve $message_type message variable, '$variable_name' variable stored in database does not contain a {subject} key:\n" . format_data($variable));
+		return;
+	}
+	
+	# Check if supposed to return short message, return long message if not defined
+	my $message;
+	if ($return_short_message) {
+		if ($variable->{short_message}) {
+			$message = $variable->{short_message};
+		}
+		else {
+			notify($ERRORS{'WARNING'}, 0, "short message was requested but not defined in '$variable_name' variable");
+		}
+	}
+	$message = $variable->{message} if !defined($message);
+	
+	# Make sure message was determined
+	if (!defined($message)) {
+		notify($ERRORS{'WARNING'}, 0, "unable to retrieve $message_type message variable, '$variable_name' variable stored in database does not contain a {message} key:\n" . format_data($variable));
+		return;
+	}
+	
+	# Extract all substitution string sections from the subject and message in the form: [foo]
+	my @substitution_strings = "$subject $message" =~ /\[([\w_]+)\]/g;
+	@substitution_strings = remove_array_duplicates(@substitution_strings);
+	
+	for my $substitution_string (@substitution_strings) {
+		my $substitution_value;
+		
+		# Check if the string matches a key in the optional substitution hash reference
+		if (defined($substitution_hashref->{$substitution_string})) {
+			$substitution_value = $substitution_hashref->{$substitution_string};
+			notify($ERRORS{'DEBUG'}, 0, "determined substitution value from supplied hash reference for '$variable_name' $message_type variable: $substitution_string --> $substitution_value");
+		}
+		elsif (defined($variable->{substitutions}{$substitution_string})) {
+			$substitution_value = $variable->{substitutions}{$substitution_string};
+			notify($ERRORS{'DEBUG'}, 0, "determined substitution value from variable definition substitutions for '$variable_name' $message_type variable: $substitution_string --> $substitution_value");
+		}
+		else {
+			#notify($ERRORS{'DEBUG'}, 0, "substitution hash reference does not contain a '$substitution_string' key:\n" . format_data($substitution_hashref));
+			
+			# Attempt to retrieve the substitution value from the DataStructure
+			# String in subject or message must be in a form such as: [image_name]
+			# Brackets were removed in earlier regex, so $substitution_string would now contain: image_name
+			
+			# Check if DataStructure.pm implements get_ function
+			if (!$self->data->can("get_$substitution_string")) {
+				notify($ERRORS{'CRITICAL'}, 0, "$message_type variable: '$variable_name', failed to determine substitution value for substitution string: $substitution_string, DataStructure does not implement a get_$substitution_string function\n" .
+					"substitution hash reference argument:\n" . format_data($substitution_hashref) . "\n" .
+					"variable definition substitution hash reference:\n" . format_data($variable->{substitutions})
+				);
+				return;
+			}
+			
+			# Assemble a code string to retrieve the value from the DataStructure:
+			my $eval_string = "\$self->data->get_$substitution_string(0)";
+			
+			# Evaluate the code string:
+			$substitution_value = eval $eval_string;
+			if (defined($substitution_value)) {
+				#notify($ERRORS{'DEBUG'}, 0, "determined DataStructure substitution value: $eval_string --> $substitution_value");
+			}
+			else {
+				$substitution_value = '<undefined>';
+			}
+		}
+		
+		# Replace the substitution strings in the subject and message
+		$subject =~ s/\[$substitution_string\]/$substitution_value/g;
+		$message =~ s/\[$substitution_string\]/$substitution_value/g;	
+	}
+	
+	# Remove leading and trailing newlines from message
+	$message =~ s/^\n+//g;
+	$message =~ s/\n+$//g;
+	
+	if (wantarray) {
+		notify($ERRORS{'DEBUG'}, 0, "retrieved '$variable_name' $message_type message variable and substituted text, returning array:\n" .
+			"subject: $subject\n" .
+			"message:\n$message"
+		);
+		return ($subject, $message);
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "retrieved '$variable_name' $message_type message variable and substituted text, returning message string:\n$message");
+		return $message;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_user_message
+
+ Parameters  : $user_message_key, $substitution_hashref (optional)
+ Returns     : array context, array: ($subject, $message)
+               scalar context, string: $message
+ Description : Retrieves user messages.
+
+=cut
+
+sub get_user_message {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($user_message_key, $substitution_hashref) = @_;
+	return $self->_get_message_variable($user_message_key, $substitution_hashref);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_user_short_message
+
+ Parameters  : $user_message_key, $substitution_hashref (optional)
+ Returns     : array context, array: ($subject, $short_message)
+               scalar context, string: $short_message
+ Description : Retrieves user short messages.
+
+=cut
+
+sub get_user_short_message {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($user_message_key, $substitution_hashref) = @_;
+	return $self->_get_message_variable($user_message_key, $substitution_hashref, 1);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_admin_message
+
+ Parameters  : $admin_message_key, $substitution_hashref (optional)
+ Returns     : array context, array: ($subject, $message)
+               scalar context, string: $message
+ Description : Retrieves administrative messages.
+
+=cut
+
+sub get_admin_message {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my ($admin_message_key, $substitution_hashref) = @_;
+	return $self->_get_message_variable($admin_message_key, $substitution_hashref, 0, 1);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
 
 =head2 setup_get_menu
 

Modified: vcl/trunk/managementnode/lib/VCL/image.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/image.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/image.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/image.pm Thu Dec 10 20:45:35 2015
@@ -113,34 +113,15 @@ sub process {
 	my $computer_shortname         = $self->data->get_computer_short_name();
 	my $managementnode_shortname   = $self->data->get_management_node_short_name();
 	my $sysadmin_mail_address      = $self->data->get_management_node_sysadmin_email(0);
-
+	
+	# Send an email to administrators indicating image capture started
 	if ($sysadmin_mail_address) {
-		# Notify administrators that image creation is starting
-		my $body = <<"END";
-VCL Image Creation Started
-
-Request ID: $request_id
-Reservation ID: $reservation_id
-PID: $$
-
-Image ID: $image_id
-Image name: $image_name
-Base image size: $image_size
-Base revision ID: $imagerevision_id
-
-Management node: $managementnode_shortname
-
-Username: $user_unityid
-User ID: $user_id
-
-Computer ID: $computer_id
-Computer name: $computer_shortname
-
-Use Sysprep: $imagemeta_sysprep
-END
-		mail($sysadmin_mail_address, "VCL IMAGE Creation Started: $image_name", $body, $affiliation_helpaddress);
+		my ($admin_subject, $admin_message) = $self->get_admin_message('image_creation_started');
+		if (defined($admin_subject) && defined($admin_message)) {
+			mail($sysadmin_mail_address, $admin_subject, $admin_message, $affiliation_helpaddress);
+		}
 	}
-	
+
 	# Make sure image does not exist in the repository
 	my $image_already_exists = $self->provisioner->does_image_exist();
 	if ($image_already_exists) {
@@ -248,7 +229,7 @@ EOF
 
 =head2 reservation_successful
 
- Parameters  : none
+ Parameters  : $image_size_old
  Returns     : exits
  Description : Handles final steps when an image capture is successful. Sends
                message to image creator. Inserts reload request into the
@@ -259,97 +240,39 @@ EOF
 
 sub reservation_successful {
 	my $self           = shift;
-	my $image_size_old = shift;
+	my $image_size_old = shift || 0;
 	
 	my $request_data               = $self->data->get_request_data();
-	my $request_id                 = $self->data->get_request_id();
 	my $request_state_name         = $self->data->get_request_state_name();
-	my $reservation_id             = $self->data->get_reservation_id();
-	my $user_id                    = $self->data->get_user_id();
-	my $user_unityid               = $self->data->get_user_login_id();
 	my $user_email                 = $self->data->get_user_email();
-	my $affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
 	my $affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $image_id                   = $self->data->get_image_id();
-	my $image_name                 = $self->data->get_image_name();
-	my $image_prettyname           = $self->data->get_image_prettyname();
-	my $image_size                 = $self->data->get_image_size();
-	my $imagerevision_id           = $self->data->get_imagerevision_id();
-	my $imagemeta_sysprep          = $self->data->get_imagemeta_sysprep();
 	my $computer_id                = $self->data->get_computer_id();
-	my $computer_shortname         = $self->data->get_computer_short_name();
-	my $managementnode_shortname   = $self->data->get_management_node_short_name();
 	my $sysadmin_mail_address      = $self->data->get_management_node_sysadmin_email(0);
 	
-	# Send image creation successful email to user
-	my $subject_user;
-	my $body_user;
+	my $image_capture_type;
 	
-	if ($request_state_name eq 'checkpoint') {
-		$subject_user = "VCL -- $image_prettyname Image Checkpoint Succeeded";
-		$body_user = <<"END";
-
-Your VCL image checkpoint creation request for $image_prettyname has succeeded.
-
-You will need to visit the "Current Reservations" page and click "Connect" in order to be able to reconnect to the computer.
-
-Thank You,
-VCL Team
-END
+	# Send a capture completed message to the image owner
+	my ($user_subject, $user_message);
+	if ($request_state_name =~ /(checkpoint)/i) {
+		$image_capture_type = 'Checkpoint';
+		($user_subject, $user_message) = $self->get_user_message('image_checkpoint_success');
 	}
 	else {
-		$subject_user = "VCL -- $image_prettyname Image Creation Succeeded";
-		$body_user = <<"END";
-
-Your VCL image creation request for $image_prettyname has succeeded.
-
-Please visit $affiliation_sitewwwaddress and you should see an image called $image_prettyname.
-
-Please test this image to confirm it works correctly.
-
-Thank You,
-VCL Team
-END
+		$image_capture_type = 'Capture';
+		($user_subject, $user_message) = $self->get_user_message('image_creation_success');
+	}
+	if (defined($user_subject) && defined($user_message)) {
+		mail($user_email, $user_subject, $user_message, $affiliation_helpaddress);
 	}
 	
-	mail($user_email, $subject_user, $body_user, $affiliation_helpaddress);
-	
-	
-	# Send mail to $sysadmin_mail_address
+	# Send mail to administrators
 	if ($sysadmin_mail_address) {
-		my $subject_admin;
-		if ($request_state_name eq 'checkpoint') {
-			$subject_admin = "VCL IMAGE Checkpoint Completed: $image_name"
-		}
-		else {
-			$subject_admin = "VCL IMAGE Creation Completed: $image_name"
+		# Get the administrator email subject and message
+		# Pass a hash containing an IMAGE_CAPTURE_TYPE key - this gets replaced in the subject of the message
+		my ($admin_subject, $admin_message) = $self->get_admin_message('image_creation_complete', { 'IMAGE_CAPTURE_TYPE' => $image_capture_type, IMAGE_SIZE_OLD => $image_size_old });
+		if (defined($admin_subject) && defined($admin_message)) {
+			mail($sysadmin_mail_address, $admin_subject, $admin_message, $affiliation_helpaddress);
 		}
-		
-		my $body_admin = <<"END";
-VCL Image Creation Completed
-
-Request ID: $request_id
-Reservation ID: $reservation_id
-PID: $$
-
-Image ID: $image_id
-Image name: $image_name
-Image size change: $image_size_old --> $image_size
-
-Revision ID: $imagerevision_id
-
-Management node: $managementnode_shortname
-
-Username: $user_unityid
-User ID: $user_id
-
-Computer ID: $computer_id
-Computer name: $computer_shortname
-
-Use Sysprep: $imagemeta_sysprep
-END
-
-		mail($sysadmin_mail_address, $subject_admin, $body_admin, $affiliation_helpaddress);
 	}
 	
 	if ($request_state_name eq 'checkpoint') {
@@ -358,7 +281,7 @@ END
 	else {
 		# Insert reload request data into the datbase
 		if (!insert_reload_request($request_data)) {
-			notify($ERRORS{'CRITICAL'}, 0, "failed to insert reload request into database for computer id=$computer_id");
+			notify($ERRORS{'CRITICAL'}, 0, "failed to insert reload request into database for computer ID: $computer_id");
 		}
 		
 		# Switch the request state to complete, leave the computer state as is, update log ending to EOR, exit
@@ -384,115 +307,51 @@ sub reservation_failed {
 	my $self = shift;
 	
 	my $request_id                 = $self->data->get_request_id();
-	my $reservation_id             = $self->data->get_reservation_id();
 	my $request_state_name         = $self->data->get_request_state_name();
-	my $user_id                    = $self->data->get_user_id();
-	my $user_unityid               = $self->data->get_user_login_id();
+	my $request_laststate_name     = $self->data->get_request_laststate_name();
 	my $user_email                 = $self->data->get_user_email();
-	my $user_firstname             = $self->data->get_user_firstname() || '';
-	my $user_lastname              = $self->data->get_user_lastname() || '';
-	my $user_affiliation_name      = $self->data->get_user_affiliation_name();
 	my $affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $image_id                   = $self->data->get_image_id();
 	my $image_name                 = $self->data->get_image_name();
-	my $image_prettyname           = $self->data->get_image_prettyname();
-	my $imagerevision_id           = $self->data->get_imagerevision_id();
-	my $os_module_perl_package     = $self->data->get_image_os_module_perl_package();
-	my $imagemeta_sysprep          = $self->data->get_imagemeta_sysprep();
 	my $computer_id                = $self->data->get_computer_id();
 	my $computer_shortname         = $self->data->get_computer_short_name();
-	my $computer_state_name        = $self->data->get_computer_state_name();
-	my $provisioning_pretty_name   = $self->data->get_computer_provisioning_pretty_name();
-	my $provisioning_name          = $self->data->get_computer_provisioning_name();
-	my $provisioning_perl_package  = $self->data->get_computer_provisioning_module_perl_package();
-	my $managementnode_shortname   = $self->data->get_management_node_short_name();
 	my $sysadmin_mail_address      = $self->data->get_management_node_sysadmin_email(0);
-	my $vmhost_id                  = $self->data->get_vmhost_id() || '';
-	my $vmhost_computer_id         = $self->data->get_vmhost_computer_id() || '';
-	my $vmhost_short_name          = $self->data->get_vmhost_short_name() || '';
-	my $vmhost_profile_id          = $self->data->get_vmhost_profile_id() || '';
-	my $vmhost_profile_name        = $self->data->get_vmhost_profile_name() || '';
-	my $request_laststate_name     = $self->data->get_request_laststate_name();
 	
 	my $message = shift;
 	
+	my $image_capture_type;
+	if ($request_state_name =~ /(checkpoint)/i) {
+		$image_capture_type = 'Checkpoint';
+	}
+	else {
+		$image_capture_type = 'Creation';
+	}
+	
 	# Image process failed
 	if ($message) {
-		notify($ERRORS{'CRITICAL'}, 0, "$image_name image creation failed - $message");
+		notify($ERRORS{'CRITICAL'}, 0, "$image_name Image $image_capture_type Failed - $message");
 	}
 	else {
-		notify($ERRORS{'CRITICAL'}, 0, "$image_name image creation failed");
+		notify($ERRORS{'CRITICAL'}, 0, "$image_name Image $image_capture_type Failed");
 	}
 	
-	# Send mail to user
-	my $body_user = <<"END";
-
-We apologize for the inconvenience.
-Your image creation of $image_prettyname has been delayed
-due to a system issue that prevented the automatic completion.
-
-The image creation request and the computing resource have
-been placed in a safe mode. The VCL system administrators
-have been notified for manual intervention.
-
-Once the issues have been resolved, you will be notified
-by the successful completion email or contacted directly
-by the VCL system administrators.
-
-If you do not receive a response within one business day, please
-reply to this email.
-
-Thank You,
-VCL Team
-END
-	# Don't attempt to send another notice if $request_laststate_name is image. 
-	if ($request_laststate_name ne "maintenance") {
-		mail($user_email, "VCL -- NOTICE DELAY Image Creation $image_prettyname", $body_user, $affiliation_helpaddress);
+	# Send a capture delayed message to the image owner
+	my $user_message_key = 'image_creation_delayed';
+	my ($user_subject, $user_message) = $self->get_user_message($user_message_key);
+	if ($request_laststate_name ne "maintenance" && defined($user_subject) && defined($user_message)) {
+		mail($user_email, $user_subject, $user_message, $affiliation_helpaddress);
 	}
-
-	# Send mail to $sysadmin_mail_address
+	
+	# Send mail to administrators
 	if ($sysadmin_mail_address) {
-		my $body_admin = <<"END";
-VCL Image Creation Failed
-
-Management node: $managementnode_shortname
-
-Request ID: $request_id
-Reservation ID: $reservation_id
-PID: $$
-
-Image ID: $image_id
-Image revision ID: $imagerevision_id
-Image name: $image_name
-Image display name: $image_prettyname
-Image OS package: $os_module_perl_package
-
-User ID: $user_id
-User login name: $user_unityid
-User name: $user_firstname $user_lastname
-User affiliation: $user_affiliation_name
-
-Provisioning module: $provisioning_pretty_name ($provisioning_name)
-Provisioning package: $provisioning_perl_package
-
-Computer ID: $computer_id
-Computer name: $computer_shortname
-END
-		if ($vmhost_id) {
-			$body_admin .= <<"END";
-
-VM host ID: $vmhost_id
-VM host computer ID: $vmhost_computer_id
-VM host computer name: $vmhost_short_name
-
-VM host profile ID: $vmhost_profile_id
-VM host profile name: $vmhost_profile_name
-END
+		# Get the administrator email subject and message
+		# Pass a hash containing an IMAGE_CAPTURE_TYPE key - this gets replaced in the subject of the message
+		my $admin_message_key = 'image_creation_failed';
+		my ($admin_subject, $admin_message) = $self->get_admin_message($admin_message_key, { 'IMAGE_CAPTURE_TYPE' => $image_capture_type });
+		if (defined($admin_subject) && defined($admin_message)) {
+			mail($sysadmin_mail_address, $admin_subject, $admin_message, $affiliation_helpaddress);
 		}
-		notify($ERRORS{'OK'}, 0, "imaging reservation info:\n$body_admin");
-		mail($sysadmin_mail_address, "VCL -- NOTICE FAILED Image Creation $image_prettyname", $body_admin, $affiliation_helpaddress);
 	}
-	
+
 	# Update the request state to maintenance, laststate to image
 	if (update_request_state($request_id, "maintenance", $request_state_name)) {
 		notify($ERRORS{'OK'}, 0, "request state set to maintenance, laststate to $request_state_name");

Modified: vcl/trunk/managementnode/lib/VCL/inuse.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/inuse.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/inuse.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/inuse.pm Thu Dec 10 20:45:35 2015
@@ -39,13 +39,14 @@ VCL::inuse - Perl module for the VCL inu
 
  # Create a new VCL::inuse object based on the request information
  my $inuse = VCL::inuse->new($request_info);
+ 
+ $inuse->process();
 
 =head1 DESCRIPTION
 
- This module supports the VCL "inuse" state. The inuse state is reached after
- a user has made a reservation, acknowledged the reservation, and connected to
- the machine. Once connected, vcld creates a new process which then
- creates a new instance of this module.
+ This module supports the VCL "inuse" state. The inuse state is reached after a
+ user has made a reservation, acknowledged the reservation by clicking the
+ "Connect" button, and connected to the remote computer.
 
  If the "checkuser" flag is set for the image that the user requested,
  this process will periodically check to make sure the user is still
@@ -101,19 +102,19 @@ use VCL::utils;
 sub process {
 	my $self = shift;
 	
-	my $request_id              = $self->data->get_request_id();
-	my $request_state_name      = $self->data->get_request_state_name();
-	my $request_start           = $self->data->get_request_start_time();
-	my $request_end             = $self->data->get_request_end_time();
-	my $request_forimaging      = $self->data->get_request_forimaging();
-	my $request_checkuser       = $self->data->get_request_checkuser();
-	my $reservation_id          = $self->data->get_reservation_id();
-	my $reservation_count       = $self->data->get_reservation_count();
-	my $server_request_id       = $self->data->get_server_request_id();
-	my $imagemeta_checkuser     = $self->data->get_imagemeta_checkuser();
-	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 $request_id            = $self->data->get_request_id();
+	my $request_state_name    = $self->data->get_request_state_name();
+	my $request_start         = $self->data->get_request_start_time();
+	my $request_end           = $self->data->get_request_end_time();
+	my $request_forimaging    = $self->data->get_request_forimaging();
+	my $request_checkuser     = $self->data->get_request_checkuser();
+	my $reservation_id        = $self->data->get_reservation_id();
+	my $reservation_count     = $self->data->get_reservation_count();
+	my $server_request_id     = $self->data->get_server_request_id();
+	my $imagemeta_checkuser   = $self->data->get_imagemeta_checkuser();
+	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('reconnecttimeout');
 	
@@ -222,7 +223,7 @@ sub process {
 			
 			# Notify user when 5 or 10 minutes remain
 			if ($request_remaining_minutes == 5 || $request_remaining_minutes == 10) {
-				$self->_notify_user_disconnect($request_remaining_minutes);
+				$self->_notify_user_endtime_imminent("$request_remaining_minutes minutes");
 			}
 			
 			if ($iteration < $end_time_notify_minutes) {
@@ -232,12 +233,12 @@ sub process {
 		}
 		
 		# Notify user - endtime and image capture has started
-		$self->_notify_user_request_ended();
+		$self->_notify_user_endtime_reached();
 		
 		# Initiate auto-capture process if this is an imaging request and not a cluster reservation
 		if ($request_forimaging && $reservation_count == 1) {
 			notify($ERRORS{'OK'}, 0, "initiating image auto-capture process");
-			if (!$self->_start_imaging_request()) {
+			if (!$self->start_imaging_request()) {
 				notify($ERRORS{'CRITICAL'}, 0, "failed to initiate image auto-capture process, changing request and computer state to maintenance");
 				$self->state_exit('maintenance', 'maintenance');
 			}
@@ -254,7 +255,7 @@ sub process {
 		# Check end time for a notice interval - returns 0 if no notice is to be given
 		my $notice_interval = check_endtimenotice_interval($request_end);
 		if ($notice_interval) {
-			$self->_notify_user_endtime($notice_interval);
+			$self->_notify_user_future_endtime($notice_interval);
 		}
 	}
 	else {
@@ -328,7 +329,7 @@ sub process {
 			# Update reservation lastcheck, otherwise request will be processed immediately again
 			update_reservation_lastcheck($reservation_id);
 			
-			$self->_notify_user_timeout();
+			$self->_notify_user_timeout_inactivity();
 			$self->state_exit('timeout', 'inuse', 'timeout');
 		}
 	}
@@ -338,18 +339,18 @@ sub process {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_endtime
+=head2 notify_user_future_endtime
 
- Parameters  : $request_data_hash_reference, $notice_interval
- Returns     : 1 if successful, 0 otherwise
+ Parameters  : $notice_interval
+ Returns     : boolean
  Description : Notifies the user how long they have until the end of the
-               request. Based on the user configuration, an e-mail message, IM
-               message, or wall message may be sent. A notice interval string
-               must be passed. Its value should be something like "5 minutes".
+               request. A notice interval argument must be passed. Its value
+               gets inserted directly in the message sent to the user and should
+               contain something like "5 minutes".
 
 =cut
 
-sub _notify_user_endtime {
+sub notify_user_future_endtime {
 	my $self = shift;
 	my $notice_interval = shift;
 	
@@ -359,412 +360,220 @@ sub _notify_user_endtime {
 		return 0;
 	}
 	
-	my $is_parent_reservation = $self->data->is_parent_reservation();
-	if (!$is_parent_reservation) {
-		notify($ERRORS{'DEBUG'}, 0, "child reservation - not notifying user of endtime");
-		return 1;
-	}
-	
-	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $computer_type                   = $self->data->get_computer_type();
-	my $image_os_name                   = $self->data->get_image_os_name();
-	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $image_os_type                   = $self->data->get_image_os_type();
-	my $user_affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
-	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_login_id                   = $self->data->get_user_login_id();
-	my $user_email                      = $self->data->get_user_email();
-	my $user_emailnotices               = $self->data->get_user_emailnotices();
-	my $user_imtype_name                = $self->data->get_user_imtype_name();
-	my $user_im_id                      = $self->data->get_user_im_id();
-	my $request_forimaging              = $self->check_imaging_request();	
-	my $request_id                      = $self->data->get_request_id();
-	
-	my $message;
-	my $subject;
-	my $short_message = "You have $notice_interval until the scheduled end time of your reservation. VCL Team";
-	
-	$message  = <<"EOF";
-
-You have $notice_interval until the scheduled end time of your reservation for image $image_prettyname.
-
-Reservation extensions are available if the machine you are on does not have a reservation immediately following.
-
-To edit this reservation:
--Visit $user_affiliation_sitewwwaddress
--Select Current Reservations
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-
-	$subject = "VCL -- $notice_interval until end of reservation for $image_prettyname";
-	
-	# Send mail
-	if ($user_emailnotices) {
-		notify($ERRORS{'DEBUG'}, 0, "user $user_login_id email notices enabled - notifying user of endtime");
-		mail($user_email, $subject, $message, $user_affiliation_helpaddress);
-	}
-	else {
-		notify($ERRORS{'DEBUG'}, 0, "user $user_login_id email notices disabled - not notifying user of endtime");
-	}
-
-	# notify via console
-	if ( $self->os->can('notify_user_console') ) {
-		if ( $self->os->notify_user_console($short_message) ) {
-			notify($ERRORS{'DEBUG'}, 0, "Successfully notified user $user_login_id via console method");
+	my $is_parent_reservation        = $self->data->is_parent_reservation();
+	my $computer_short_name          = $self->data->get_computer_short_name();
+	my $image_os_type                = $self->data->get_image_os_type();
+	my $user_affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $user_login_id                = $self->data->get_user_login_id();
+	my $user_email                   = $self->data->get_user_email();
+	my $user_emailnotices            = $self->data->get_user_emailnotices();
+	my $user_imtype_name             = $self->data->get_user_imtype_name();
+	my $user_im_id                   = $self->data->get_user_im_id();
+	
+	my $user_message_key = 'future_endtime';
+	
+	# Send a message to the user notifying them the reservation end time is coming up
+	if ($is_parent_reservation && $user_emailnotices) {
+		my ($user_subject, $user_message) = $self->get_user_message($user_message_key, { NOTICE_INTERVAL => $notice_interval});
+		if (defined($user_subject) && defined($user_message)) {
+			mail($user_email, $user_subject, $user_message, $user_affiliation_helpaddress);
 		}
 	}
 	
-	# Send message to machine
-	if ($computer_type =~ /blade|virtualmachine/) {
+	my $user_short_message = $self->get_user_short_message($user_message_key, { NOTICE_INTERVAL => $notice_interval});
+	if ($user_short_message) {
+		# Display a message on the console or desktop if the OS module supports it
+		if ($self->os->can('notify_user_console')) {
+			$self->os->notify_user_console($user_short_message);
+		}
+		
+		# TODO: move this to OS module
 		if ($image_os_type =~ /osx/) {
-        # Notify via oascript
-        notify_via_oascript($computer_short_name, $user_login_id, $short_message);
-     }
-	} ## end if ($computer_type =~ /blade|virtualmachine/)
-	
-	# Send IM
-	if ($user_imtype_name ne "none") {
-		notify($ERRORS{'DEBUG'}, 0, "user $user_login_id IM type: $user_imtype_name - notifying user of endtime");
-		notify_via_im($user_imtype_name, $user_im_id, $message);
-	}
-	else {
-		notify($ERRORS{'DEBUG'}, 0, "user $user_login_id IM type: $user_imtype_name - not notifying user of endtime");
+			# Mac images only, notify via oascript
+			notify_via_oascript($computer_short_name, $user_login_id, $user_short_message);
+		}
+		
+		# Notify via IM
+		if ($user_imtype_name ne "none" && defined($user_im_id)) {
+			notify_via_im($user_imtype_name, $user_im_id, $user_short_message);
+		}
 	}
 	
 	return 1;
-} ## end sub _notify_user_endtime
+} ## end sub notify_user_future_endtime
+
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_disconnect
+=head2 notify_user_endtime_imminent
 
- Parameters  : $disconnect_time
+ Parameters  : $notice_interval
  Returns     : boolean
- Description : Notifies the user that the session will be disconnected soon.
-               Based on the user configuration, an e-mail message, IM message,
-               Windows msg, or Linux wall message may be sent. A scalar
-               containing the number of minutes until the user is disconnected
-               must be passed as the 2nd parameter.
+ Description : Notifies the user that the request end time will be reached and
+               the session will be disconnected soon. A notice interval argument
+               must be passed. Its value gets inserted directly in the message
+               sent to the user and should contain something like "5 minutes".
 
 =cut
 
-sub _notify_user_disconnect {
+sub notify_user_endtime_imminent {
 	my $self = shift;
-	my $disconnect_time = shift;
+	my $notice_interval = shift;
 	
 	# Check to make sure disconnect time was passed
-	if (!defined($disconnect_time)) {
+	if (!defined($notice_interval)) {
 		notify($ERRORS{'WARNING'}, 0, "disconnect time message not set, disconnect time was not passed");
 		return 0;
 	}
 	
-	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $computer_type                   = $self->data->get_computer_type();
-	my $image_os_name                   = $self->data->get_image_os_name();
-	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $image_os_type                   = $self->data->get_image_os_type();
-	my $user_affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
-	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_login_id                   = $self->data->get_user_login_id();
-	my $user_email                      = $self->data->get_user_email();
-	my $user_emailnotices               = $self->data->get_user_emailnotices();
-	my $user_imtype_name                = $self->data->get_user_imtype_name();
-	my $user_im_id                      = $self->data->get_user_im_id();
-	my $is_parent_reservation           = $self->data->is_parent_reservation();
-	my $request_forimaging              = $self->check_imaging_request();
-	
-	my $disconnect_string;
-	if ($disconnect_time == 0) {
-		$disconnect_string = "0 minutes";
-	}
-	elsif ($disconnect_time == 1) {
-		$disconnect_string = "1 minute";
+	my $computer_short_name          = $self->data->get_computer_short_name();
+	my $image_os_type                = $self->data->get_image_os_type();
+	my $user_affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $user_login_id                = $self->data->get_user_login_id();
+	my $user_email                   = $self->data->get_user_email();
+	my $user_emailnotices            = $self->data->get_user_emailnotices();
+	my $user_imtype_name             = $self->data->get_user_imtype_name();
+	my $user_im_id                   = $self->data->get_user_im_id();
+	my $is_parent_reservation        = $self->data->is_parent_reservation();
+	my $request_forimaging           = $self->check_imaging_request();
+	
+	my $user_message_key;
+	if ($request_forimaging) {
+		$user_message_key = 'endtime_imminent_imaging';
 	}
 	else {
-		$disconnect_string = "$disconnect_time minutes";
+		$user_message_key = 'endtime_imminent';
 	}
 	
-	my $short_message;
-	my $subject;
-	my $message;
-	
-	if (!$request_forimaging) {
-		$message = <<"EOF";
-
-You have $disconnect_string until the end of your reservation for image $image_prettyname, please save all work and prepare to exit.
-
-Reservation extensions are available if the machine you are on does not have a reservation immediately following.
-
-Visit $user_affiliation_sitewwwaddress and select Current Reservations to edit this reservation.
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-
-		$short_message = "You have $disconnect_string until the end of your reservation. Please save all work and prepare to log off.";
-		$subject = "VCL -- $disconnect_string until end of reservation";
-	}
-	else {
-		$short_message = "You have $disconnect_string until the auto capture process is started.";
-		$subject = "VCL Imaging Reservation -- $disconnect_string until starting auto capture";
-		$message = <<"EOF";
-
-You have $disconnect_string until the end of your reservation for image $image_prettyname. 
-
-At the scheduled end time your imaging reservation will be automatically captured. 
-
-To prevent this auto capture, visit the VCL site $user_affiliation_sitewwwaddress manually start the image creation process.
-
-Please note this auto capture feature is intended to prevent destorying any work you have done to the image.
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-
-	}
 	
-	# Send mail
+	# Send a message to the user notifying them the reservation end time is close
 	if ($is_parent_reservation && $user_emailnotices) {
-		mail($user_email, $subject, $message, $user_affiliation_helpaddress);
-	}
-
-	# notify via console
-	if ( $self->os->can('notify_user_console') ) {
-		if ( $self->os->notify_user_console($short_message) ) {
-			notify($ERRORS{'DEBUG'}, 0, "Successfully notified user $user_login_id via console method");
+		my ($user_subject, $user_message) = $self->get_user_message($user_message_key, { NOTICE_INTERVAL => $notice_interval});
+		if (defined($user_subject) && defined($user_message)) {
+			mail($user_email, $user_subject, $user_message, $user_affiliation_helpaddress);
 		}
 	}
 	
-	# Send IM
-	if ($is_parent_reservation && $user_imtype_name ne "none") {
-		notify_via_im($user_imtype_name, $user_im_id, $message);
+	my $user_short_message = $self->get_user_short_message($user_message_key, { NOTICE_INTERVAL => $notice_interval});
+	if ($user_short_message) {
+		# Display a message on the console or desktop if the OS module supports it
+		if ($self->os->can('notify_user_console')) {
+			$self->os->notify_user_console($user_short_message);
+		}
+		
+		# TODO: move this to OS module
+		if ($image_os_type =~ /osx/) {
+			# Mac images only, notify via oascript
+			notify_via_oascript($computer_short_name, $user_login_id, $user_short_message);
+		}
+		
+		# Notify via IM
+		if ($user_imtype_name ne "none" && defined($user_im_id)) {
+			notify_via_im($user_imtype_name, $user_im_id, $user_short_message);
+		}
 	}
 	
 	return 1;
-} ## end sub _notify_user_disconnect
+} ## end sub notify_user_endtime_imminent
+
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_timeout
+=head2 notify_user_timeout_inactivity
 
  Parameters  : none
  Returns     : boolean
- Description : Notifies the user that the session has timed out. Based on the
-               user configuration, an e-mail message, IM message, Windows msg,
-               or Linux wall message may be sent.
+ Description : Notifies the user that the session has timed out due to
+               inactivity.
 
 =cut
 
-sub _notify_user_timeout {
+sub notify_user_timeout_inactivity {
 	my $self = shift;
 	
-	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $computer_type                   = $self->data->get_computer_type();
-	my $image_os_name                   = $self->data->get_image_os_name();
-	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $image_os_type                   = $self->data->get_image_os_type();
-	my $user_affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
-	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_login_id                   = $self->data->get_user_login_id();
-	my $user_email                      = $self->data->get_user_email();
-	my $user_emailnotices               = $self->data->get_user_emailnotices();
-	my $user_imtype_name                = $self->data->get_user_imtype_name();
-	my $user_im_id                      = $self->data->get_user_im_id();
-	my $is_parent_reservation           = $self->data->is_parent_reservation();
-	
-	my $message = <<"EOF";
-
-Your reservation has timed out due to inactivity for image $image_prettyname.
-
-To make another reservation, please revisit:
-$user_affiliation_sitewwwaddress
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-
-	my $subject = "VCL -- reservation timeout";
+	my $user_affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $user_email                   = $self->data->get_user_email();
+	my $user_emailnotices            = $self->data->get_user_emailnotices();
+	my $user_imtype_name             = $self->data->get_user_imtype_name();
+	my $user_im_id                   = $self->data->get_user_im_id();
+	my $is_parent_reservation        = $self->data->is_parent_reservation();
 	
-	# Send mail
+	my $user_message_key = 'timeout_inactivity';
+	my ($user_subject, $user_message) = $self->get_user_message($user_message_key);
+
+	# Send a message to the user notifying them the reservation timed out
 	if ($is_parent_reservation && $user_emailnotices) {
-		mail($user_email, $subject, $message, $user_affiliation_helpaddress);
+		if (defined($user_subject) && defined($user_message)) {
+			mail($user_email, $user_subject, $user_message, $user_affiliation_helpaddress);
+		}
 	}
 	
-	# Send IM
-	if ($is_parent_reservation && $user_imtype_name ne "none") {
-		notify_via_im($user_imtype_name, $user_im_id, $message);
+	# Notify the user via IM
+	if ($user_imtype_name ne "none" && defined($user_im_id)) {
+		notify_via_im($user_imtype_name, $user_im_id, $user_message);
 	}
 	
 	return 1;
-} ## end sub _notify_user_timeout
+} ## end sub notify_user_timeout_inactivity
+
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_request_ended
+=head2 notify_user_endtime_reached
 
  Parameters  : none
  Returns     : boolean
- Description : Notifies the user that the session has ended.
-               Based on the user configuration, an e-mail message, IM message,
-               Windows msg, or Linux wall message may be sent.
+ Description : Notifies the user that the request has ended because the end
+               time was reached.
 
 =cut
 
-sub _notify_user_request_ended {
+sub notify_user_endtime_reached {
 	my $self = shift;
 	
-	my $request_id                      = $self->data->get_request_id();
-	my $request_logid                   = $self->data->get_request_log_id();
-	my $request_forimaging              = $self->data->get_request_forimaging();
-	my $reservation_count               = $self->data->get_reservation_count();
-	my $reservation_id                  = $self->data->get_reservation_id();
-	my $reservation_is_parent           = $self->data->is_parent_reservation;
-	my $computer_id                     = $self->data->get_computer_id();
-	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $computer_type                   = $self->data->get_computer_type();
-	my $image_os_name                   = $self->data->get_image_os_name();
-	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $image_os_type                   = $self->data->get_image_os_type();
-	my $user_affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
-	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_standalone                 = $self->data->get_user_standalone();
-	my $user_email                      = $self->data->get_user_email();
-	my $user_emailnotices               = $self->data->get_user_emailnotices();
-	my $user_imtype_name                = $self->data->get_user_imtype_name();
-	my $user_im_id                      = $self->data->get_user_im_id();
-	my $is_parent_reservation           = $self->data->is_parent_reservation();
-	my $subject;
-	my $message;
-	
-	if (!$request_forimaging) {
-	$subject = "VCL -- End of reservation";
-	
-	$message = <<"EOF";
-
-Your reservation of $image_prettyname has ended. Thank you for using $user_affiliation_sitewwwaddress.
-
-Regards,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
+	my $request_forimaging           = $self->data->get_request_forimaging();
+	my $user_affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $user_email                   = $self->data->get_user_email();
+	my $user_emailnotices            = $self->data->get_user_emailnotices();
+	my $user_imtype_name             = $self->data->get_user_imtype_name();
+	my $user_im_id                   = $self->data->get_user_im_id();
+	my $is_parent_reservation        = $self->data->is_parent_reservation();
+	
+	my $user_message_key;
+	if ($request_forimaging) {
+		$user_message_key = 'endtime_reached_imaging';
 	}
 	else {
-		$subject = "VCL Image Reservation - Auto capture started";
-		
-		$message = <<"EOF";
-
-Your imaging reservation of $image_prettyname has reached it's scheduled end time.
-
-To avoid losing your work we have started an automatic capture of this image. Upon completion of the 
-image capture. You will be notified about the completion of the image capture.
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-
+		$user_message_key = 'endtime_reached';
+	}
+	
+	my ($user_subject, $user_message) = $self->get_user_message($user_message_key);
+	if (!defined($user_subject) || !defined($user_message)) {
+		return;
 	}
 	
-	# Send mail
+	# Send a message to the user notifying them the reservation ended
 	if ($is_parent_reservation && $user_emailnotices) {
-		mail($user_email, $subject, $message, $user_affiliation_helpaddress);
+		mail($user_email, $user_subject, $user_message, $user_affiliation_helpaddress);
 	}
 	
-	# Send IM
-	if ($is_parent_reservation && $user_imtype_name ne "none") {
-		notify_via_im($user_imtype_name, $user_im_id, $message);
+	# Notify via IM
+	if ($user_imtype_name ne "none" && defined($user_im_id)) {
+		notify_via_im($user_imtype_name, $user_im_id, $user_message);
 	}
 	
 	return 1;
-} ## end sub _notify_user_request_ended
+} ## end sub notify_user_endtime_reached
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _start_imaging_request
+=head2 start_imaging_request
 
  Parameters  : none
  Returns     : boolean
- Description : If request is forimaging and times out, this inserts a imaging
-               reservation. 
+ Description : Inserts an "autocapture" imaging request is imaging request times
+               out.
 
 =cut
 
-sub _start_imaging_request {
+sub start_imaging_request {
 	my $self = shift;
 	
 	my $request_id = $self->data->get_request_id();

Modified: vcl/trunk/managementnode/lib/VCL/makeproduction.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/makeproduction.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/makeproduction.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/makeproduction.pm Thu Dec 10 20:45:35 2015
@@ -95,7 +95,7 @@ sub process {
 	}
 	
 	# Notify owner that image revision is production
-	if (!$self->notify_imagerevision_to_production()) {
+	if (!$self->notify_production_imagerevision()) {
 		$self->reservation_failed("failed to notify owner that $image_name is in production mode");
 	}
 	
@@ -114,45 +114,28 @@ sub process {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 notify_imagerevision_to_production
+=head2 notify_production_imagerevision
 
- Parameters  : 
- Returns     : 
- Description : 
+ Parameters  : none
+ Returns     : boolean
+ Description : Notifies the image owner that the production image revision has
+               changed.
  
 =cut
 
-sub notify_imagerevision_to_production {
+sub notify_production_imagerevision {
 	my $self = shift;
-	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $imagerevision_revision          = $self->data->get_imagerevision_revision();
-	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_email                      = $self->data->get_user_email();
 	
-
-	# Assemble the message subject
-	my $subject = "VCL -- Image $image_prettyname made production";
+	my $user_affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $user_email                   = $self->data->get_user_email();
 	
-	# Assemble the message body
-	my $body = <<"END";
-
-Revision $imagerevision_revision of your VCL '$image_prettyname' image has been made production.  Any new reservations for the image will receive this revision by default.
-
-If you have any questions, please contact $user_affiliation_helpaddress.
-
-Thank You,
-VCL Team
-END
-	
-	# Send the message
-	if (mail($user_email, $subject, $body)) {
-		notify($ERRORS{'OK'}, 0, "email message sent to $user_email");
-		return 1;
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to send email message to $user_email");
-		return 0;
+	my $user_message_key = 'production_imagerevision';
+	my ($user_subject, $user_message) = $self->get_user_message($user_message_key);
+	if (defined($user_subject) && defined($user_message)) {
+		mail($user_email, $user_subject, $user_message, $user_affiliation_helpaddress);
 	}
+	
+	return 1;
 } ## end sub _notify_owner
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: vcl/trunk/managementnode/lib/VCL/reserved.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reserved.pm Thu Dec 10 20:45:35 2015
@@ -94,7 +94,6 @@ sub process {
 	my $self = shift;
 	
 	my $request_id                      = $self->data->get_request_id();
-	my $request_data                    = $self->data->get_request_data();
 	my $request_logid                   = $self->data->get_request_log_id();
 	my $request_checkuser               = $self->data->get_request_checkuser();
 	my $reservation_id                  = $self->data->get_reservation_id();
@@ -121,7 +120,7 @@ sub process {
 	if ($is_parent_reservation) {
 		# Send an email and/or IM to the user
 		# Do this after updating the computer state to reserved because this is when the Connect button appears
-		$self->_notify_user_ready();
+		$self->notify_user_ready();
 		
 		# Insert acknowledgetimeout immediately before beginning to check user clicked Connect
 		# Web uses timestamp of this to determine when next to refresh the page
@@ -161,7 +160,7 @@ sub process {
 	# Wait for the user to acknowledge the request by clicking Connect button or from API
 	my $user_acknowledged = $self->code_loop_timeout(sub{$self->user_acknowledged()}, [], 'waiting for user acknowledgement', $acknowledge_timeout_remaining_seconds, 1, 10);
 	if (!$user_acknowledged) {
-		$self->_notify_user_timeout($request_data);
+		$self->notify_user_timeout_no_acknowledgement();
 		$self->state_exit('timeout', 'available', 'noack');
 	}
 	
@@ -245,7 +244,7 @@ sub process {
 			$self->state_exit();
 		}
 		else {
-			$self->_notify_user_no_login();
+			$self->notify_user_timeout_no_initial_connection();
 			$self->state_exit('timeout', 'reserved', 'nologin');
 		}
 	}
@@ -383,7 +382,7 @@ sub user_acknowledged {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_ready
+=head2 notify_user_ready
 
  Parameters  : none
  Returns     : boolean
@@ -391,84 +390,47 @@ sub user_acknowledged {
 
 =cut
 
-sub _notify_user_ready {
+sub notify_user_ready {
 	my $self = shift;
 	
-	#my $request_id                 = $self->data->get_request_id();
-	my $request_state_name         = $self->data->get_request_id();
-	#my $reservation_id             = $self->data->get_reservation_id();
-	my $user_email                 = $self->data->get_user_email();
-	my $user_emailnotices          = $self->data->get_user_emailnotices();
-	my $user_imtype_name               = $self->data->get_user_imtype_name();
-	my $user_im_id                 = $self->data->get_user_im_id();
-	my $affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
-	my $affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $image_prettyname           = $self->data->get_image_prettyname();
-	my $is_parent_reservation      = $self->data->is_parent_reservation();
-
-	my $mailstring;
-	my $subject;
+	my $request_state_name = $self->data->get_request_id();
+	my $user_email = $self->data->get_user_email();
+	my $user_emailnotices = $self->data->get_user_emailnotices();
+	my $user_imtype_name = $self->data->get_user_imtype_name();
+	my $user_im_id = $self->data->get_user_im_id();
+	my $affiliation_helpaddress = $self->data->get_user_affiliation_helpaddress();
+	my $is_parent_reservation = $self->data->is_parent_reservation();
 	
-	# Assemble the message body reservations
+	my $user_message_key;
 	if ($request_state_name =~ /^(reinstall)$/) {
-		$subject = "VCL -- $image_prettyname reservation reinstalled";
-		
-		$mailstring = <<"EOF";
-Your reservation was successfully reinstalled and you can proceed to reconnect. 
-Please revisit the 'Current Reservations' page for any additional information.
-EOF
+		$user_message_key = 'reinstalled';
 	}
 	else {
-		$subject = "VCL -- $image_prettyname reservation";
-		
-		$mailstring = <<"EOF";
-The resources for your VCL reservation have been successfully reserved.
-Connection will not be allowed until you click the 'Connect' button on the 'Current Reservations' page.
-You must acknowledge the reservation within the next 15 minutes or the resources will be reclaimed for other VCL users.
-
--Visit $affiliation_sitewwwaddress
--Select "Current Reservations"
--Click the "Connect" button
-Upon acknowledgement, all of the remaining connection details will be displayed.
-EOF
-	}
-	
-	$mailstring .= <<"EOF";
-
-Thank You,
-VCL Team
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
+		$user_message_key = 'reserved';
+	}
+	
+	my ($subject, $message) = $self->get_user_message($user_message_key);
+	if (!defined($subject) || !defined($message)) {
+		return;
+	}
 	
 	if ($is_parent_reservation && $user_emailnotices) {
-		mail($user_email, $subject, $mailstring, $affiliation_helpaddress);
+		mail($user_email, $subject, $message, $affiliation_helpaddress);
 	}
 	else {
-		# For email record keeping
-		notify($ERRORS{'MAILMASTERS'}, 0, " $user_email\n$mailstring");
+		notify($ERRORS{'MAILMASTERS'}, 0, "$user_email\n$message");
 	}
 	
 	if ($user_imtype_name ne "none") {
-		notify_via_im($user_imtype_name, $user_im_id, $mailstring, $affiliation_helpaddress);
+		notify_via_im($user_imtype_name, $user_im_id, $message, $affiliation_helpaddress);
 	}
 	
 	return 1;
-} ## end sub _notify_user_no_login
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_no_login
+=head2 notify_user_timeout_no_initial_connection
 
  Parameters  : none
  Returns     : boolean
@@ -478,59 +440,35 @@ EOF
 
 =cut
 
-sub _notify_user_no_login {
+sub notify_user_timeout_no_initial_connection {
 	my $self = shift;
 	
-	my $request_id                 = $self->data->get_request_id();
-	my $reservation_id             = $self->data->get_reservation_id();
 	my $user_email                 = $self->data->get_user_email();
 	my $user_emailnotices          = $self->data->get_user_emailnotices();
 	my $user_im_name               = $self->data->get_user_imtype_name();
 	my $user_im_id                 = $self->data->get_user_im_id();
-	my $affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
 	my $affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $image_prettyname           = $self->data->get_image_prettyname();
 	my $is_parent_reservation      = $self->data->is_parent_reservation();
-
-	my $message = <<"EOF";
-
-Your reservation has timed out for image $image_prettyname because no initial connection was made.
-
-To make another reservation, please revisit $affiliation_sitewwwaddress.
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance
-please respond with detailed information on the issue
-and a help ticket will be generated.
-
-To disable email notices
--Visit $affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-******************************************************************
-EOF
-
-	my $subject = "VCL -- Reservation Timeout";
-
+	
+	my $user_message_key = 'timeout_no_initial_connection';
+	my ($subject, $message) = $self->get_user_message($user_message_key);
+	if (!defined($subject) || !defined($message)) {
+		return;
+	}
+	
 	if ($is_parent_reservation && $user_emailnotices) {
-		#if  "0" user does not care to get additional notices
 		mail($user_email, $subject, $message, $affiliation_helpaddress);
-		notify($ERRORS{'OK'}, 0, "sent reservation timeout e-mail to $user_email");
 	}
 	if ($user_im_name ne "none") {
 		notify_via_im($user_im_name, $user_im_id, $message);
-		notify($ERRORS{'OK'}, 0, "sent reservation timeout IM to $user_im_name");
 	}
+	
 	return 1;
-} ## end sub _notify_user_no_login
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 _notify_user_timeout
+=head2 notify_user_timeout_no_acknowledgement
 
  Parameters  : none
  Returns     : boolean
@@ -540,55 +478,31 @@ EOF
 
 =cut
 
-sub _notify_user_timeout {
+sub notify_user_timeout_no_acknowledgement {
 	my $self = shift;
 	
-	my $request_id                 = $self->data->get_request_id();
-	my $reservation_id             = $self->data->get_reservation_id();
 	my $user_email                 = $self->data->get_user_email();
 	my $user_emailnotices          = $self->data->get_user_emailnotices();
 	my $user_im_name               = $self->data->get_user_imtype_name();
 	my $user_im_id                 = $self->data->get_user_im_id();
-	my $affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
 	my $affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $image_prettyname           = $self->data->get_image_prettyname();
 	my $is_parent_reservation      = $self->data->is_parent_reservation();
-
-	my $message = <<"EOF";
-
-Your reservation has timed out for image $image_prettyname because no initial connection was made.
-
-To make another reservation, please revisit $affiliation_sitewwwaddress.
-
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance
-please respond with detailed information on the issue
-and a help ticket will be generated.
-
-To disable email notices
--Visit $affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-******************************************************************
-EOF
-
-	my $subject = "VCL -- Reservation Timeout";
-
+	
+	my $user_message_key = 'timeout_no_acknowledgement';
+	my ($subject, $message) = $self->get_user_message($user_message_key);
+	if (!defined($subject) || !defined($message)) {
+		return;
+	}
+	
 	if ($is_parent_reservation && $user_emailnotices) {
-		#if  "0" user does not care to get additional notices
 		mail($user_email, $subject, $message, $affiliation_helpaddress);
-		notify($ERRORS{'OK'}, 0, "sent reservation timeout e-mail to $user_email");
 	}
 	if ($user_im_name ne "none") {
 		notify_via_im($user_im_name, $user_im_id, $message);
-		notify($ERRORS{'OK'}, 0, "sent reservation timeout IM to $user_im_name");
 	}
+	
 	return 1;
-} ## end sub _notify_user_timeout
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1719206&r1=1719205&r2=1719206&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Thu Dec 10 20:45:35 2015
@@ -2790,6 +2790,8 @@ sub database_select {
 		$ENV{database_select_calls}{$calling_sub}++;
 	}
 	
+	$database = $DATABASE unless $database;
+	
 	my $dbh;
 	if (!($dbh = getnewdbh($database))) {
 		# Try again if first attempt failed
@@ -8694,9 +8696,29 @@ sub get_caller_trace {
 =cut
 
 sub get_calling_subroutine {
-	my @caller = caller(2);
-	my $calling_subroutine = $caller[3] || '';
-	return $calling_subroutine;
+	for (my $i=2; $i<10; $i++) {
+		my @caller = caller($i);
+		
+		if (!@caller) {
+			return '';
+		}
+		
+		my $calling_subroutine = $caller[3];
+		
+		# Ignore if subroutine includes _ANON_
+		# This is a workaround for DataStructure.pm::can
+		# DataStructure.pm::_automethod checks if DataStructure.pm::can is called
+		if ($calling_subroutine =~ /_ANON_/) {
+			#notify($ERRORS{'DEBUG'}, 0, "ignoring calling subroutine: $calling_subroutine");
+			next;
+		}
+		else {
+			return $calling_subroutine;
+		}
+	}
+	
+	notify($ERRORS{'WARNING'}, 0, "failed to determine calling subroutine");
+	return '';
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -10139,48 +10161,71 @@ sub get_current_subroutine_name {
 
 =head2 get_affiliation_info
 
- Parameters  : Affiliation ID (optional)
- Returns     : Array
- Description : Returns a hash reference containing information from the affiliation
-               table.
-               
-               An optional affiliation ID argument can be supplied. If supplied, only
-               the information for the specified affiliation is returned.
+ Parameters  : $affiliation_identifier (optional)
+ Returns     : hash reference
+ Description : Returns a hash reference containing information from the
+               affiliation table.
                
-               A hash reference is returned. The keys of the hash are the affiliation IDs.
-               Example showing the format of the data structure returned:
+               If no $affiliation_identifier argument is supplied, a hash
+               reference is returned with the hash keys corresponding to the
+               affiliation.id values:
+                  {
+                    1 => {
+                      "dataUpdateText" => "",
+                      "helpaddress" => "vcl_help\@example.edu",
+                      "id" => 1,
+                      "name" => "Local",
+                      "shibname" => undef,
+                      "shibonly" => 0,
+                      "sitewwwaddress" => undef,
+                      "theme" => "default"
+                    },
+                    2 => {
+                      "dataUpdateText" => "",
+                      "helpaddress" => "vcl_help\@example.edu",
+                      "id" => 2,
+                      "name" => "Global",
+                      "shibname" => undef,
+                      "shibonly" => 0,
+                      "sitewwwaddress" => undef,
+                      "theme" => "default"
+                    },
+                    ...
+                  }
                
-               my $affiliation_info = get_affiliation_info();
-               $affiliation_info->{0}
-                  |--{dataUpdateText} = ''
-                  |--{helpaddress} = NULL
-                  |--{name} = 'Global'
-                  |--{shibname} = NULL
-                  |--{shibonly} = '0'
-                  |--{sitewwwaddress} = NULL
-               $affiliation_info->{1}
-                  |--{dataUpdateText} = '<font size="-2">* To update any of these fields, follow the appropriate<br>link under <strong>Related Tools</strong> at the Campus Directory</font>'
-                  |--{helpaddress} = 'vcl_help@blah.edu'
-                  |--{name} = 'University of Blah'
-                  |--{shibname} = 'blah.edu'
-                  |--{shibonly} = '0'
-                  |--{sitewwwaddress} = 'http://vcl.blah.edu'
+               If the $affiliation_identifier argument is supplied, a hash
+               reference is returned which only contains information for the
+               matching affiliation:
+                  {
+                    "dataUpdateText" => "",
+                    "helpaddress" => "vcl_help\@example.edu",
+                    "id" => 2,
+                    "name" => "Global",
+                    "shibname" => undef,
+                    "shibonly" => 0,
+                    "sitewwwaddress" => undef,
+                    "theme" => "default"
+                  }
 
 =cut
 
 sub get_affiliation_info {
+	my ($affiliation_identifier) = @_;
+	
 	# Create the select statement
-	my $select_statement = "
-   SELECT
-	*
-	FROM
-	affiliation
-	";
+	my $select_statement = <<EOF;
+SELECT
+*
+FROM
+affiliation
+EOF
 	
-	# Append a WHERE clause if a affiliation ID argument was supplied
-	my $affiliation_id = shift;
-	if ($affiliation_id) {
-		$select_statement .= "WHERE id = $affiliation_id";
+	# Append a WHERE clause if a affiliation identifier argument was supplied
+	if ($affiliation_identifier && $affiliation_identifier =~ /^\d+$/) {
+		$select_statement .= "WHERE id = $affiliation_identifier";
+	}
+	elsif ($affiliation_identifier) {
+		$select_statement .= "WHERE name = '$affiliation_identifier'";
 	}
 
 	# Call the database select subroutine
@@ -10188,24 +10233,31 @@ sub get_affiliation_info {
 
 	# Check to make sure rows were returned
 	if (!@selected_rows) {
-		notify($ERRORS{'WARNING'}, 0, "unable to retrieve rows from affiliation table");
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve rows from affiliation table");
 		return;
 	}
 	
 	# Transform the array of database rows into a hash
-	my %affiliation_info_hash;
+	my $affiliation_info = {};
 	for my $row (@selected_rows) {
 		my $affiliation_id = $row->{id};
 		
 		for my $key (keys %$row) {
-			next if $key eq 'id';
 			my $value = $row->{$key};
-			$affiliation_info_hash{$affiliation_id}{$key} = $value;
+			$affiliation_info->{$affiliation_id}{$key} = $value;
 		}
 	}
 	
-	#notify($ERRORS{'DEBUG'}, 0, "retrieved affiliation info:\n" . format_data(\%affiliation_info_hash));
-	return \%affiliation_info_hash;
+	if ($affiliation_identifier) {
+		my $affiliation_id = (keys %$affiliation_info)[0];
+		$affiliation_info = $affiliation_info->{$affiliation_id};
+		notify($ERRORS{'DEBUG'}, 0, "retrieved info for affiliation $affiliation_identifier:\n" . format_data($affiliation_info));
+		return $affiliation_info;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "retrieved affiliation info:\n" . format_data($affiliation_info));
+		return $affiliation_info;
+	}
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -12684,7 +12736,7 @@ EOF
 	# Check to make 1 sure row was returned
 	if (!@selected_rows) {
 		notify($ERRORS{'OK'}, 0, "variable '$variable_name' is not set in the database") if $show_warnings;
-		return 0;
+		return;
 	}
 	elsif (@selected_rows > 1) {
 		notify($ERRORS{'WARNING'}, 0, "unable to get value of variable '$variable_name', multiple rows exist in the database for variable:\n" . format_data(\@selected_rows));
@@ -12845,13 +12897,6 @@ sub set_variable {
 		}
 	}
 	
-	# Escape all backslashes
-	$database_value =~ s/\\/\\\\/g;
-	
-	# Escape all single quote characters with a backslash
-	#   or else the SQL statement will fail becuase it is wrapped in single quotes
-	$database_value =~ s/'/\\'/g;
-	
 	# Assemble an insert statement, if the variable already exists, update the existing row
 	my $insert_statement .= <<"EOF";
 INSERT INTO variable