sub process()

in managementnode/lib/VCL/image.pm [89:241]


sub process {
	my $self = shift;
	
	# Check if image OS needs to be updated
	# Do this before retrieving data because it may change
	if ($self->provisioner->can('check_image_os')) {
		if (!$self->provisioner->check_image_os()) {
			return;
		}
	}
	
	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 $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_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_type              = $self->data->get_computer_type();
	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) {
		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 already exist
	my $image_already_exists = $self->provisioner->does_image_exist();
	if ($image_already_exists) {
		notify($ERRORS{'CRITICAL'}, 0, "image $image_name already exists");
		$self->reservation_failed();
	}
	elsif (!defined($image_already_exists)) {
		notify($ERRORS{'CRITICAL'}, 0, "failed to determine if image $image_name already exists");
		$self->reservation_failed();
	}
	else {
		notify($ERRORS{'OK'}, 0, "image $image_name does not exist");
	}
	
	# Get the current timestamp
	# This will be used for image.lastupdate, imagerevision.datecreated and currentimage.txt
	my $timestamp = makedatestring();
	$self->data->set_image_lastupdate($timestamp);
	$self->data->set_imagerevision_date_created($timestamp);
	
	# Check if capture() subroutine has been implemented by the provisioning module
	if (!$self->provisioner->can("capture")) {
		notify($ERRORS{'CRITICAL'}, 0, "failed to capture image, " . ref($self->provisioner) . " provisioning module does not implement a 'capture' subroutine");
		$self->reservation_failed();
	}
	
	# If this was a checkpoint, make sure the provisioning module implements a power_on subroutine
	if ($request_state_name eq 'checkpoint' && !$self->provisioner->can('power_on')) {
		notify($ERRORS{'CRITICAL'}, 0, "failed to create checkpoint of image, " . ref($self->provisioner) . " provisioning module does not implement a 'power_on' subroutine, won't be able to power the computer back on after image is captured in order to return it to a usable state for the user");
		$self->reservation_failed();
	}
	
	# Make sure post_reservation scripts get executed before capturing computer
	# This is normally done by reclaim.pm, but this won't be called in the following capture/reload sequence
	$self->os->post_reservation();
	
	# Call the provisioning modules's capture() subroutine
	# The provisioning module should do everything necessary to capture the image
	notify($ERRORS{'OK'}, 0, "calling provisioning module's capture() subroutine");
	if ($self->provisioner->capture()) {
		notify($ERRORS{'OK'}, 0, "$image_name image was successfully captured by the provisioning module");
	}
	else {
		notify($ERRORS{'WARNING'}, 0, "$image_name image failed to be captured by provisioning module");
		$self->reservation_failed();
	}
	
	# If this was a checkpoint, power the computer back on and wait for it to respond
	if ($request_state_name eq 'checkpoint') {
		if (!$self->provisioner->power_on()) {
			notify($ERRORS{'CRITICAL'}, 0, "failed to create checkpoint of image, failed to power $computer_shortname back on after image was captured");
			$self->reservation_failed();
		}
		
		# Check if the OS module implements a post_load subroutine
		if ($self->os->can('post_load')) {
			if ($self->os->post_load()) {
				# Add a line to currentimage.txt indicating post_load has run
				$self->os->set_post_load_status();
			}
			else {
				notify($ERRORS{'CRITICAL'}, 0, "failed to create checkpoint of image, unable to complete OS post-load tasks on $computer_shortname after image was captured and computer was powered on");
				$self->reservation_failed();
			}
		}
		
		if (!$self->os->reserve()) {
			notify($ERRORS{'CRITICAL'}, 0, "failed to create checkpoint of image, unable to complete OS reserve tasks on $computer_shortname");
			$self->reservation_failed();
		}
		
		# Disable user connection checking for this request to prevent timeouts
		update_request_checkuser($request_id, 0);
	}
	
	# Get the new image size
	my $image_size_new;
	if ($image_size_new = $self->provisioner->get_image_size($image_name)) {
		notify($ERRORS{'OK'}, 0, "size of $image_name: $image_size_new");
	}
	else {
		notify($ERRORS{'WARNING'}, 0, "unable to retrieve size of new revision: $image_name, old size will be used");
		$image_size_new = $image_size;
	}
	$self->data->set_image_size($image_size_new);
	
	# Update image timestamp, image size, clear deleted flag
	my $update_image_statement = <<EOF;
UPDATE
image,
imagerevision
SET
image.lastupdate = '$timestamp',
image.deleted = '0',
image.size = '$image_size_new',
image.name = '$image_name',
imagerevision.deleted = '0',
imagerevision.datecreated = '$timestamp'
WHERE
image.id = $image_id
AND imagerevision.id = $imagerevision_id
EOF
	
	# Execute the image update statement
	if (database_execute($update_image_statement)) {
		notify($ERRORS{'OK'}, 0, "image and imagerevision tables updated for image=$image_id, imagerevision=$imagerevision_id, name=$image_name, lastupdate=$timestamp, deleted=0, size=$image_size_new");
	}
	else {
		notify($ERRORS{'WARNING'}, 0, "image table could not be updated for image=$image_id");
	}
	
	# Call the OS module's post_capture subroutine
	# This call might be relocated to each provisioning module's process subroutine like the call to pre_capture
	$self->os->post_capture();
	
	$self->reservation_successful($image_size);
} ## end sub process