blob: 6aaf0ce12c5d1b9857295ffeb43e469948215e31 [file] [log] [blame]
#!/usr/bin/perl -w
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################
# $Id: image.pm 1945 2008-12-11 20:58:08Z fapeeler $
##############################################################################
=head1 NAME
VCL::image - Perl module for the VCL image state
=head1 SYNOPSIS
use VCL::image;
use VCL::utils;
# Set variables containing the IDs of the request and reservation
my $request_id = 5;
my $reservation_id = 6;
# Call the VCL::utils::get_request_info subroutine to populate a hash
my %request_info = get_request_info($request_id);
# Set the reservation ID in the hash
$request_info{RESERVATIONID} = $reservation_id;
# Create a new VCL::image object based on the request information
my $image = VCL::image->new(%request_info);
=head1 DESCRIPTION
This module supports the VCL "image" state.
=cut
##############################################################################
package VCL::image;
# Specify the lib path using FindBin
use FindBin;
use lib "$FindBin::Bin/..";
# Configure inheritance
use base qw(VCL::Module::State);
# Specify the version of this module
our $VERSION = '2.00';
# Specify the version of Perl to use
use 5.008000;
use strict;
use warnings;
use diagnostics;
use VCL::utils;
##############################################################################
=head1 OBJECT METHODS
=cut
#/////////////////////////////////////////////////////////////////////////////
=head2 process
Parameters : $request_data_hash_reference
Returns : 1 if successful, 0 otherwise
Description : Processes a reservation in the timout state. You must pass this
method a reference to a hash containing request data.
=cut
sub process {
my $self = shift;
my $request_id = $self->data->get_request_id();
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_preferredname = $self->data->get_user_preferred_name();
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_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();
# 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, "VCL IMAGE Creation Started: $image_name", $body, $affiliation_helpaddress);
# Make sure image does not exist in the repository
my $image_already_exists = $self->provisioner->does_image_exist();
if ($image_already_exists) {
notify($ERRORS{'CRITICAL'}, 0, "image $image_name already exists in the repository");
$self->image_creation_failed();
}
elsif (!defined($image_already_exists)) {
notify($ERRORS{'CRITICAL'}, 0, "image $image_name already partially exists in the repository");
$self->image_creation_failed();
}
else {
notify($ERRORS{'OK'}, 0, "image $image_name does not exist in the repository");
}
# 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);
# Call the create image subroutine in utils.pm
my $create_image_result;
if ($computer_type eq "blade" && $self->os) {
$create_image_result = 1;
notify($ERRORS{'OK'}, 0, "OS modularization supported, beginning OS module capture prepare");
if (!($create_image_result = $self->os->capture_prepare())) {
notify($ERRORS{'WARNING'}, 0, "OS module capture prepare failed");
}
notify($ERRORS{'OK'}, 0, "beginning provisioning module capture prepare");
if ($create_image_result && !($create_image_result = $self->provisioner->capture_prepare())) {
notify($ERRORS{'WARNING'}, 0, "provisioning module capture prepare failed");
}
notify($ERRORS{'OK'}, 0, "beginning OS module capture start");
if ($create_image_result && !($create_image_result = $self->os->capture_start())) {
notify($ERRORS{'WARNING'}, 0, "OS module capture start failed");
}
notify($ERRORS{'OK'}, 0, "beginning provisioning module capture monitor");
if ($create_image_result && !($create_image_result = $self->provisioner->capture_monitor())) {
notify($ERRORS{'WARNING'}, 0, "provisioning module capture monitor failed");
}
} ## end if ($computer_type eq "blade" && $self->os)
elsif ($computer_type eq "blade") {
$create_image_result = $self->provisioner->capture_prepare();
if ($create_image_result) {
$create_image_result = $self->provisioner->capture_monitor();
}
}
elsif ($computer_type eq "virtualmachine") {
$create_image_result = $self->provisioner->capture();
}
else {
notify($ERRORS{'CRITICAL'}, 0, "unsupported computer type: $computer_type");
$self->image_creation_failed();
}
# Image creation was successful, proceed to update database tables
if ($create_image_result) {
# Success
notify($ERRORS{'OK'}, 0, "$image_name image files successfully saved");
# Update the request state to completed, laststate to image
if (update_request_state($request_id, "completed", "image")) {
notify($ERRORS{'OK'}, 0, "request state updated to completed, laststate to image");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "unable to update request state to completed, laststate to image");
}
# 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, clear deleted flag
# Set test flag if according to whether this image is new or updated
# Update the image size
my $update_image_statement = "
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
";
# 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");
}
} ## end if ($create_image_result)
# Check if image creation was successful and database tables were successfully updated
# Notify user and admins of the results
if ($create_image_result) {
$self->image_creation_successful($image_size);
}
else {
notify($ERRORS{'CRITICAL'}, 0, "image creation failed, see previous log messages");
$self->image_creation_failed();
}
} ## end sub process
#/////////////////////////////////////////////////////////////////////////////
sub image_creation_successful {
my $self = shift;
my $image_size_old = shift;
my $request_data = $self->data->get_request_data();
my $request_id = $self->data->get_request_id();
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_preferredname = $self->data->get_user_preferred_name();
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_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();
# Send image creation successful email to user
my $body_user = <<"END";
$user_preferredname,
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
mail($user_email, "VCL -- $image_prettyname Image Creation Succeeded", $body_user, $affiliation_helpaddress);
# Send mail to SYSADMIN
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, "VCL IMAGE Creation Completed: $image_name", $body_admin, $affiliation_helpaddress);
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "inserted 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
switch_state($request_data, 'complete', '', 'EOR', '1');
}
else {
notify($ERRORS{'CRITICAL'}, 0, "failed to insert reload request into database for computer id=$computer_id");
# Switch the request and computer states to failed, set log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
notify($ERRORS{'OK'}, 0, "exiting");
exit;
} ## end sub image_creation_successful
#/////////////////////////////////////////////////////////////////////////////
sub image_creation_failed {
my $self = shift;
my $request_data = $self->data->get_request_data();
my $request_id = $self->data->get_request_id();
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_preferredname = $self->data->get_user_preferred_name();
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_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();
# Image process failed
notify($ERRORS{'CRITICAL'}, 0, "$image_name image creation failed");
# Send mail to user
my $body_user = <<"END";
$user_preferredname,
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
mail($user_email, "VCL -- NOTICE DELAY Image Creation $image_prettyname", $body_user, $affiliation_helpaddress);
# Send mail to SYSADMIN
my $body_admin = <<"END";
VCL Image Creation Failed
Request ID: $request_id
Reservation ID: $reservation_id
PID: $$
Image ID: $image_id
Image name: $image_name
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, "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", "image")) {
notify($ERRORS{'OK'}, 0, "request state set to maintenance, laststate to image");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "unable to set request state to maintenance, laststate to image");
}
# Update the computer state to maintenance
if (update_computer_state($computer_id, "maintenance")) {
notify($ERRORS{'OK'}, 0, "$computer_shortname state set to maintenance");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "unable to set $computer_shortname state to maintenance");
}
notify($ERRORS{'OK'}, 0, "exiting");
exit;
} ## end sub image_creation_failed
#/////////////////////////////////////////////////////////////////////////////
1;
__END__
=head1 BUGS and LIMITATIONS
There are no known bugs in this module.
Please report problems to the VCL team (vcl_help@ncsu.edu).
=head1 AUTHOR
Aaron Peeler, aaron_peeler@ncsu.edu
Andy Kurth, andy_kurth@ncsu.edu
=head1 SEE ALSO
L<http://vcl.ncsu.edu>
=cut