blob: edfaa032e70f05d77b9f27f11ac8c8aff748dfe2 [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: reclaim.pm 1953 2008-12-12 14:23:17Z arkurth $
##############################################################################
=head1 NAME
VCL::reclaim - Perl module for the VCL reclaim state
=head1 SYNOPSIS
use VCL::reclaim;
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::reclaim object based on the request information
my $reclaim = VCL::reclaim->new(%request_info);
=head1 DESCRIPTION
This module supports the VCL "reclaim" state.
=cut
##############################################################################
package VCL::reclaim;
# 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 reclaim state. You must pass this
method a reference to a hash containing request data.
=cut
sub process {
my $self = shift;
my ($package, $filename, $line, $sub) = caller(0);
# Store hash variables into local variables
my $request_data = $self->data->get_request_data;
my $request_id = $request_data->{id};
my $request_state_name = $request_data->{state}{name};
my $request_laststate_name = $request_data->{laststate}{name};
my $reservation_id = $request_data->{RESERVATIONID};
my $reservation_remoteip = $request_data->{reservation}{$reservation_id}{remoteIP};
my $computer_type = $request_data->{reservation}{$reservation_id}{computer}{type};
my $computer_id = $request_data->{reservation}{$reservation_id}{computer}{id};
my $computer_shortname = $request_data->{reservation}{$reservation_id}{computer}{SHORTNAME};
my $computer_hostname = $request_data->{reservation}{$reservation_id}{computer}{hostname};
my $computer_ipaddress = $request_data->{reservation}{$reservation_id}{computer}{IPaddress};
my $computer_state_name = $request_data->{reservation}{$reservation_id}{computer}{state}{name};
my $image_os_name = $request_data->{reservation}{$reservation_id}{image}{OS}{name};
my $imagerevision_imagename = $request_data->{reservation}{$reservation_id}{imagerevision}{imagename};
my $user_unityid = $request_data->{user}{unityid};
# Assemble a consistent prefix for notify messages
my $notify_prefix = "req=$request_id, res=$reservation_id:";
# Retrieve next image
# It's possible the results may not get used based on the state of the reservation
my @nextimage;
if($self->predictor->can("get_next_image")){
@nextimage = $self->predictor->get_next_image();
}
else{
notify($ERRORS{'WARNING'}, 0, "$notify_prefix predictor module does not support get_next_image, calling default get_next_image from utils");
@nextimage = get_next_image_default($computer_id);
}
# Assign values to hash for insert reload request
# Not necessary to change local variables for active image
$request_data->{reservation}{$reservation_id}{imagerevision}{imagename} = $nextimage[0];
$request_data->{reservation}{$reservation_id}{image}{id} = $nextimage[1];
$request_data->{reservation}{$reservation_id}{imagerevision}{id} = $nextimage[2];
$request_data->{reservation}{$reservation_id}{imageid} = $nextimage[1];
$request_data->{reservation}{$reservation_id}{imagerevisionid} = $nextimage[2];
my $nextimagename = $nextimage[0];
notify($ERRORS{'OK'}, 0, "$notify_prefix nextimage results imagename=$nextimage[0] imageid=$nextimage[1] imagerevisionid=$nextimage[2]");
# Insert into computerloadlog if request state = timeout
if ($request_state_name =~ /timeout|deleted/) {
insertloadlog($reservation_id, $computer_id, $request_state_name, "reclaim: starting $request_state_name process");
}
insertloadlog($reservation_id, $computer_id, "info", "reclaim: request state is $request_state_name");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: request laststate is $request_laststate_name");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: computer type is $computer_type");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: computer OS is $image_os_name");
# If request laststate = new, nothing needs to be done
if ($request_laststate_name =~ /new/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix request laststate is $request_laststate_name, nothing needs to be done to the computer");
# Proceed to set request to complete and computer to available
}
# Don't attempt to do anything to machines that are currently reloading
elsif ($computer_state_name =~ /maintenance|reloading/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix computer in $computer_state_name state, nothing needs to be done to the computer");
# Proceed to set request to complete
}
# Check the computer type
# Treat blades and virtual machines the same
# The request will either be changed to "reload" or they will be cleaned
# up based on the OS.
# Lab computers only need to have sshd disabled.
elsif ($computer_type =~ /blade|virtualmachine/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix computer type is $computer_type");
# Check if request laststate is reserved
# This is the only case where computers will be cleaned and not reloaded
if ($request_laststate_name =~ /reserved/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix request laststate is $request_laststate_name, attempting to clean up computer for next user");
# Check the image OS type and clean up computer accordingly
if ($image_os_name =~ /^(win|vmwarewin|vmwareesxwin)/) {
# Loaded Windows image needs to be cleaned up
notify($ERRORS{'OK'}, 0, "$notify_prefix attempting steps to clean up loaded $image_os_name image");
# Remove user
if (del_user($computer_shortname, $user_unityid, $computer_type, $image_os_name)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix user $user_unityid removed from $computer_shortname");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: removed user");
}
else {
notify($ERRORS{'WARNING'}, 0, "$notify_prefix could not remove user $user_unityid from $computer_shortname, proceed to forced reload");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id imagename=$nextimagename");
# 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, "$notify_prefix failed to insert reload request into database for computer id=$computer_id imagename=$nextimagename");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
exit;
} ## end else [ if (del_user($computer_shortname, $user_unityid...
# Disable RDP
if (remotedesktopport($computer_shortname, "DISABLE")) {
notify($ERRORS{'OK'}, 0, "$notify_prefix remote desktop disabled on $computer_shortname");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: disabled RDP");
}
else {
notify($ERRORS{'WARNING'}, 0, "$notify_prefix remote desktop could not be disabled on $computer_shortname");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id imagename=$nextimagename");
# Switch the request state to complete, leave the computer state as is, log ending to EOR, exit
switch_state($request_data, 'complete', '', 'EOR', '1');
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix failed to insert reload request into database for computer id=$computer_id imagename=$nextimagename");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
exit;
} ## end else [ if (remotedesktopport($computer_shortname,...
## Stop Tivoli Monitoring
#if (system_monitoring($computer_shortname, $imagerevision_imagename, "stop", "ITM")) {
# notify($ERRORS{'OK'}, 0, "$notify_prefix ITM monitoring disabled");
#}
} ## end if ($image_os_name =~ /^(win|vmwarewin|vmwareesxwin)/)
elsif ($image_os_name =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9])/) {
# Loaded Linux image needs to be cleaned up
notify($ERRORS{'OK'}, 0, "$notify_prefix attempting steps to clean up loaded $image_os_name image");
# Make sure user is not connected
if (isconnected($computer_shortname, $computer_type, $reservation_remoteip, $image_os_name, $computer_ipaddress)) {
notify($ERRORS{'WARNING'}, 0, "$notify_prefix user $user_unityid is connected to $computer_shortname, vm will be reloaded");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id imagename=$nextimagename");
# Switch the request state to complete, leave the computer state as is, set log ending to EOR, exit
switch_state($request_data, 'complete', '', 'EOR', '1');
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix failed to insert reload request into database for computer id=$computer_id");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
exit;
} ## end if (isconnected($computer_shortname, $computer_type...
# User is not connected, delete the user
if (del_user($computer_shortname, $user_unityid, $computer_type, $image_os_name)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix user $user_unityid removed from $computer_shortname");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: removed user");
}
else {
notify($ERRORS{'OK'}, 0, "$notify_prefix user $user_unityid could not be removed from $computer_shortname, vm will be reloaded");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id");
# Switch the request state to complete, leave the computer state as is, log ending to EOR, exit
switch_state($request_data, 'complete', '', 'EOR', '1');
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix failed to insert reload request into database for computer id=$computer_id");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
exit;
} ## end else [ if (del_user($computer_shortname, $user_unityid...
} ## end elsif ($image_os_name =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9])/) [ if ($image_os_name =~ /^(win|vmwarewin|vmwareesxwin)/)
else {
# Unknown image type
notify($ERRORS{'WARNING'}, 0, "$notify_prefix unsupported image OS detected: $image_os_name, reload will be attempted");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id");
# Switch the request state to complete, leave the computer state as is, log ending to EOR, exit
switch_state($request_data, 'complete', '', 'EOR', '1');
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix failed to insert reload request into database for computer id=$computer_id");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
exit;
} ## end else [ if ($image_os_name =~ /^(win|vmwarewin|vmwareesxwin)/) [elsif ($image_os_name =~ /^(rh[0-9]image|rhel[0-9]|fc[0-9]image|rhfc[0-9]|rhas[0-9])/)
} ## end if ($request_laststate_name =~ /reserved/)
else {
# Either blade or vm, request laststate is not reserved
# Computer should be reloaded
notify($ERRORS{'OK'}, 0, "$notify_prefix request laststate is $request_laststate_name, reload will be attempted");
# Insert reload request data into the datbase
if (insert_reload_request($request_data)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix inserted reload request into database for computer id=$computer_id imagename=$nextimagename");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix failed to insert reload request into database for computer id=$computer_id imagename=$nextimagename");
# Switch the request and computer states to failed, log ending to failed, exit
switch_state($request_data, 'failed', 'failed', 'failed', '1');
}
# Switch the request state to complete, leave the computer state as is, log ending to EOR, exit
switch_state($request_data, 'complete', '', 'EOR', '1');
} ## end else [ if ($request_laststate_name =~ /reserved/)
} ## end elsif ($computer_type =~ /blade|virtualmachine/) [ if ($request_laststate_name =~ /new/)
elsif ($computer_type =~ /lab/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix computer type is $computer_type");
# Display a warning if laststate is not inuse, or reserved
# but still try to clean up computer
if ($request_laststate_name =~ /inuse|reserved/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix request laststate is $request_laststate_name");
}
else {
notify($ERRORS{'WARNING'}, 0, "$notify_prefix laststate for request is $request_laststate_name, this shouldn't happen");
}
# Disable sshd
if (disablesshd($computer_ipaddress, $user_unityid, $reservation_remoteip, "timeout", $image_os_name)) {
notify($ERRORS{'OK'}, 0, "$notify_prefix sshd on $computer_shortname $computer_ipaddress has been disabled");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: disabled sshd");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix unable to disable sshd on $computer_shortname $computer_ipaddress");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: unable to disable sshd");
# Attempt to put lab computer in failed state if not already in maintenance
if ($computer_state_name =~ /maintenance/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix $computer_shortname in $computer_state_name state, skipping state update to failed");
}
else {
if (update_computer_state($computer_id, "failed")) {
notify($ERRORS{'OK'}, 0, "$notify_prefix $computer_shortname put into failed state");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: set computer state to failed");
}
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix unable to put $computer_shortname into failed state");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: unable to set computer state to failed");
}
} ## end else [ if ($computer_state_name =~ /maintenance/)
} ## end else [ if (disablesshd($computer_ipaddress, $user_unityid...
} ## end elsif ($computer_type =~ /lab/) [ if ($request_laststate_name =~ /new/)
# Unknown computer type, this shouldn't happen
else {
notify($ERRORS{'CRITICAL'}, 0, "$notify_prefix unsupported computer type: $computer_type, not blade, virtualmachine, or lab");
insertloadlog($reservation_id, $computer_id, "info", "reclaim: unsupported computer type: $computer_type");
}
# Update the request state to complete and exit
# Set the computer state to available if it isn't in the maintenance or reloading state
if ($computer_state_name =~ /maintenance|reloading/) {
notify($ERRORS{'OK'}, 0, "$notify_prefix $computer_shortname in $computer_state_name state, skipping state update to available");
switch_state($request_data, 'complete', '', '', '1');
}
else {
switch_state($request_data, 'complete', 'available', '', '1');
}
} ## end sub process
#/////////////////////////////////////////////////////////////////////////////
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
=======